00001
00002
00003
00004
00005
00006
00007
00008 #include "WOscTcpServer.h"
00009
00010 #if OS_IS_LINUX == 1 || OS_IS_MACOSX == 1 || OS_IS_CYGWIN == 1
00011
00012 #include <fcntl.h>
00013 #include <sys/socket.h>
00014
00015 #define WOSC_TCP_SERVER_NUM_PENDING_CONNECTIONS 5
00016
00017 void
00018 WOscTcpServerHandler::ReceiveThread()
00019 {
00020 WOSC_DBG_PRT("Client thread entered.");
00021 WOscTcpHandler::ReceiveThread();
00022
00023
00024
00025 if ( GetServer()->UnRegister(this) ) {
00026 close(GetSocketID());
00027 int ret = pthread_detach(GetRxThreadID());
00028 if ( ret ) {
00029 WOSC_ERR_PRT("Client detach failed.");
00030 } else {
00031 WOSC_DBG_PRT("Client thread detached.");
00032 }
00033 delete this;
00034 }
00035 WOSC_DBG_PRT("Client thread terminated.");
00036 }
00037
00038
00039
00040
00041 void*
00042 wosc_tcp_server_thread(void* argument)
00043 {
00044 WOSC_DBG_PRT("Server thread entered.");
00045 WOscTcpServer* server = static_cast<WOscTcpServer*>(argument);
00046 server->Accept();
00047 WOSC_DBG_PRT("Server thread terminated.");
00048 pthread_exit(NULL);
00049 }
00050
00051 WOscTcpServer::WOscTcpServer(bool threading)
00052 {
00053 m_socketServer = -1;
00054 m_threading = threading;
00055 m_serverThreadID = 0;
00056 pthread_mutex_init(&m_connectionsMutex, NULL);
00057 }
00058
00059 WOscTcpServer::~WOscTcpServer()
00060 {
00061 Stop();
00062 pthread_mutex_destroy(&m_connectionsMutex);
00063 }
00064
00065 WOscTcpServer::Error
00066 WOscTcpServer::Bind(int port, in_addr_t addr)
00067 {
00068 if ( m_socketServer >= 0 )
00069 return WOS_TCPS_ERR_ALREADY_BOUND;
00070 if ( m_threading && m_serverThreadID )
00071 return WOS_TCPS_ERR_SERVER_RUNNING;
00072
00073
00074 int socket_server = socket(AF_INET, SOCK_STREAM, 0);
00075 if ( socket_server < 0)
00076 return WOS_TCPS_ERR_OPEN_SOCKET;
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 int on = 1;
00090 if (setsockopt(socket_server, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
00091
00092 }
00093
00094
00095 struct sockaddr_in address_server;
00096 bzero(&address_server, sizeof(address_server));
00097 address_server.sin_family = AF_INET;
00098 address_server.sin_addr.s_addr = htonl(addr);
00099 address_server.sin_port = htons(port);
00100
00101 if (bind(socket_server, (struct sockaddr *) &address_server,
00102 sizeof(address_server)) < 0) {
00103 close(socket_server);
00104 return WOS_TCPS_ERR_BIND;
00105 }
00106
00107 if ( listen(socket_server, WOSC_TCP_SERVER_NUM_PENDING_CONNECTIONS) < 0) {
00108 close(socket_server);
00109 return WOS_TCPS_ERR_LISTEN;
00110 }
00111 m_socketServer = socket_server;
00112
00113
00114 if ( m_threading ) {
00115
00116 int ret = pthread_create(&m_serverThreadID, NULL, wosc_tcp_server_thread, this);
00117 if ( ret ) {
00118 close(m_socketServer);
00119 m_socketServer = -1;
00120 m_serverThreadID = 0;
00121 return WOS_TCPS_ERR_CREATE_THREAD;
00122 }
00123 } else {
00124
00125
00126 if (fcntl(m_socketServer, F_SETFL, fcntl(m_socketServer, F_GETFL) | O_NONBLOCK) < 0) {
00127 close(m_socketServer);
00128 m_socketServer = -1;
00129 return WOS_TCPS_ERR_SET_NONBLOCKING;
00130 }
00131 }
00132
00133 return WOS_TCPS_ERR_NO_ERR;
00134 }
00135
00136 WOscTcpServer::Error
00137 WOscTcpServer::Accept()
00138 {
00139 if ( m_socketServer < 0 )
00140 return WOS_TCPS_ERR_NO_SERVER_SOCKET;
00141 for (;;) {
00142
00143
00144 int socket_client;
00145 struct sockaddr_in address_client;
00146 socklen_t client_address_size = sizeof(address_client);
00147
00148
00149 socket_client = accept(m_socketServer, (struct sockaddr *) &address_client, &client_address_size);
00150
00151 if (socket_client < 0) {
00152
00153 WOSC_ERR_PRT("socket_client < 0");
00154 return WOS_TCPS_ERR_ACCEPT;
00155 }
00156
00157
00158 WOscTcpServerHandler* handler;
00159 WOscTcpHandler::Error err = SetupHandlerForNewConnection(&handler, socket_client, TheNetReturnAddress(address_client));
00160 if ( err == WOscTcpHandler::WOS_ERR_NO_ERROR ) {
00161
00162
00163 Register(handler);
00164 } else {
00165
00166 close(socket_client);
00167 }
00168
00169 }
00170 return WOS_TCPS_ERR_NO_ERR;
00171 }
00172
00173
00174 WOscTcpServer::Error
00175 WOscTcpServer::Stop()
00176 {
00177
00178 if ( m_socketServer < 0 )
00179 return WOS_TCPS_ERR_NO_SERVER_SOCKET;
00180
00181 WOSC_DBG_PRT("Stopping server thread.");
00182
00183 if ( m_threading && m_serverThreadID ) {
00184 WOSC_DBG_PRT("Cancelling server thread.");
00185 int ret = pthread_cancel(m_serverThreadID);
00186 if ( ret ) {
00187 WOSC_ERR_PRT("Server thread cancel failed.");
00188 }
00189 void* threadReturn = NULL;
00190 ret = pthread_join(m_serverThreadID, &threadReturn);
00191 if ( ret ) {
00192 WOSC_ERR_PRT("Server thread join failed.");
00193 }
00194 m_serverThreadID = 0;
00195 }
00196
00197
00198
00199
00200 pthread_mutex_lock(&m_connectionsMutex);
00201
00202 std::vector<WOscTcpServerHandler*> openClients = m_connections;
00203 m_connections.clear();
00204 pthread_mutex_unlock(&m_connectionsMutex);
00205
00206
00207
00208 for ( int i = openClients.size()-1; i >= 0; i-- ) {
00209 WOSC_DBG_PRT("Terminating client connection "<<i<<" and joining thread.");
00210
00211
00212 openClients[i]->Stop();
00213 close(openClients[i]->GetSocketID());
00214 delete openClients[i];
00215 }
00216
00217 WOSC_DBG_PRT("Closing server socket.");
00218
00219 close(m_socketServer);
00220 m_socketServer = -1;
00221
00222
00223 return WOS_TCPS_ERR_NO_ERR;
00224 }
00225
00226 const char*
00227 WOscTcpServer::GetErrStr(Error err)
00228 {
00229 switch (err) {
00230 case WOS_TCPS_ERR_NO_ERR:
00231 return "No error.";
00232 case WOS_TCPS_ERR_OPEN_SOCKET:
00233 return "WOS_TCPS_ERR_OPEN_SOCKET";
00234 case WOS_TCPS_ERR_BIND:
00235 return "WOS_TCPS_ERR_BIND";
00236 case WOS_TCPS_ERR_CREATE_THREAD:
00237 return "WOS_TCPS_ERR_CREATE_THREAD";
00238 case WOS_TCPS_ERR_NO_SERVER_SOCKET:
00239 return "WOS_TCPS_ERR_NO_SERVER_SOCKET";
00240 case WOS_TCPS_ERR_ACCEPT:
00241 return "WOS_TCPS_ERR_ACCEPT";
00242 case WOS_TCPS_ERR_SET_NONBLOCKING:
00243 return "WOS_TCPS_ERR_SET_NONBLOCKING";
00244 case WOS_TCPS_ERR_ALREADY_BOUND:
00245 return "WOS_TCPS_ERR_ALREADY_BOUND";
00246 case WOS_TCPS_ERR_SERVER_RUNNING:
00247 return "WOS_TCPS_ERR_SERVER_RUNNING";
00248 default:
00249 return "Unknown or undocumented error.";
00250 }
00251 }
00252
00253 #elif OS_IS_WIN32 == 1
00254
00255 # warning "WOscTcpServer not supported on this platform"
00256 #endif