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