Jack2 1.9.8

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