Jack2 1.9.6

JackNetWinSocket.cpp

00001 /*
00002  Copyright (C) 2004-2008 Grame
00003  
00004  This program is free software; you can redistribute it and/or modify
00005  it under the terms of the GNU Lesser General Public License as published by
00006  the Free Software Foundation; either version 2.1 of the License, or
00007  (at your option) any later version.
00008  
00009  This program is distributed in the hope that it will be useful,
00010  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  GNU Lesser General Public License for more details.
00013  
00014  You should have received a copy of the GNU Lesser General Public License
00015  along with this program; if not, write to the Free Software
00016  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  
00018  */
00019 
00020 
00021 #include "JackNetWinSocket.h"
00022 
00023 namespace Jack
00024 {
00025     //utility *********************************************************************************************************
00026     SERVER_EXPORT int GetHostName ( char * name, int size )
00027     {
00028         if ( gethostname ( name, size ) == SOCKET_ERROR )
00029         {
00030             jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) );
00031             strcpy ( name, "default" );
00032             return -1;
00033         }
00034         return 0;
00035     }
00036 
00037     win_net_error_t NetErrorList[] =
00038     {
00039         E ( 0,                  "No error" ),
00040         E ( WSAEINTR,           "Interrupted system call" ),
00041         E ( WSAEBADF,           "Bad file number" ),
00042         E ( WSAEACCES,          "Permission denied" ),
00043         E ( WSAEFAULT,          "Bad address" ),
00044         E ( WSAEINVAL,          "Invalid argument" ),
00045         E ( WSAEMFILE,          "Too many open sockets" ),
00046         E ( WSAEWOULDBLOCK,     "Operation would block" ),
00047         E ( WSAEINPROGRESS,     "Operation now in progress" ),
00048         E ( WSAEALREADY,        "Operation already in progress" ),
00049         E ( WSAENOTSOCK,        "Socket operation on non-socket" ),
00050         E ( WSAEDESTADDRREQ,    "Destination address required" ),
00051         E ( WSAEMSGSIZE,        "Message too long" ),
00052         E ( WSAEPROTOTYPE,      "Protocol wrong type for socket" ),
00053         E ( WSAENOPROTOOPT,     "Bad protocol option" ),
00054         E ( WSAEPROTONOSUPPORT, "Protocol not supported" ),
00055         E ( WSAESOCKTNOSUPPORT, "Socket type not supported" ),
00056         E ( WSAEOPNOTSUPP,      "Operation not supported on socket" ),
00057         E ( WSAEPFNOSUPPORT,    "Protocol family not supported" ),
00058         E ( WSAEAFNOSUPPORT,    "Address family not supported" ),
00059         E ( WSAEADDRINUSE,      "Address already in use" ),
00060         E ( WSAEADDRNOTAVAIL,   "Can't assign requested address" ),
00061         E ( WSAENETDOWN,        "Network is down" ),
00062         E ( WSAENETUNREACH,     "Network is unreachable" ),
00063         E ( WSAENETRESET,       "Net connection reset" ),
00064         E ( WSAECONNABORTED,    "Software caused connection abort" ),
00065         E ( WSAECONNRESET,      "Connection reset by peer" ),
00066         E ( WSAENOBUFS,         "No buffer space available" ),
00067         E ( WSAEISCONN,         "Socket is already connected" ),
00068         E ( WSAENOTCONN,        "Socket is not connected" ),
00069         E ( WSAESHUTDOWN,       "Can't send after socket shutdown" ),
00070         E ( WSAETOOMANYREFS,    "Too many references, can't splice" ),
00071         E ( WSAETIMEDOUT,       "Connection timed out" ),
00072         E ( WSAECONNREFUSED,    "Connection refused" ),
00073         E ( WSAELOOP,           "Too many levels of symbolic links" ),
00074         E ( WSAENAMETOOLONG,    "File name too long" ),
00075         E ( WSAEHOSTDOWN,       "Host is down" ),
00076         E ( WSAEHOSTUNREACH,    "No route to host" ),
00077         E ( WSAENOTEMPTY,       "Directory not empty" ),
00078         E ( WSAEPROCLIM,        "Too many processes" ),
00079         E ( WSAEUSERS,          "Too many users" ),
00080         E ( WSAEDQUOT,          "Disc quota exceeded" ),
00081         E ( WSAESTALE,          "Stale NFS file handle" ),
00082         E ( WSAEREMOTE,         "Too many levels of remote in path" ),
00083         E ( WSASYSNOTREADY,     "Network system is unavailable" ),
00084         E ( WSAVERNOTSUPPORTED, "Winsock version out of range" ),
00085         E ( WSANOTINITIALISED,  "WSAStartup not yet called" ),
00086         E ( WSAEDISCON,         "Graceful shutdown in progress" ),
00087         E ( WSAHOST_NOT_FOUND,  "Host not found" ),
00088         E ( WSANO_DATA,         "No host data of that type was found" ),
00089         { -1, NULL },
00090     };
00091 
00092     SERVER_EXPORT const char* PrintError ( int error )
00093     {
00094         int i;
00095         for ( i = 0; NetErrorList[i].code >= 0; ++i )
00096         {
00097             if ( error == NetErrorList[i].code )
00098                 return NetErrorList[i].msg;
00099         }
00100         return strerror ( error );
00101     }
00102 
00103     //construct/destruct***********************************************************************************************
00104     JackNetWinSocket::JackNetWinSocket()
00105     {
00106         fSockfd = 0;
00107         fSendAddr.sin_family = AF_INET;
00108         fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
00109         memset ( &fSendAddr.sin_zero, 0, 8 );
00110         fRecvAddr.sin_family = AF_INET;
00111         fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
00112         memset ( &fRecvAddr.sin_zero, 0, 8 );
00113     }
00114 
00115     JackNetWinSocket::JackNetWinSocket ( const char* ip, int port )
00116     {
00117         fSockfd = 0;
00118         fPort = port;
00119         fSendAddr.sin_family = AF_INET;
00120         fSendAddr.sin_port = htons ( port );
00121         fSendAddr.sin_addr.s_addr = inet_addr ( ip );
00122         memset ( &fSendAddr.sin_zero, 0, 8 );
00123         fRecvAddr.sin_family = AF_INET;
00124         fRecvAddr.sin_port = htons ( port );
00125         fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
00126         memset ( &fRecvAddr.sin_zero, 0, 8 );
00127     }
00128 
00129     JackNetWinSocket::JackNetWinSocket ( const JackNetWinSocket& socket )
00130     {
00131         fSockfd = 0;
00132         fPort = socket.fPort;
00133         fSendAddr = socket.fSendAddr;
00134         fRecvAddr = socket.fRecvAddr;
00135     }
00136 
00137     JackNetWinSocket::~JackNetWinSocket()
00138     {
00139         Close();
00140     }
00141 
00142     JackNetWinSocket& JackNetWinSocket::operator= ( const JackNetWinSocket& socket )
00143     {
00144         if ( this != &socket )
00145         {
00146             fSockfd = 0;
00147             fPort = socket.fPort;
00148             fSendAddr = socket.fSendAddr;
00149             fRecvAddr = socket.fRecvAddr;
00150         }
00151         return *this;
00152     }
00153 
00154     //socket***********************************************************************************************************
00155     int JackNetWinSocket::NewSocket()
00156     {
00157         if ( fSockfd )
00158         {
00159             Close();
00160             Reset();
00161         }
00162         fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 );
00163         return fSockfd;
00164     }
00165 
00166     int JackNetWinSocket::Bind()
00167     {
00168         return bind ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), sizeof ( SOCKADDR ) );
00169     }
00170 
00171     int JackNetWinSocket::BindWith ( const char* ip )
00172     {
00173         fRecvAddr.sin_addr.s_addr = inet_addr ( ip );
00174         return Bind();
00175     }
00176 
00177     int JackNetWinSocket::BindWith ( int port )
00178     {
00179         fRecvAddr.sin_port = htons ( port );
00180         return Bind();
00181     }
00182 
00183     int JackNetWinSocket::Connect()
00184     {
00185         return connect ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) );
00186     }
00187 
00188     int JackNetWinSocket::ConnectTo ( const char* ip )
00189     {
00190         fSendAddr.sin_addr.s_addr = inet_addr ( ip );
00191         return Connect();
00192     }
00193 
00194     void JackNetWinSocket::Close()
00195     {
00196         if ( fSockfd )
00197             closesocket ( fSockfd );
00198         fSockfd = 0;
00199     }
00200 
00201     void JackNetWinSocket::Reset()
00202     {
00203         fSendAddr.sin_family = AF_INET;
00204         fSendAddr.sin_port = htons ( fPort );
00205         fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
00206         memset ( &fSendAddr.sin_zero, 0, 8 );
00207         fRecvAddr.sin_family = AF_INET;
00208         fRecvAddr.sin_port = htons ( fPort );
00209         fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
00210         memset ( &fRecvAddr.sin_zero, 0, 8 );
00211     }
00212 
00213     bool JackNetWinSocket::IsSocket()
00214     {
00215         return ( fSockfd ) ? true : false;
00216     }
00217 
00218     //IP/PORT***********************************************************************************************************
00219     void JackNetWinSocket::SetPort ( int port )
00220     {
00221         fPort = port;
00222         fSendAddr.sin_port = htons ( port );
00223         fRecvAddr.sin_port = htons ( port );
00224     }
00225 
00226     int JackNetWinSocket::GetPort()
00227     {
00228         return fPort;
00229     }
00230 
00231     //address***********************************************************************************************************
00232     int JackNetWinSocket::SetAddress ( const char* ip, int port )
00233     {
00234         fSendAddr.sin_addr.s_addr = inet_addr ( ip );
00235         fSendAddr.sin_port = htons ( port );
00236         return 0;
00237     }
00238 
00239     char* JackNetWinSocket::GetSendIP()
00240     {
00241         return inet_ntoa ( fSendAddr.sin_addr );
00242     }
00243 
00244     char* JackNetWinSocket::GetRecvIP()
00245     {
00246         return inet_ntoa ( fRecvAddr.sin_addr );
00247     }
00248 
00249     //utility************************************************************************************************************
00250     int JackNetWinSocket::GetName ( char* name )
00251     {
00252         return gethostname ( name, 255 );
00253     }
00254 
00255     int JackNetWinSocket::JoinMCastGroup ( const char* ip )
00256     {
00257         struct ip_mreq multicast_req;
00258         multicast_req.imr_multiaddr.s_addr = inet_addr ( ip );
00259         multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY );
00260         //12 is IP_ADD_MEMBERSHIP in winsock2 (differs from winsock1...)
00261         return SetOption ( IPPROTO_IP, 12, &multicast_req, sizeof ( multicast_req ) );
00262     }
00263 
00264     //options************************************************************************************************************
00265     int JackNetWinSocket::SetOption ( int level, int optname, const void* optval, SOCKLEN optlen )
00266     {
00267         return setsockopt ( fSockfd, level, optname, static_cast<const char*> ( optval ), optlen );
00268     }
00269 
00270     int JackNetWinSocket::GetOption ( int level, int optname, void* optval, SOCKLEN* optlen )
00271     {
00272         return getsockopt ( fSockfd, level, optname, static_cast<char*> ( optval ), optlen );
00273     }
00274 
00275     //tiemout************************************************************************************************************
00276     int JackNetWinSocket::SetTimeOut ( int usec )
00277     {
00278         jack_log ( "JackNetWinSocket::SetTimeout %d usec", usec );
00279 
00280         //negative timeout, or exceeding 10s, return
00281         if ( ( usec < 0 ) || ( usec > 10000000 ) )
00282             return SOCKET_ERROR;
00283         int time = usec / 1000;
00284         return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &time, sizeof ( time ) );
00285     }
00286 
00287     //local loop*********************************************************************************************************
00288     int JackNetWinSocket::SetLocalLoop()
00289     {
00290         //char disable = 0;
00291         /*
00292         see http://msdn.microsoft.com/en-us/library/aa916098.aspx
00293         Default value is TRUE. When TRUE, data that is sent from the local interface to the multicast group to
00294         which the socket is joined, including data sent from the same socket, will be echoed to its receive buffer.
00295         */
00296         char disable = 1;
00297         return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) );
00298     }
00299 
00300     //network operations*************************************************************************************************
00301     int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags )
00302     {
00303         return sendto ( fSockfd, reinterpret_cast<const char*> ( buffer ), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) );
00304     }
00305 
00306     int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip )
00307     {
00308         fSendAddr.sin_addr.s_addr = inet_addr ( ip );
00309         return SendTo ( buffer, nbytes, flags );
00310     }
00311 
00312     int JackNetWinSocket::Send ( const void* buffer, size_t nbytes, int flags )
00313     {
00314         return send ( fSockfd, reinterpret_cast<const char*> ( buffer ), nbytes, flags );
00315     }
00316 
00317     int JackNetWinSocket::RecvFrom ( void* buffer, size_t nbytes, int flags )
00318     {
00319         SOCKLEN addr_len = sizeof ( SOCKADDR );
00320         return recvfrom ( fSockfd, reinterpret_cast<char*> ( buffer ), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), &addr_len );
00321     }
00322 
00323     int JackNetWinSocket::Recv ( void* buffer, size_t nbytes, int flags )
00324     {
00325         return recv ( fSockfd, reinterpret_cast<char*> ( buffer ), nbytes, flags );
00326     }
00327 
00328     int JackNetWinSocket::CatchHost ( void* buffer, size_t nbytes, int flags )
00329     {
00330         SOCKLEN addr_len = sizeof ( SOCKADDR );
00331         return recvfrom ( fSockfd, reinterpret_cast<char*> ( buffer ), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), &addr_len );
00332     }
00333 
00334     net_error_t JackNetWinSocket::GetError()
00335     {
00336         switch ( NET_ERROR_CODE )
00337         {
00338             case WSABASEERR:
00339                 return NET_NO_ERROR;
00340             case WSAETIMEDOUT:
00341                 return NET_NO_DATA;
00342             case WSAEWOULDBLOCK:
00343                 return NET_NO_DATA;
00344             case WSAECONNREFUSED:
00345                 return NET_CONN_ERROR;
00346             case WSAECONNRESET:
00347                 return NET_CONN_ERROR;
00348             case WSAEACCES:
00349                 return NET_CONN_ERROR;
00350             case WSAECONNABORTED:
00351                 return NET_CONN_ERROR;
00352             case WSAEHOSTDOWN:
00353                 return NET_CONN_ERROR;
00354             case WSAEHOSTUNREACH:
00355                 return NET_CONN_ERROR;
00356             default:
00357                 return NET_OP_ERROR;
00358         }
00359     }
00360 }
00361