00001
00002 #include "lugre_prefix.h"
00003 #include "lugre_net.h"
00004
00005 #include <errno.h>
00006
00007 #ifdef WIN32
00008 #include <winsock2.h>
00009 #else
00010 #include <netdb.h>
00011 #include <sys/types.h>
00012 #include <netinet/in.h>
00013 #include <sys/socket.h>
00014 #include <arpa/inet.h>
00015 #endif
00016
00017 #include <string.h>
00018
00019
00020 #ifdef WIN32
00021 #ifndef socklen_t
00022 #define socklen_t int
00023 #endif
00024 #endif
00025
00026
00027
00028 namespace Lugre {
00029
00030 fd_set sSelectSet_Read;
00031 fd_set sSelectSet_Write;
00032 fd_set sSelectSet_Except;
00033
00034 #define kConMinRecvSpace (1024*32)
00035 #define kConStartSpace (1024*32*2)
00036
00037 #ifndef WIN32
00038 void closesocket(int socket){
00039 close(socket);
00040 }
00041 #endif
00042
00043
00044 #define kMaxUDPMsgLen 65507 // TODO : unhardcode this, should be in some header ?!?
00045
00046
00047
00048
00049 cNet::cNet () { PROFILE
00050 #ifdef WIN32
00051 WSADATA wsaData;
00052 WSAStartup( MAKEWORD( 2, 0 ), &wsaData );
00053 #endif
00054 }
00055
00056 cNet::~cNet () { PROFILE
00057 #ifdef WIN32
00058 WSACleanup();
00059 #endif
00060
00061 for (std::set<cNetListener*>::iterator itor=mlListener.begin();itor!=mlListener.end(); ++itor) delete (*itor);
00062 for (std::set<cConnection*>::iterator itor=mlCons.begin(); itor!=mlCons.end(); ++itor) delete (*itor);
00063 for (std::set<cConnection*>::iterator itor=mlDeadCons.begin();itor!=mlDeadCons.end(); ++itor) delete (*itor);
00064 for (std::set<cConnection*>::iterator itor=mlDyingCons.begin();itor!=mlDyingCons.end(); ++itor) delete (*itor);
00065 }
00066
00067 void cNet::Step () { PROFILE
00068
00069 for (std::set<cNetListener*>::iterator itor=mlListener.begin();itor!=mlListener.end();++itor) (*itor)->Step();
00070
00071
00072 if (mlCons.size() > 0) {
00073
00074 int res,mysocket,imax=0;
00075 timeval timeout;
00076 timeout.tv_sec = 0;
00077 timeout.tv_usec = 0;
00078
00079 FD_ZERO(&sSelectSet_Read);
00080 FD_ZERO(&sSelectSet_Write);
00081 FD_ZERO(&sSelectSet_Except);
00082
00083 for (std::set<cConnection*>::iterator itor=mlCons.begin(); itor!=mlCons.end(); ++itor) {
00084 mysocket = (*itor)->miSocket;
00085 if (mysocket != INVALID_SOCKET) {
00086 if (imax < mysocket)
00087 imax = mysocket;
00088 FD_SET((unsigned int)mysocket,&sSelectSet_Read);
00089 FD_SET((unsigned int)mysocket,&sSelectSet_Write);
00090 FD_SET((unsigned int)mysocket,&sSelectSet_Except);
00091 }
00092 }
00093
00094 res = select(imax+1,&sSelectSet_Read,&sSelectSet_Write,&sSelectSet_Except,&timeout);
00095
00096 for (std::set<cConnection*>::iterator itor=mlCons.begin(); itor!=mlCons.end(); ++itor) if ((*itor)->miSocket != INVALID_SOCKET) {
00097 (*itor)->Step( FD_ISSET((unsigned int)(*itor)->miSocket,&sSelectSet_Read) != 0,
00098 FD_ISSET((unsigned int)(*itor)->miSocket,&sSelectSet_Write) != 0,
00099 FD_ISSET((unsigned int)(*itor)->miSocket,&sSelectSet_Except) != 0 );
00100 }
00101 }
00102
00103 for (std::set<cBroadcast*>::iterator itor=mlBroadCasts.begin();itor!=mlBroadCasts.end();++itor) (*itor)->Step();
00104
00105
00106 for (std::set<cConnection*>::iterator itor=mlDyingCons.begin();itor!=mlDyingCons.end();++itor) {
00107 mlCons.erase(*itor);
00108 mlDeadCons.insert(*itor);
00109 for (std::set<cBroadcast*>::iterator itor2=mlBroadCasts.begin();itor2!=mlBroadCasts.end();++itor2)
00110 (*itor2)->mlCons.erase(*itor);
00111 }
00112 mlDyingCons.clear();
00113
00114 }
00115
00116
00117 const bool cConnection::IsConnected() {
00118 return miSocket != INVALID_SOCKET;
00119 }
00120
00121
00124 unsigned int cNet::GetHostByName (const char *szHost) { PROFILE
00125 assert(szHost);
00126 if (!szHost) return 0;
00127
00128 hostent* h;
00129 h = gethostbyname(szHost);
00130 if(h){
00131 unsigned int res = *((uint32 *)h->h_addr);
00132 if (res == INADDR_NONE) return 0;
00133 return res;
00134 } else if(inet_addr(szHost) != INADDR_NONE){
00135 return inet_addr(szHost);
00136 } else {
00137 return 0;
00138 }
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00165 int cNet::ConnectSocket (uint32 iIP,const int iPort) { PROFILE
00166 if (iIP == 0) return INVALID_SOCKET;
00167
00168 sockaddr_in sAddr;
00169 sAddr.sin_family = AF_INET;
00170 sAddr.sin_port = htons(iPort);
00171 sAddr.sin_addr.s_addr = iIP;
00172
00173
00174
00175 int iSocket;
00176 iSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00177
00178 if (iSocket == INVALID_SOCKET) {
00179 printf("cNet::ConnectSocket : socket creation failed (port:%d)\n",iPort);
00180 return INVALID_SOCKET;
00181 }
00182 if (connect(iSocket,(const sockaddr*)&sAddr,sizeof(sAddr)) == SOCKET_ERROR) {
00183 printf("cNet::ConnectSocket : socket connect failed (port:%d)\n",iPort);
00184 return INVALID_SOCKET;
00185 }
00186
00187 return iSocket;
00188 }
00189
00190 bool cNet::IsInvalidSocket (const int iSocket) { return iSocket == INVALID_SOCKET; }
00191 void cNet::CloseSocket (const int iSocket) { closesocket(iSocket); }
00192 int cNet::Send (const int iSocket,const char* pBuffer,const int iBufferSize,const int iFlags) {
00193 return send(iSocket,pBuffer,iBufferSize,iFlags);
00194 }
00195 int cNet::Recv (const int iSocket,char* pBuffer,const int iBufferSize,const int iFlags) {
00196 return recv(iSocket,pBuffer,iBufferSize,iFlags);
00197 }
00198
00200 cConnection* cNet::Connect (const char* szHost,const int iPort) { PROFILE
00201 uint32 iIP = GetHostByName(szHost);
00202 int iSocket = ConnectSocket(iIP,iPort);
00203 if (iSocket == INVALID_SOCKET) {
00204 printf("cNet::Connect : ConnectSocket failed (%s:%d)\n",szHost,iPort);
00205 return 0;
00206 }
00207 return new cConnection(iSocket,szHost,iPort,iIP);
00208 }
00209
00210
00211 cNetListener* cNet::Listen (const int iPort) { PROFILE
00212 int iListenSocket;
00213
00214
00215 iListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00216 if (iListenSocket == INVALID_SOCKET) {
00217 printf("cNet::Listen : Socket Creation Failed\n");
00218 return 0;
00219 }
00220
00221
00222 sockaddr_in sa;
00223 memset(&sa,0,sizeof(sa));
00224
00225 sa.sin_family = AF_INET;
00226 sa.sin_port = htons(iPort);
00227 sa.sin_addr.s_addr = (uint32)0x00000000;
00228
00229 int err;
00230 err = bind(iListenSocket,(sockaddr*)&sa,sizeof(sa));
00231 if (err != 0) {
00232 printf("cNet::Listen : BIND ERROR %d %d(%s)\n",err,errno,strerror(errno));
00233 closesocket(iListenSocket);
00234 return 0;
00235 }
00236
00237
00238 err = listen(iListenSocket,SOMAXCONN);
00239 if (err != 0) {
00240 printf("cNet::Listen : LISTEN ERROR %d\n",err);
00241 closesocket(iListenSocket);
00242 return 0;
00243 }
00244
00245
00246 return new cNetListener(iListenSocket,iPort);
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00257 cConnection::cConnection ()
00258 : miSocket(INVALID_SOCKET), mbOwnBuffers(true), miPort(0), miRemoteAddr(0) { PROFILE
00259 Init();
00260 }
00261
00263 cConnection::cConnection (cConnection* con)
00264 : miSocket(INVALID_SOCKET), mbOwnBuffers(false), miPort(0), miRemoteAddr(0),
00265 mpInBuffer(con->mpOutBuffer), mpOutBuffer(con->mpInBuffer) { PROFILE
00266 Init();
00267 }
00268
00269
00271 cConnection::cConnection (const int iSocket,const char* szHost,const int iPort,const uint32 iIP)
00272 : miSocket(iSocket), mbOwnBuffers(true), miPort(iPort), miRemoteAddr(iIP) { PROFILE
00273 Init();
00274
00275 }
00276
00278 cConnection::cConnection (const int iSocket,const uint32 iIP)
00279 : miSocket(iSocket), mbOwnBuffers(true), miPort(0), miRemoteAddr(iIP) { PROFILE
00280 Init();
00281
00282 }
00283
00284 void cConnection::Init () { PROFILE
00285 if (mbOwnBuffers) {
00286 mpInBuffer = new cFIFO(kConStartSpace);
00287 mpOutBuffer = new cFIFO(kConStartSpace);
00288 }
00289
00290 mIP[0] = ((unsigned char*)&miRemoteAddr)[0];
00291 mIP[1] = ((unsigned char*)&miRemoteAddr)[1];
00292 mIP[2] = ((unsigned char*)&miRemoteAddr)[2];
00293 mIP[3] = ((unsigned char*)&miRemoteAddr)[3];
00294 cNet::GetSingleton().mlCons.insert(this);
00295 }
00296
00297 void cConnection::Close () { PROFILE
00298 if (miSocket != INVALID_SOCKET) {
00299 closesocket(miSocket);
00300
00301
00302 miSocket = INVALID_SOCKET;
00303 }
00304 }
00305
00306 bool cConnection::IsLocal () { return miSocket == INVALID_SOCKET; }
00307
00308 cConnection::~cConnection () { PROFILE
00309 Close();
00310 cNet::GetSingleton().mlCons.erase(this);
00311 if (mbOwnBuffers) {
00312 delete mpInBuffer;
00313 delete mpOutBuffer;
00314 }
00315 }
00316
00318 void cConnection::SendPush (cFIFO& source,const bool bWrite) { PROFILE
00319
00320 assert(mpOutBuffer);
00321 if (source.size() == 0) return;
00322
00323 size_t res = (miSocket == INVALID_SOCKET || mpOutBuffer->size() > 0 || !bWrite) ? 0 : send(miSocket,source.HackGetRawReader(),source.size(),0);
00324 if (res >= 0) {
00325 if (res < source.size()) {
00326
00327 mpOutBuffer->PushRaw(source.HackGetRawReader()-res,source.size()-res);
00328 }
00329 } else if (res < 0) {
00330
00331
00332 miSocket = INVALID_SOCKET;
00333 cNet::GetSingleton().mlDyingCons.insert(this);
00334 return;
00335 }
00336 }
00337
00338 void cConnection::Step (const bool bRead,const bool bWrite, const bool bExcept) { PROFILE
00339 if (miSocket == INVALID_SOCKET) return;
00340 assert(mpOutBuffer);
00341 assert(mpInBuffer);
00342 int res;
00343
00344
00345 if (bWrite && mpOutBuffer->size() > 0) {
00346 res = send(miSocket,mpOutBuffer->HackGetRawReader(),mpOutBuffer->size(),0);
00347 if (res > 0) {
00348 mpOutBuffer->PopRaw(res);
00349 } else if (res < 0) {
00350
00351
00352 miSocket = INVALID_SOCKET;
00353 cNet::GetSingleton().mlDyingCons.insert(this);
00354 return;
00355 }
00356 }
00357
00358
00359 if (bRead) {
00360 char *rw = mpInBuffer->HackGetRawWriter(kConMinRecvSpace);
00361 int fs = mpInBuffer->HackGetFreeSpace();
00362 res = recv(miSocket,rw,fs,0);
00363 if (res > 0) {
00364
00365 mpInBuffer->HackAddLength(res);
00366 } else if(res < 0) {
00367
00368
00369 miSocket = INVALID_SOCKET;
00370 cNet::GetSingleton().mlDyingCons.insert(this);
00371 return;
00372 } else {
00373
00374
00375 miSocket = INVALID_SOCKET;
00376 cNet::GetSingleton().mlDyingCons.insert(this);
00377 return;
00378 }
00379 }
00380 }
00381
00382
00383
00384
00385
00386
00387
00388 cBroadcast::cBroadcast() : mOutBuffer(kConStartSpace) { PROFILE cNet::GetSingleton().mlBroadCasts.insert(this); }
00389 cBroadcast::~cBroadcast() {}
00390
00391 void cBroadcast::Step () { PROFILE
00392
00393 if (mOutBuffer.size() == 0) return;
00394 if (mlCons.size() == 0) {
00395 mOutBuffer.Clear();
00396 return;
00397 }
00398
00399 bool bWrite;
00400 int res,mysocket,imax=0;
00401 timeval timeout;
00402 timeout.tv_sec = 0;
00403 timeout.tv_usec = 0;
00404
00405 FD_ZERO(&sSelectSet_Write);
00406
00407 for (std::set<cConnection*>::iterator itor=mlCons.begin(); itor!=mlCons.end(); ++itor) {
00408 mysocket = (*itor)->miSocket;
00409 if (mysocket != INVALID_SOCKET) {
00410 if (imax < mysocket)
00411 imax = mysocket;
00412 FD_SET((unsigned int)mysocket,&sSelectSet_Write);
00413 }
00414 }
00415
00416 if (imax > 0)
00417 res = select(imax+1,0,&sSelectSet_Write,0,&timeout);
00418
00419 for (std::set<cConnection*>::iterator itor=mlCons.begin(); itor!=mlCons.end(); ++itor) {
00420
00421 bWrite = (*itor)->miSocket != INVALID_SOCKET && FD_ISSET((unsigned int)(*itor)->miSocket,&sSelectSet_Write) != 0;
00422 (*itor)->SendPush(mOutBuffer, bWrite);
00423 }
00424
00425 mOutBuffer.Clear();
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 cNetListener::cNetListener (int iListenSocket,int iPort) : miPort(iPort), miListenSocket(iListenSocket) { PROFILE
00435 cNet::GetSingleton().mlListener.insert(this);
00436 }
00437
00438 cNetListener::~cNetListener () { PROFILE
00439 if (miListenSocket != INVALID_SOCKET) {
00440 closesocket(miListenSocket);
00441 miListenSocket = INVALID_SOCKET;
00442 }
00443
00444 cNet::GetSingleton().mlListener.erase(this);
00445 }
00446
00447 void cNetListener::Step () { PROFILE
00448 if (miListenSocket == INVALID_SOCKET) return;
00449
00450
00451
00452 timeval timeout;
00453 timeout.tv_sec = 0;
00454 timeout.tv_usec = 0;
00455
00456 fd_set conn;
00457 FD_ZERO(&conn);
00458 FD_SET((unsigned int)miListenSocket, &conn);
00459
00460 int selres;
00461 selres = select(miListenSocket+1, &conn, NULL, NULL, &timeout);
00462
00463
00464 if (selres <= 0) return;
00465
00466
00467 int consocket;
00468 struct sockaddr_in their_addr;
00469 socklen_t sin_size;
00470
00471 sin_size = sizeof(struct sockaddr_in);
00472 consocket = accept(miListenSocket,(struct sockaddr *)&their_addr, &sin_size);
00473
00474 if (consocket != INVALID_SOCKET) {
00475
00476 mlCons.insert(new cConnection(consocket,their_addr.sin_addr.s_addr));
00477 }
00478 }
00479
00480 cConnection* cNetListener::PopAccepted () { PROFILE
00481 if (mlCons.size() == 0) return 0;
00482 cConnection* con = *mlCons.begin();
00483 mlCons.erase(con);
00484 return con;
00485 }
00486
00487
00488
00489
00490
00491 cUDP_ReceiveSocket::cUDP_ReceiveSocket (const int iPort) : miPort(iPort) {
00492 struct sockaddr_in host_address;
00493
00494 miSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00495 if (miSocket < 0) {
00496 printf("cUDP_ReceiveSocket : error opening socket : %d\n",miSocket);
00497 miSocket = INVALID_SOCKET;
00498 return;
00499 }
00500
00501 memset((void*)&host_address, 0, sizeof(host_address));
00502 host_address.sin_family =AF_INET;
00503 host_address.sin_addr.s_addr =INADDR_ANY;
00504 host_address.sin_port =htons(miPort);
00505 int res = bind(miSocket,(struct sockaddr*)&host_address,sizeof(host_address));
00506 if (res < 0) {
00507 printf("cUDP_ReceiveSocket : error binding socket to port %d : %d\n",miPort,res);
00508
00509 }
00510 }
00511
00512 cUDP_ReceiveSocket::~cUDP_ReceiveSocket () {
00513 if (miSocket != INVALID_SOCKET) { closesocket(miSocket); miSocket = INVALID_SOCKET; }
00514 }
00515
00516 int cUDP_ReceiveSocket::Receive (cFIFO& pFIFO,uint32& iAddr) {
00517 if (miSocket == INVALID_SOCKET) return 0;
00518
00519
00520 if (1) {
00521 int res,mysocket,imax=0;
00522 timeval timeout;
00523 timeout.tv_sec = 0;
00524 timeout.tv_usec = 0;
00525
00526 FD_ZERO(&sSelectSet_Read);
00527 FD_ZERO(&sSelectSet_Write);
00528 FD_ZERO(&sSelectSet_Except);
00529
00530 FD_SET((unsigned int)miSocket,&sSelectSet_Read);
00531 FD_SET((unsigned int)miSocket,&sSelectSet_Write);
00532 FD_SET((unsigned int)miSocket,&sSelectSet_Except);
00533
00534 imax = miSocket;
00535 res = select(imax+1,&sSelectSet_Read,&sSelectSet_Write,&sSelectSet_Except,&timeout);
00536
00537 if (FD_ISSET((unsigned int)miSocket,&sSelectSet_Read) == 0) return 0;
00538 }
00539
00540 static struct sockaddr_in remote_address;
00541 static bool init_remote_address = true;
00542 if (init_remote_address) {
00543 init_remote_address = false;
00544 memset((void*)&remote_address, 0, sizeof(remote_address));
00545 remote_address.sin_family = AF_INET;
00546 }
00547 remote_address.sin_port = htons(miPort);
00548 socklen_t remote_address_size = sizeof(remote_address);
00549
00550
00551 int res = recvfrom(miSocket,pFIFO.HackGetRawWriter(kMaxUDPMsgLen),kMaxUDPMsgLen,0,(struct sockaddr*)&remote_address,&remote_address_size);
00552
00553 if (res > 0) pFIFO.HackAddLength(res);
00554 iAddr = remote_address.sin_addr.s_addr;
00555 return res;
00556 }
00557
00558
00559
00560 cUDP_SendSocket::cUDP_SendSocket () {
00561 miSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
00562 if (miSocket < 0) {
00563 printf("cUDP_SendSocket : error opening socket : %d\n",miSocket);
00564 miSocket = INVALID_SOCKET;
00565 }
00566
00567 char broadcast = 1;
00568 setsockopt(miSocket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 }
00579
00580 cUDP_SendSocket::~cUDP_SendSocket () {
00581 if (miSocket != INVALID_SOCKET) { closesocket(miSocket); miSocket = INVALID_SOCKET; }
00582 }
00583
00584 void cUDP_SendSocket::SetBroadcast (char broadcast) {
00585 if (miSocket) {
00586
00587 #ifndef WIN32
00588 int p = 0;
00589 if(broadcast > 0)p = 1;
00590 setsockopt(miSocket, SOL_SOCKET, SO_BROADCAST, &p, sizeof(p));
00591 #endif
00592 }
00593 }
00594
00595 int cUDP_SendSocket::Send (const uint32 iAddr,const int iPort,const char* pData,const int iDataLen) {
00596 if (miSocket == INVALID_SOCKET) return 0;
00597
00598 static struct sockaddr_in remote_address;
00599 static bool init_remote_address = true;
00600 if (init_remote_address) {
00601 init_remote_address = false;
00602 memset((void*)&remote_address, 0, sizeof(remote_address));
00603 remote_address.sin_family = AF_INET;
00604 remote_address.sin_port = htons(iPort);
00605 }
00606 remote_address.sin_addr.s_addr = iAddr;
00607 return sendto(miSocket,pData,iDataLen,0,(struct sockaddr*)&remote_address,sizeof(remote_address));
00608 }
00609
00610 int cUDP_SendSocket::Send (const uint32 iAddr,const int iPort,cFIFO& pFIFO,const int iDataLen) {
00611 assert(iDataLen <= pFIFO.size() && "cUDP_SendSocket::Send fifo underrun");
00612 return Send(iAddr,iPort,pFIFO.HackGetRawReader(),(iDataLen>0&&iDataLen<=pFIFO.size())?iDataLen:pFIFO.size());
00613 }
00614
00615
00616
00617 };