Jack2 1.9.6

JackNetUnixSocket.cpp

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