Jack2 1.9.6
|
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 }