00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #if defined(__sun)
00044 #define BSD_COMP
00045 #endif
00046
00047
00048 #include <sys/types.h>
00049 #ifdef WIN32
00050 #include <windows.h>
00051 #include <io.h>
00052 #else
00053 #include <sys/socket.h>
00054 #include <netinet/in.h>
00055 #include <netinet/tcp.h>
00056 #include <arpa/inet.h>
00057 #include <netdb.h>
00058 #include <unistd.h>
00059 #include <fcntl.h>
00060 #include <sys/time.h>
00061 #include <sys/ioctl.h>
00062 #endif
00063 #include <errno.h>
00064 #include <stdio.h>
00065 #include <math.h>
00066 #include <map>
00067 #include <OSGBase.h>
00068 #include <OSGBaseFunctions.h>
00069 #include <OSGSocketAddress.h>
00070 #include <OSGSocket.h>
00071 #include <OSGSocketSelection.h>
00072 #include <OSGNetworkMessage.h>
00073
00074 OSG_USING_NAMESPACE
00075
00095 int Socket::initialized=0;
00096
00097
00098
00099
00105 Socket::Socket(void):
00106 _sd(-1)
00107 {
00108 if(!initialized)
00109 {
00110 initialized=1;
00111 #ifdef WIN32
00112 WSADATA wsaData;
00113
00114 WORD wVersionRequested = MAKEWORD( 2, 2 );
00115 if(WSAStartup( wVersionRequested, &wsaData )!=0)
00116 {
00117 throw SocketError("WSAStartup()");
00118 }
00119 #endif
00120 }
00121 }
00122
00125 Socket::Socket(const Socket &source):
00126 _sd(source._sd)
00127 {
00128 }
00129
00133 Socket::~Socket()
00134 {
00135 }
00136
00137
00138
00139
00150 void Socket::bind(const SocketAddress &address)
00151 {
00152 SocketAddress result=address;
00153
00154 if( ::bind(_sd,
00155 result.getSockAddr(),
00156 result.getSockAddrSize()) < 0)
00157 {
00158 if(getError() ==
00159 #if defined WIN32
00160 WSAEADDRINUSE
00161 #else
00162 EADDRINUSE
00163 #endif
00164 )
00165 {
00166 throw SocketInUse("bind()");
00167 }
00168 else
00169 {
00170 throw SocketError("bind()");
00171 }
00172 }
00173 }
00174
00177 void Socket::listen(int maxPending)
00178 {
00179 if(::listen(_sd,maxPending)<0)
00180 {
00181 throw SocketError("listen()");
00182 }
00183 }
00184
00188 void Socket::connect(const SocketAddress &address)
00189 {
00190 if( ::connect(_sd,
00191 address.getSockAddr(),
00192 address.getSockAddrSize()) )
00193 {
00194 throw SocketError("connect()");
00195 }
00196 }
00197
00198
00199
00200
00206 int Socket::recv(void *buf,int size)
00207 {
00208 int readSize;
00209 int pos=0;
00210
00211 while(size)
00212 {
00213 readSize=::recv(_sd,((char*)buf) + pos,size,0);
00214 if(readSize < 0)
00215 {
00216 #if defined WIN32
00217 if(getError() == WSAECONNRESET)
00218 {
00219 throw SocketConnReset("recv");
00220 }
00221 if(getError() == WSAEMSGSIZE)
00222 {
00223 readSize=size;
00224 }
00225 else
00226 #endif
00227 throw SocketError("recv()");
00228 }
00229 if(readSize == 0)
00230 {
00231 return 0;
00232 }
00233 size-=readSize;
00234 pos +=readSize;
00235 }
00236 return pos;
00237 }
00238
00243 int Socket::recvAvailable(void *buf,int size)
00244 {
00245 int len;
00246
00247 #ifndef WIN32
00248 do
00249 {
00250 #endif
00251 len=::recv(_sd,(char*)buf,size,0);
00252 #ifndef WIN32
00253 }
00254 while(len < 0 && errno == EAGAIN);
00255 #endif
00256 if(len==-1)
00257 {
00258 #if defined WIN32
00259 switch(getError())
00260 {
00261 case WSAECONNRESET:
00262 throw SocketConnReset("recvAvailable()");
00263 break;
00264 case WSAEMSGSIZE:
00265 len=size;
00266 break;
00267 default:
00268 throw SocketError("recv()");
00269 }
00270 #else
00271 throw SocketError("recv()");
00272 #endif
00273 }
00274 return len;
00275 }
00276
00280 int Socket::recv(NetworkMessage &msg)
00281 {
00282 NetworkMessage::Header hdr;
00283 peek(&hdr,sizeof(hdr));
00284 msg.setSize(osgntohl(hdr.size));
00285 return recv(msg.getBuffer(),msg.getSize());
00286 }
00287
00295 int Socket::peek(void *buf,int size)
00296 {
00297 int readSize;
00298 int pos=0;
00299
00300 do
00301 {
00302 readSize=::recv(_sd,((char*)buf)+pos,size,MSG_PEEK);
00303 if(readSize<0)
00304 {
00305 #if defined WIN32
00306 if(getError() == WSAECONNRESET)
00307 {
00308 throw SocketConnReset("peek");
00309 }
00310 if(getError() == WSAEMSGSIZE)
00311 {
00312 readSize=size;
00313 }
00314 else
00315 #endif
00316 throw SocketError("peek");
00317 }
00318 if(readSize == 0)
00319 {
00320 return 0;
00321 }
00322 }
00323 while(readSize != size);
00324 return readSize;
00325 }
00326
00330 int Socket::send(const void *buf,int size)
00331 {
00332 int writeSize;
00333 int pos=0;
00334 while(size)
00335 {
00336 #if defined(WIN32) && defined(MSG_NOSIGNAL)
00337 writeSize=::send(_sd,((const char*)buf)+pos,size,MSG_NOSIGNAL);
00338 #else
00339 writeSize=::send(_sd,((const char*)buf)+pos,size,0);
00340 #endif
00341 if(writeSize == -1)
00342 {
00343 throw SocketError("send()");
00344 }
00345 if(writeSize == 0)
00346 {
00347 return 0;
00348 }
00349 size-=writeSize;
00350 pos+=writeSize;
00351 }
00352 return pos;
00353 }
00354
00358 int Socket::send(NetworkMessage &msg)
00359 {
00360 NetworkMessage::Header &hdr=msg.getHeader();
00361 hdr.size=osghtonl(msg.getSize());
00362 return send(msg.getBuffer(),msg.getSize());
00363 }
00364
00365
00366
00367
00374 void Socket::setReusePort(bool value)
00375 {
00376 int v=(int)value;
00377 #ifdef SO_REUSEPORT
00378 ::setsockopt(_sd,SOL_SOCKET,SO_REUSEPORT,(SocketOptT*)&v,sizeof(v));
00379 #endif
00380 ::setsockopt(_sd,SOL_SOCKET,SO_REUSEADDR,(SocketOptT*)&v,sizeof(v));
00381 }
00382
00391 void Socket::setBlocking(bool value)
00392 {
00393 #ifndef WIN32
00394 int val=0;
00395
00396 if(value==false)
00397 val=O_NDELAY;
00398 if (fcntl(_sd, F_GETFL, &val) < 0)
00399 {
00400 throw SocketError("fcntl()");
00401 }
00402 val|=O_NDELAY;
00403 if(value)
00404 {
00405 val^=O_NDELAY;
00406 }
00407 if (fcntl(_sd, F_SETFL, val) < 0)
00408 {
00409 throw SocketError("fcntl()");
00410 }
00411 #else
00412 u_long ulVal = !value;
00413 if( (ioctlsocket(_sd, FIONBIO, &ulVal)) != 0)
00414 {
00415 throw SocketError("ioctlsocket()");
00416 }
00417 #endif
00418 }
00419
00423 SocketAddress Socket::getAddress()
00424 {
00425 SocketAddress result;
00426 SocketLenT len;
00427
00428 len=result.getSockAddrSize();
00429 if( ::getsockname(_sd,result.getSockAddr(),&len) < 0)
00430 {
00431 throw SocketError("getsockname()");
00432 }
00433 return result;
00434 }
00435
00439 void Socket::setReadBufferSize(int size)
00440 {
00441 int v=(int)size;
00442 ::setsockopt(_sd,SOL_SOCKET,SO_RCVBUF,(SocketOptT*)&v,sizeof(v));
00443 }
00444
00448 void Socket::setWriteBufferSize(int size)
00449 {
00450 int v=(int)size;
00451 ::setsockopt(_sd,SOL_SOCKET,SO_SNDBUF,(SocketOptT*)&v,sizeof(v));
00452 }
00453
00457 int Socket::getReadBufferSize()
00458 {
00459 int v;
00460 SocketLenT len=sizeof(v);
00461 ::getsockopt(_sd,SOL_SOCKET,SO_RCVBUF,(SocketOptT*)&v,&len);
00462 return v;
00463 }
00464
00468 int Socket::getWriteBufferSize()
00469 {
00470 int v;
00471 SocketLenT len=sizeof(v);
00472 ::getsockopt(_sd,SOL_SOCKET,SO_SNDBUF,(SocketOptT*)&v,&len);
00473 return v;
00474 }
00475
00478 int Socket::getAvailable(void)
00479 {
00480 #ifndef WIN32
00481 int value;
00482 if(::ioctl(_sd, FIONREAD, &value)<0)
00483 {
00484 throw SocketError("ioctl()");
00485 }
00486 return value;
00487 #else
00488 u_long ulVal;
00489 if( (ioctlsocket(_sd, FIONREAD, &ulVal)) != 0)
00490 {
00491 throw SocketError("ioctlsocket()");
00492 }
00493 return (int)ulVal;
00494 #endif
00495 }
00496
00500 bool Socket::waitReadable(double duration)
00501 {
00502 SocketSelection selection;
00503 selection.setRead(*this);
00504 if(selection.select(duration)==1)
00505 return true;
00506 else
00507 return false;
00508 }
00509
00513 bool Socket::waitWritable(double duration)
00514 {
00515 SocketSelection selection;
00516 selection.setWrite(*this);
00517 if(selection.select(duration)==1)
00518 return true;
00519 else
00520 return false;
00521 }
00522
00525 const Socket & Socket::operator =(const Socket &source)
00526 {
00527 _sd=source._sd;
00528 return *this;
00529 }
00530
00531
00532
00533
00536 int Socket::getError(void)
00537 {
00538 #ifdef WIN32
00539 return WSAGetLastError();
00540 #else
00541 return errno;
00542 #endif
00543 }
00544
00547 int Socket::getHostError(void)
00548 {
00549 #ifdef WIN32
00550 return WSAGetLastError();
00551 #else
00552 return h_errno;
00553 #endif
00554 }
00555
00558 std::string Socket::getErrorStr(void)
00559 {
00560 const char *err=NULL;
00561
00562 #ifdef WIN32
00563 switch(getError())
00564 {
00565 case WSAEINTR: err= "WSAEINTR"; break;
00566 case WSAEBADF: err= "WSAEBADF"; break;
00567 case WSAEFAULT: err= "WSAEFAULT"; break;
00568 case WSAEINVAL: err= "WSAEINVAL"; break;
00569 case WSAEMFILE: err= "WSAEMFILE"; break;
00570 case WSAEWOULDBLOCK: err= "WSAEWOULDBLOCK"; break;
00571 case WSAEINPROGRESS: err= "WSAEINPROGRESS"; break;
00572 case WSAEALREADY: err= "WSAEALREADY"; break;
00573 case WSAENOTSOCK: err= "WSAENOTSOCK"; break;
00574 case WSAEDESTADDRREQ: err= "WSAEDESTADDRREQ"; break;
00575 case WSAEMSGSIZE: err= "WSAEMSGSIZE"; break;
00576 case WSAEPROTOTYPE: err= "WSAEPROTOTYPE"; break;
00577 case WSAENOPROTOOPT: err= "WSAENOPROTOOPT"; break;
00578 case WSAEPROTONOSUPPORT: err= "WSAEPROTONOSUPPORT"; break;
00579 case WSAESOCKTNOSUPPORT: err= "WSAESOCKTNOSUPPORT"; break;
00580 case WSAEOPNOTSUPP: err= "WSAEOPNOTSUPP"; break;
00581 case WSAEPFNOSUPPORT: err= "WSAEPFNOSUPPORT"; break;
00582 case WSAEAFNOSUPPORT: err= "WSAEAFNOSUPPORT"; break;
00583 case WSAEADDRINUSE: err= "WSAEADDRINUSE"; break;
00584 case WSAEADDRNOTAVAIL: err= "WSAEADDRNOTAVAIL"; break;
00585 case WSAENETDOWN: err= "WSAENETDOWN"; break;
00586 case WSAENETUNREACH: err= "WSAENETUNREACH"; break;
00587 case WSAENETRESET: err= "WSAENETRESET"; break;
00588 case WSAECONNABORTED: err= "WSAECONNABORTED"; break;
00589 case WSAECONNRESET: err= "WSAECONNRESET"; break;
00590 case WSAENOBUFS: err= "WSAENOBUFS"; break;
00591 case WSAEISCONN: err= "WSAEISCONN"; break;
00592 case WSAENOTCONN: err= "WSAENOTCONN"; break;
00593 case WSAESHUTDOWN: err= "WSAESHUTDOWN"; break;
00594 case WSAETOOMANYREFS: err= "WSAETOOMANYREFS"; break;
00595 case WSAETIMEDOUT: err= "WSAETIMEDOUT"; break;
00596 case WSAECONNREFUSED: err= "WSAECONNREFUSED"; break;
00597 case WSAELOOP: err= "WSAELOOP"; break;
00598 case WSAENAMETOOLONG: err= "WSAENAMETOOLONG"; break;
00599 case WSAEHOSTDOWN: err= "WSAEHOSTDOWN"; break;
00600 case WSAEHOSTUNREACH: err= "WSAEHOSTUNREACH"; break;
00601 case WSASYSNOTREADY: err= "WSASYSNOTREADY"; break;
00602 case WSAVERNOTSUPPORTED: err= "WSAVERNOTSUPPORTED"; break;
00603 case WSANOTINITIALISED: err= "WSANOTINITIALISED"; break;
00604 case WSAHOST_NOT_FOUND: err= "WSAHOST_NOT_FOUND"; break;
00605 case WSATRY_AGAIN: err= "WSATRY_AGAIN"; break;
00606 case WSANO_RECOVERY: err= "WSANO_RECOVERY"; break;
00607 case WSANO_DATA: err= "WSANO_DATA"; break;
00608 }
00609 #else
00610 err=strerror(getError());
00611 #endif
00612 if(err)
00613 return std::string(err);
00614 else
00615 return std::string("Unknown error");
00616 }
00617
00620 std::string Socket::getHostErrorStr(void)
00621 {
00622 const char *err;
00623 #if defined(WIN32) || defined(__hpux)
00624 err = strerror(getHostError());
00625 #else
00626 err = hstrerror(getHostError());
00627 #endif
00628 if(err)
00629 return std::string(err);
00630 else
00631 return std::string("Unknown error");
00632 }
00633
00634
00635
00636
00637 #ifdef __sgi
00638 #pragma set woff 1174
00639 #endif
00640
00641 #ifdef OSG_LINUX_ICC
00642 #pragma warning( disable : 177 )
00643 #endif
00644
00645 namespace
00646 {
00647 static Char8 cvsid_cpp [] = "@(#)$Id: $";
00648 static Char8 cvsid_hpp [] = OSG_SOCKET_HEADER_CVSID;
00649 }
00650