Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGSocket.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 //---------------------------------------------------------------------------
00040 //  Includes
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 /*                            constructor destructor                       */
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 /*                        open, close, connect                             */
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 /*                        read, write    nnect                             */
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 /*                        socket state access                              */
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 /*                              error information                          */
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 /*                              cvs id's                                   */
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 

Generated on Thu Aug 25 04:10:26 2005 for OpenSG by  doxygen 1.4.3