Jack2  1.9.8
JackNetUnixSocket.cpp
00001 /*
00002 Copyright (C) 2008-2011 Romain Moret at Grame
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 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 General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackNetUnixSocket.h"
00021 #include <unistd.h>
00022 #include <fcntl.h>
00023 
00024 namespace Jack
00025 {
00026     //utility *********************************************************************************************************
00027     int GetHostName(char * name, int size)
00028     {
00029         if (gethostname(name, size) == SOCKET_ERROR) {
00030             jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
00031             strcpy(name, "default");
00032             return SOCKET_ERROR;
00033         }
00034         return 0;
00035     }
00036 
00037     //construct/destruct***********************************************************************************************
00038     JackNetUnixSocket::JackNetUnixSocket()
00039     {
00040         fSockfd = 0;
00041         fPort = 0;
00042         fTimeOut = 0;
00043         fSendAddr.sin_family = AF_INET;
00044         fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00045         memset(&fSendAddr.sin_zero, 0, 8);
00046         fRecvAddr.sin_family = AF_INET;
00047         fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00048         memset(&fRecvAddr.sin_zero, 0, 8);
00049     }
00050 
00051     JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
00052     {
00053         fSockfd = 0;
00054         fPort = port;
00055         fTimeOut = 0;
00056         fSendAddr.sin_family = AF_INET;
00057         fSendAddr.sin_port = htons(port);
00058         inet_aton(ip, &fSendAddr.sin_addr);
00059         memset(&fSendAddr.sin_zero, 0, 8);
00060         fRecvAddr.sin_family = AF_INET;
00061         fRecvAddr.sin_port = htons(port);
00062         fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00063         memset(&fRecvAddr.sin_zero, 0, 8);
00064     }
00065 
00066     JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
00067     {
00068         fSockfd = 0;
00069         fTimeOut = 0;
00070         fPort = socket.fPort;
00071         fSendAddr = socket.fSendAddr;
00072         fRecvAddr = socket.fRecvAddr;
00073     }
00074 
00075     JackNetUnixSocket::~JackNetUnixSocket()
00076     {
00077         Close();
00078     }
00079 
00080     JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
00081     {
00082         if (this != &socket) {
00083             fSockfd = 0;
00084             fPort = socket.fPort;
00085             fSendAddr = socket.fSendAddr;
00086             fRecvAddr = socket.fRecvAddr;
00087         }
00088         return *this;
00089     }
00090 
00091     //socket***********************************************************************************************************
00092     int JackNetUnixSocket::NewSocket()
00093     {
00094         if (fSockfd) {
00095             Close();
00096             Reset();
00097         }
00098         fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
00099 
00100         /* Enable address reuse */
00101         int res, on = 1;
00102     #ifdef __APPLE__
00103         if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) < 0) {
00104     #else
00105         if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
00106     #endif
00107             StrError(NET_ERROR_CODE);
00108         }
00109         return fSockfd;
00110     }
00111 
00112     bool JackNetUnixSocket::IsLocal(char* ip)
00113     {
00114         if (strcmp(ip, "127.0.0.1") == 0) {
00115             return true;
00116         }
00117 
00118         char host_name[32];
00119         gethostname(host_name, sizeof(host_name));
00120 
00121         struct hostent* host = gethostbyname(host_name);
00122         if (host) {
00123             for (int i = 0; host->h_addr_list[i] != 0; ++i) {
00124                 struct in_addr addr;
00125                 memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
00126                 if (strcmp(inet_ntoa(addr), ip) == 0) {
00127                     return true;
00128                 }
00129             }
00130             return false;
00131         } else {
00132             return false;
00133         }
00134     }
00135 
00136     int JackNetUnixSocket::Bind()
00137     {
00138         return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t));
00139     }
00140 
00141     int JackNetUnixSocket::BindWith(const char* ip)
00142     {
00143         int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr);
00144         if (addr_conv < 0)
00145             return addr_conv;
00146         return Bind();
00147     }
00148 
00149     int JackNetUnixSocket::BindWith(int port)
00150     {
00151         fRecvAddr.sin_port = htons(port);
00152         return Bind();
00153     }
00154 
00155     int JackNetUnixSocket::Connect()
00156     {
00157         return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
00158     }
00159 
00160     int JackNetUnixSocket::ConnectTo(const char* ip)
00161     {
00162         int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
00163         if (addr_conv < 0)
00164             return addr_conv;
00165         return Connect();
00166     }
00167 
00168     void JackNetUnixSocket::Close()
00169     {
00170         if (fSockfd)
00171             close(fSockfd);
00172         fSockfd = 0;
00173     }
00174 
00175     void JackNetUnixSocket::Reset()
00176     {
00177         fSendAddr.sin_family = AF_INET;
00178         fSendAddr.sin_port = htons(fPort);
00179         fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00180         memset(&fSendAddr.sin_zero, 0, 8);
00181         fRecvAddr.sin_family = AF_INET;
00182         fRecvAddr.sin_port = htons(fPort);
00183         fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00184         memset(&fRecvAddr.sin_zero, 0, 8);
00185     }
00186 
00187     bool JackNetUnixSocket::IsSocket()
00188     {
00189         return(fSockfd) ? true : false;
00190     }
00191 
00192     //IP/PORT***********************************************************************************************************
00193     void JackNetUnixSocket::SetPort(int port)
00194     {
00195         fPort = port;
00196         fSendAddr.sin_port = htons(port);
00197         fRecvAddr.sin_port = htons(port);
00198     }
00199 
00200     int JackNetUnixSocket::GetPort()
00201     {
00202         return fPort;
00203     }
00204 
00205     //address***********************************************************************************************************
00206     int JackNetUnixSocket::SetAddress(const char* ip, int port)
00207     {
00208         int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
00209         if (addr_conv < 0)
00210             return addr_conv;
00211         fSendAddr.sin_port = htons(port);
00212         return 0;
00213     }
00214 
00215     char* JackNetUnixSocket::GetSendIP()
00216     {
00217         return inet_ntoa(fSendAddr.sin_addr);
00218     }
00219 
00220     char* JackNetUnixSocket::GetRecvIP()
00221     {
00222         return inet_ntoa(fRecvAddr.sin_addr);
00223     }
00224 
00225     //utility************************************************************************************************************
00226     int JackNetUnixSocket::GetName(char* name)
00227     {
00228         return gethostname(name, 255);
00229     }
00230 
00231     int JackNetUnixSocket::JoinMCastGroup(const char* ip)
00232     {
00233         struct ip_mreq multicast_req;
00234         inet_aton(ip, &multicast_req.imr_multiaddr);
00235         multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
00236         return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
00237     }
00238 
00239     //options************************************************************************************************************
00240     int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
00241     {
00242         return setsockopt(fSockfd, level, optname, optval, optlen);
00243     }
00244 
00245     int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
00246     {
00247         return getsockopt(fSockfd, level, optname, optval, optlen);
00248     }
00249 
00250     //timeout************************************************************************************************************
00251 
00252 #if defined(__sun__) || defined(sun)
00253     int JackNetUnixSocket::SetTimeOut(int us)
00254     {
00255         int     flags;
00256         fTimeOut = us;
00257 
00258         if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
00259                     jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
00260                     return -1;
00261             }
00262 
00263             flags |= O_NONBLOCK;
00264             if (fcntl(fSockfd, F_SETFL, flags) < 0) {
00265                     jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
00266                     return 1;
00267             }
00268 
00269         return 0;
00270     }
00271 
00272     int JackNetUnixSocket::WaitRead()
00273     {
00274         if (fTimeOut > 0) {
00275 
00276             struct timeval tv;
00277                 fd_set fdset;
00278             ssize_t     res;
00279 
00280             tv.tv_sec = fTimeOut / 1000000;
00281                 tv.tv_usec = fTimeOut % 1000000;
00282 
00283                 FD_ZERO(&fdset);
00284                 FD_SET(fSockfd, &fdset);
00285 
00286                 do {
00287                         res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
00288                 } while(res < 0 && errno == EINTR);
00289 
00290                 if (res < 0) {
00291                         return res;
00292             } else if (res == 0) {
00293                 errno = ETIMEDOUT;
00294                         return -1;
00295                 }
00296         }
00297 
00298         return 0;
00299     }
00300 
00301     int JackNetUnixSocket::WaitWrite()
00302     {
00303         if (fTimeOut > 0) {
00304 
00305             struct timeval tv;
00306                 fd_set fdset;
00307             ssize_t     res;
00308 
00309             tv.tv_sec = fTimeOut / 1000000;
00310             tv.tv_usec = fTimeOut % 1000000;
00311 
00312                 FD_ZERO(&fdset);
00313                 FD_SET(fSockfd, &fdset);
00314 
00315                 do {
00316                         res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
00317                 } while(res < 0 && errno == EINTR);
00318 
00319                 if (res < 0) {
00320                         return res;
00321             } else if (res == 0) {
00322                 errno = ETIMEDOUT;
00323                         return -1;
00324                 }
00325         }
00326 
00327         return 0;
00328     }
00329 
00330 #else
00331     int JackNetUnixSocket::SetTimeOut(int us)
00332     {
00333         jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
00334 
00335         //negative timeout, or exceding 10s, return
00336         if ((us < 0) ||(us > 10000000))
00337             return SOCKET_ERROR;
00338         struct timeval timeout;
00339 
00340         //less than 1sec
00341         if (us < 1000000) {
00342             timeout.tv_sec = 0;
00343             timeout.tv_usec = us;
00344         } else {
00345         //more than 1sec
00346             float sec = static_cast<float>(us) / 1000000.f;
00347             timeout.tv_sec =(int) sec;
00348             float usec = (sec - static_cast<float>(timeout.tv_sec)) * 1000000;
00349             timeout.tv_usec =(int) usec;
00350         }
00351         return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
00352     }
00353 #endif
00354 
00355     //local loop**********************************************************************************************************
00356     int JackNetUnixSocket::SetLocalLoop()
00357     {
00358         char disable = 0;
00359         return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
00360     }
00361 
00362     //network operations**************************************************************************************************
00363     int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
00364     {
00365     #if defined(__sun__) || defined(sun)
00366         if (WaitWrite() < 0)
00367             return -1;
00368     #endif
00369         return sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
00370     }
00371 
00372     int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
00373     {
00374         int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
00375         if (addr_conv < 1)
00376             return addr_conv;
00377     #if defined(__sun__) || defined(sun)
00378         if (WaitWrite() < 0)
00379             return -1;
00380     #endif
00381         return SendTo(buffer, nbytes, flags);
00382     }
00383 
00384     int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
00385     {
00386     #if defined(__sun__) || defined(sun)
00387         if (WaitWrite() < 0)
00388             return -1;
00389     #endif
00390         return send(fSockfd, buffer, nbytes, flags);
00391     }
00392 
00393     int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
00394     {
00395         socklen_t addr_len = sizeof(socket_address_t);
00396     #if defined(__sun__) || defined(sun)
00397         if (WaitRead() < 0)
00398             return -1;
00399     #endif
00400         return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len);
00401     }
00402 
00403     int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
00404     {
00405     #if defined(__sun__) || defined(sun)
00406         if (WaitRead() < 0)
00407             return -1;
00408     #endif
00409         return recv(fSockfd, buffer, nbytes, flags);
00410     }
00411 
00412     int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags)
00413     {
00414         socklen_t addr_len = sizeof(socket_address_t);
00415     #if defined(__sun__) || defined(sun)
00416         if (WaitRead() < 0)
00417             return -1;
00418     #endif
00419         return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len);
00420     }
00421 
00422     net_error_t JackNetUnixSocket::GetError()
00423     {
00424         switch(errno)
00425         {
00426             case EAGAIN:
00427             case ETIMEDOUT:
00428                 return NET_NO_DATA;
00429 
00430             case ECONNABORTED:
00431             case ECONNREFUSED:
00432             case ECONNRESET:
00433             case EINVAL:
00434             case EHOSTDOWN:
00435             case EHOSTUNREACH:
00436             case ENETDOWN:
00437             case ENETUNREACH:
00438                 return NET_CONN_ERROR;
00439 
00440             default:
00441                 //return NET_OP_ERROR;
00442                 return NET_CONN_ERROR;
00443         }
00444     }
00445 }