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