Now you can download a copy of these docs so you can use them offline! Download now
ConnectionManager.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2011. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include "NetworkTables/ConnectionManager.h" 00008 00009 #include "NetworkTables/Connection.h" 00010 #include "NetworkTables/InterfaceConstants.h" 00011 #include "Synchronized.h" 00012 #include "WPIErrors.h" 00013 00014 #include <inetLib.h> 00015 #include <selectLib.h> 00016 #include <semLib.h> 00017 #include <sockLib.h> 00018 #include <taskLib.h> 00019 #include <usrLib.h> 00020 00021 #define kPort 1735 00022 00023 namespace NetworkTables 00024 { 00025 00026 ConnectionManager *ConnectionManager::_instance = NULL; 00027 00028 ConnectionManager::ConnectionManager() : 00029 m_isServer(true), 00030 m_listener("NetworkTablesListener", (FUNCPTR)InitListenTask), 00031 m_run(true), 00032 m_listenSocket(-1), 00033 m_connectionLock(NULL) 00034 { 00035 AddToSingletonList(); 00036 m_connectionLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 00037 m_listener.Start((UINT32)this); 00038 } 00039 00040 ConnectionManager::~ConnectionManager() 00041 { 00042 close(m_listenSocket); 00043 _instance->m_run = false; 00044 while(_instance->m_listener.Verify()) 00045 taskDelay(10); 00046 semTake(m_connectionLock, WAIT_FOREVER); 00047 m_connections.clear(); 00048 semDelete(m_connectionLock); 00049 } 00050 00051 ConnectionManager *ConnectionManager::GetInstance() 00052 { 00053 if (_instance == NULL) 00054 _instance = new ConnectionManager(); 00055 return _instance; 00056 } 00057 00058 int ConnectionManager::ListenTaskRun() 00059 { 00060 struct sockaddr_in serverAddr; 00061 int sockAddrSize = sizeof(serverAddr); 00062 bzero((char *)&serverAddr, sockAddrSize); 00063 serverAddr.sin_len = (u_char)sockAddrSize; 00064 serverAddr.sin_family = AF_INET; 00065 serverAddr.sin_port = htons(kPort); 00066 serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); 00067 00068 // Create the socket. 00069 if ((m_listenSocket = socket(AF_INET, SOCK_STREAM, 0)) == ERROR) 00070 { 00071 printErrno(0); 00072 wpi_setGlobalWPIErrorWithContext(ResourceAlreadyAllocated, "Could not create NetworkTables server socket"); 00073 return -1; 00074 } 00075 00076 // Set the TCP socket so that it can be reused if it is in the wait state. 00077 int reuseAddr = 1; 00078 setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseAddr, sizeof(reuseAddr)); 00079 00080 // Bind socket to local address. 00081 if (bind(m_listenSocket, (struct sockaddr *)&serverAddr, sockAddrSize) == ERROR) 00082 { 00083 close(m_listenSocket); 00084 printErrno(0); 00085 wpi_setGlobalWPIErrorWithContext(ResourceAlreadyAllocated, "Could not bind NetworkTables server socket"); 00086 return -1; 00087 } 00088 00089 if (listen(m_listenSocket, 1) == ERROR) 00090 { 00091 close(m_listenSocket); 00092 printErrno(0); 00093 wpi_setGlobalWPIErrorWithContext(ResourceAlreadyAllocated, "Could not listen on NetworkTables server socket"); 00094 return -1; 00095 } 00096 00097 struct timeval timeout; 00098 // Check for a shutdown once per second 00099 timeout.tv_sec = 1; 00100 timeout.tv_usec = 0; 00101 while (m_run) 00102 { 00103 fd_set fdSet; 00104 00105 FD_ZERO(&fdSet); 00106 FD_SET(m_listenSocket, &fdSet); 00107 if (select(FD_SETSIZE, &fdSet, NULL, NULL, &timeout) > 0) 00108 { 00109 if (FD_ISSET(m_listenSocket, &fdSet)) 00110 { 00111 struct sockaddr clientAddr; 00112 int clientAddrSize; 00113 int connectedSocket = accept(m_listenSocket, &clientAddr, &clientAddrSize); 00114 if (connectedSocket == ERROR) 00115 continue; 00116 00117 // TODO: Linger option? 00118 AddConnection(new Connection(connectedSocket)); 00119 } 00120 } 00121 } 00122 return 0; 00123 } 00124 00125 void ConnectionManager::AddConnection(Connection *connection) 00126 { 00127 { 00128 Synchronized sync(m_connectionLock); 00129 if (!m_connections.insert(connection).second) 00130 { 00131 wpi_setGlobalWPIErrorWithContext(ResourceAlreadyAllocated, "Connection object already exists"); 00132 return; 00133 } 00134 } 00135 connection->Start(); 00136 } 00137 00138 void ConnectionManager::RemoveConnection(Connection *connection) 00139 { 00140 { 00141 Synchronized sync(m_connectionLock); 00142 m_connections.erase(connection); 00143 } 00144 delete connection; 00145 } 00146 00147 }
Generated on Thu Jan 12 2012 22:35:18 for WPILibC++ by
1.7.1