Jack2  1.9.10
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 #include "JackError.h"
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         int millisec = usec / 1000;
00300         return SetOption(SOL_SOCKET, SO_RCVTIMEO, &millisec, sizeof(millisec));
00301     }
00302 
00303     //local loop*********************************************************************************************************
00304     int JackNetWinSocket::SetLocalLoop()
00305     {
00306         //char disable = 0;
00307         /*
00308         see http://msdn.microsoft.com/en-us/library/aa916098.aspx
00309         Default value is TRUE. When TRUE, data that is sent from the local interface to the multicast group to
00310         which the socket is joined, including data sent from the same socket, will be echoed to its receive buffer.
00311         */
00312         char disable = 1;
00313         return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
00314     }
00315 
00316     //network operations*************************************************************************************************
00317     int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags)
00318     {
00319         return sendto(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), sizeof(SOCKADDR));
00320     }
00321 
00322     int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
00323     {
00324         fSendAddr.sin_addr.s_addr = inet_addr(ip);
00325         return SendTo(buffer, nbytes, flags);
00326     }
00327 
00328     int JackNetWinSocket::Send(const void* buffer, size_t nbytes, int flags)
00329     {
00330         return send(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags);
00331     }
00332 
00333     int JackNetWinSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
00334     {
00335         SOCKLEN addr_len = sizeof(SOCKADDR);
00336         return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fRecvAddr), &addr_len);
00337     }
00338 
00339     int JackNetWinSocket::Recv(void* buffer, size_t nbytes, int flags)
00340     {
00341         return recv(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags);
00342     }
00343 
00344     int JackNetWinSocket::CatchHost(void* buffer, size_t nbytes, int flags)
00345     {
00346         SOCKLEN addr_len = sizeof(SOCKADDR);
00347         return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), &addr_len);
00348     }
00349 
00350     net_error_t JackNetWinSocket::GetError()
00351     {
00352         switch (NET_ERROR_CODE)
00353         {
00354             case WSABASEERR:
00355                 return NET_NO_ERROR;
00356             case WSAETIMEDOUT:
00357                 return NET_NO_DATA;
00358             case WSAEWOULDBLOCK:
00359                 return NET_NO_DATA;
00360             case WSAECONNREFUSED:
00361                 return NET_CONN_ERROR;
00362             case WSAECONNRESET:
00363                 return NET_CONN_ERROR;
00364             case WSAEACCES:
00365                 return NET_CONN_ERROR;
00366             case WSAECONNABORTED:
00367                 return NET_CONN_ERROR;
00368             case WSAEHOSTDOWN:
00369                 return NET_CONN_ERROR;
00370             case WSAEHOSTUNREACH:
00371                 return NET_CONN_ERROR;
00372             default:
00373                 return NET_OP_ERROR;
00374         }
00375     }
00376 }
00377