jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

812 lines
28KB

  1. /*
  2. Copyright (C) 2008-2011 Romain Moret at Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackNetUnixSocket.h"
  16. #include "JackError.h"
  17. #include <arpa/inet.h>
  18. #include <sys/socket.h>
  19. #include <ifaddrs.h>
  20. #include <net/if.h>
  21. #include <unistd.h>
  22. #include <fcntl.h>
  23. using namespace std;
  24. // See RFC 3493; The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition
  25. #define _sock4(x) (*(struct sockaddr_in *)&x)
  26. #define _sock6(x) (*(struct sockaddr_in6*)&x)
  27. #define _ss_addr_p(x) ((fFamily==AF_INET6) ? \
  28. (void*)&(((struct sockaddr_in6*)&x)->sin6_addr) \
  29. : (void*)&(((struct sockaddr_in *)&x)->sin_addr))
  30. #define JNS_UNSPEC 0x0
  31. #define JNS_PROBED 0x1
  32. #define JNS_BOUND 0x2
  33. #define JNS_CONNCD 0x4
  34. #define JNS_MCAST 0x10
  35. namespace Jack
  36. {
  37. //utility *********************************************************************************************************
  38. int GetHostName(char * name, int size)
  39. {
  40. if (gethostname(name, size) == SOCKET_ERROR) {
  41. jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
  42. strcpy(name, "default");
  43. return SOCKET_ERROR;
  44. }
  45. return 0;
  46. }
  47. //construct/destruct***********************************************************************************************
  48. JackNetUnixSocket::JackNetUnixSocket()
  49. : fFamily(AF_UNSPEC), fSockfd(0), fState(JNS_UNSPEC), fPort(0), fTimeOut(0)
  50. {
  51. Reset();
  52. }
  53. JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
  54. : fFamily(AF_UNSPEC), fSockfd(0), fState(JNS_UNSPEC), fPort(0), fTimeOut(0)
  55. {
  56. Reset();
  57. fPort = port;
  58. if(NewSocket(ip)==SOCKET_ERROR)
  59. jack_error("JackNetUnixSocket::JackNetUnixSocket Cannot initialize (%s:%d): %s",ip,port,strerror(NET_ERROR_CODE));
  60. }
  61. JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
  62. {
  63. Clone(socket);
  64. }
  65. JackNetUnixSocket::~JackNetUnixSocket()
  66. {
  67. Close();
  68. }
  69. JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
  70. {
  71. if (this != &socket)
  72. Clone(socket);
  73. return *this;
  74. }
  75. //socket***********************************************************************************************************
  76. void JackNetUnixSocket::Clone(const JackNetUnixSocket& socket)
  77. {
  78. fSockfd = 0;
  79. fTimeOut = 0;
  80. fPort = socket.fPort;
  81. fFamily = socket.fFamily;
  82. fState = socket.fState;
  83. fState &= (JNS_MCAST | JNS_PROBED); // Reset all fields except mcast and probed
  84. memcpy(&fSendAddr, & socket.fSendAddr, sizeof(fSendAddr));
  85. memcpy(&fRecvAddr, & socket.fRecvAddr, sizeof(fRecvAddr));
  86. }
  87. /* When using Multicast always create socket with new (mip,port) or call NewSocket(mip) for autoinitialized sockets first.
  88. * This makes sure proper workarounds for Multicast incompatibility will be activated while setting up address family.
  89. */
  90. int JackNetUnixSocket::ProbeAF(const char* ip, struct sockaddr_storage *addr, int (*call)(int,const struct sockaddr*,socklen_t))
  91. {
  92. struct addrinfo hint,*res, *ri;
  93. char sport[6];
  94. int ret;
  95. snprintf(sport,6,"%d",fPort);
  96. memset(&hint,0,sizeof(hint));
  97. hint.ai_family = fFamily;
  98. hint.ai_socktype = SOCK_DGRAM;
  99. hint.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_NUMERICSERV;
  100. if(ip == NULL) hint.ai_flags |= AI_PASSIVE;
  101. ret = getaddrinfo(ip,sport,&hint,&res);
  102. if(ret) {
  103. jack_error("JackNetUnixSocket::ProbeAF getaddrinfo(%s:%s): %s",ip,sport,gai_strerror(ret));
  104. return ret;
  105. }
  106. #define GLIBC_BUG
  107. // An ugly GLIBC bug, which one may argue to be RFC bug. See http://sourceware.org/bugzilla/show_bug.cgi?id=14967
  108. #ifdef GLIBC_BUG
  109. // Of course gai configuration can say to have v4 having precedence explicitly but... here we prefer ipv6. period
  110. if(!ip && res->ai_family == AF_INET && res->ai_next && res->ai_next->ai_family == AF_INET6) {
  111. jack_log("JackNetUnixSocket::ProbeAF swapping addrinfo entries to work around GLIBC getaddrinfo bug: AF_INET<->AF_INET6");
  112. // Swapping first two entries
  113. ri = res->ai_next;
  114. res->ai_next = ri->ai_next;
  115. ri->ai_next = res;
  116. res = ri;
  117. } else // << Remove up to this very line including once GLIBC is fixed <<
  118. #endif
  119. ri = res;
  120. do {
  121. jack_log("JackNetUnixSocket::ProbeAF trying AF[%d], TYPE[%d], PROTO[%d]",
  122. ri->ai_family,ri->ai_socktype,ri->ai_protocol);
  123. ret = socket(ri->ai_family, ri->ai_socktype, ri->ai_protocol);
  124. if(ret < 0)
  125. continue;
  126. if(!(*call)(ret, ri->ai_addr, ri->ai_addrlen))
  127. break;
  128. close(ret);
  129. jack_log("JackNetUnixSocket::ProbeAF failed for AF[%d], %s",ri->ai_family,(ri->ai_next)?"trying next":"giving up");
  130. } while((ri = ri->ai_next) != NULL);
  131. // probe successfully made a *call on socket for ip represented by ri
  132. if(ri) {
  133. fSockfd = ret;
  134. fFamily = ri->ai_family;
  135. memcpy(addr,ri->ai_addr,ri->ai_addrlen);
  136. jack_log("JackNetUnixSocket::ProbeAF probed[%d] AF[%d] for %s",ret,fFamily,ip);
  137. fState |= JNS_PROBED;
  138. if(fFamily == AF_INET6 && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6*)addr)->sin6_addr))
  139. fState |= JNS_MCAST;
  140. } else
  141. ret = SOCKET_ERROR;
  142. freeaddrinfo(res);
  143. return ret;
  144. }
  145. int JackNetUnixSocket::NewSocket()
  146. {
  147. return NewSocket(NULL);
  148. }
  149. int JackNetUnixSocket::NewSocket(const char *ip)
  150. {
  151. if(fFamily == AF_UNSPEC) {
  152. if(ip) {
  153. if(ProbeAF(ip,&fSendAddr,connect)<0)
  154. return SOCKET_ERROR;
  155. } else {
  156. if(ProbeAF(ip,&fRecvAddr,bind)<0)
  157. return SOCKET_ERROR;
  158. // It should be with AF/port/ANY after bind
  159. memcpy(&fSendAddr,&fRecvAddr,sizeof(fRecvAddr));
  160. }
  161. // Now re-create the fd to get a brand-new unnamed socket
  162. }
  163. if (fSockfd) {
  164. Close();
  165. Reset();
  166. }
  167. fSockfd = socket(fFamily, SOCK_DGRAM, 0);
  168. /* Enable address reuse */
  169. int res, on = 1;
  170. #ifdef __APPLE__
  171. if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) < 0) {
  172. #else
  173. if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
  174. #endif
  175. StrError(NET_ERROR_CODE);
  176. }
  177. int tos = 0; /* see <netinet/in.h> */
  178. /*
  179. DSCP Field Hex/Bin/Dec Layer 2 Prio Traffic Type Acronym WMM Access Category
  180. 0x38 / 111000 / 56 7 Network Control NC AC_VO
  181. 0x30 / 110000 / 48 6 Voice VO AC_VO
  182. 0x28 / 101000 / 40 5 Video VI AC_VI
  183. 0x20 / 100000 / 32 4 Controlled Load CL AC_VI
  184. 0x18 / 011000 / 24 3 Excellent Effort EE AC_BE
  185. 0x10 / 010000 / 16 2 Spare -- AC_BK
  186. 0x08 / 001000 / 8 1 Background BK AC_BK
  187. 0x00 / 000000 / 0 0 Best Effort BE AC_BE
  188. */
  189. socklen_t len = sizeof(tos);
  190. res = getsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, &len);
  191. tos = 46 * 4; // see <netinet/in.h>
  192. res = setsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
  193. return fSockfd;
  194. }
  195. bool JackNetUnixSocket::IsLocal(char* ip)
  196. {
  197. if (strcmp(ip, "127.0.0.1") == 0) {
  198. return true;
  199. } else if(!strcmp(ip,"::1"))
  200. return true;
  201. struct ifaddrs *ifas, *ifa;
  202. socklen_t len;
  203. if (getifaddrs(&ifas) == -1) {
  204. jack_error("JackNetUnixSocket::IsLocal error in getifaddrs");
  205. return false;
  206. }
  207. for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
  208. if (ifa->ifa_addr == NULL)
  209. continue; // Address is mandatory
  210. len = (ifa->ifa_addr->sa_family==AF_INET)?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6);
  211. if(!getnameinfo(ifa->ifa_addr, len, f_addr_buff, INET6_ADDRSTRLEN, NULL,0, NI_NUMERICSERV | NI_DGRAM | NI_NUMERICSERV | NI_DGRAM | NI_NUMERICHOST))
  212. if(!strcmp(f_addr_buff,ip))
  213. break;
  214. }
  215. freeifaddrs(ifas);
  216. return (ifa != NULL);
  217. }
  218. int JackNetUnixSocket::Bind()
  219. {
  220. int yes=1;
  221. if(fState & JNS_BOUND) return 0;
  222. // Multicast is incompatible with V4MAPPED or V4COMPAT addresses, if probe detected MC we need V6ONLY
  223. if(fFamily == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&_sock6(fRecvAddr).sin6_addr) && fState & JNS_MCAST)
  224. if(SetOption(IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes))) return SOCKET_ERROR;
  225. if(::bind(fSockfd, reinterpret_cast<struct sockaddr*>(&fRecvAddr), sizeof(fRecvAddr))) return SOCKET_ERROR;
  226. fState |= JNS_BOUND;
  227. return 0;
  228. }
  229. int JackNetUnixSocket::Bind(const char *if_name)
  230. {
  231. int ret = Bind();
  232. if(!ret && strcmp(if_name,"any")) {
  233. if(fFamily == AF_INET) {
  234. // 'all' for this case will lead to 'last valid interface', which is not that one might expect
  235. if(strcmp(if_name,"all"))
  236. ret = BindMCastIface(if_name, IP_MULTICAST_IF, &_sock4(fSendAddr).sin_addr);
  237. else
  238. jack_error("Multicast Interface all not found, sending from default");
  239. } else if(fFamily == AF_INET6) {
  240. struct if_nameindex *if_ni = if_nameindex(); // In V6 world we do everything differently.
  241. if(if_ni) {
  242. int i;
  243. for (i=0; if_ni[i].if_index > 0; i++) {
  244. if(if_ni[i].if_index == 1)
  245. continue; // Skip loopback
  246. if(!strcmp(if_ni[i].if_name,if_name)) {
  247. ret = SetOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_ni[i].if_index, sizeof(if_ni[i].if_index));
  248. jack_log("JackNetUnixSocket::Bind Multicasting from %s",if_ni[i].if_name);
  249. break;
  250. }
  251. }
  252. if(if_ni[i].if_index == 0) jack_error("Multicast Interface %s not found, sending from default",if_name);
  253. if_freenameindex(if_ni);
  254. }
  255. }
  256. }
  257. return ret;
  258. }
  259. int JackNetUnixSocket::BindWith(const char* ip)
  260. {
  261. if(fFamily == AF_UNSPEC) {
  262. if(!fPort) return SOCKET_ERROR;
  263. if(ProbeAF(ip,&fRecvAddr,&bind)<0) return SOCKET_ERROR;
  264. fState |= JNS_BOUND;
  265. return 0;
  266. } else {
  267. if(SetRecvIP(ip)==-1) return SOCKET_ERROR;
  268. return Bind();
  269. }
  270. }
  271. int JackNetUnixSocket::BindWith(int port)
  272. {
  273. if(fFamily == AF_UNSPEC) {
  274. fPort = port;
  275. if(ProbeAF(NULL,&fRecvAddr,&bind)<0) return SOCKET_ERROR;
  276. fState |= JNS_BOUND;
  277. return 0;
  278. } else {
  279. SetPort(port);
  280. return Bind();
  281. }
  282. }
  283. int JackNetUnixSocket::Connect()
  284. {
  285. if(fFamily != AF_UNSPEC)
  286. return connect(fSockfd, (struct sockaddr*)&fSendAddr,sizeof(fSendAddr));
  287. jack_error("JackNetUnixSocket::Connect Family not initialized");
  288. return SOCKET_ERROR;
  289. }
  290. int JackNetUnixSocket::ConnectTo(const char* ip)
  291. {
  292. socklen_t l=sizeof(fRecvAddr);
  293. if(fPort==0) return SOCKET_ERROR;
  294. if(fState & JNS_PROBED) {
  295. Reset();
  296. fFamily=AF_UNSPEC;
  297. }
  298. if(fSockfd)
  299. Close();
  300. if(ProbeAF(ip,&fSendAddr,&connect)<0) return SOCKET_ERROR;
  301. fState |= JNS_CONNCD;
  302. return getsockname(fSockfd, (struct sockaddr *)&fRecvAddr, &l);
  303. }
  304. void JackNetUnixSocket::Close()
  305. {
  306. if (fSockfd) {
  307. close(fSockfd);
  308. }
  309. fSockfd = 0;
  310. fState = JNS_UNSPEC;
  311. }
  312. void JackNetUnixSocket::Reset()
  313. {
  314. memset(&fSendAddr, 0, sizeof(fSendAddr));
  315. fSendAddr.ss_family = fFamily;
  316. memset(&fRecvAddr, 0, sizeof(fRecvAddr));
  317. fRecvAddr.ss_family = fFamily;
  318. if(fPort)
  319. SetPort(fPort);
  320. }
  321. bool JackNetUnixSocket::IsSocket()
  322. {
  323. return(fSockfd) ? true : false;
  324. }
  325. //IP/PORT***********************************************************************************************************
  326. void JackNetUnixSocket::SetPort(int port)
  327. {
  328. fPort = port;
  329. switch(fFamily) { // Playing dumb here, in fact port section of both sockaddrs is compatible
  330. case AF_INET:
  331. _sock4(fSendAddr).sin_port = htons(port);
  332. _sock4(fRecvAddr).sin_port = htons(port);
  333. break;
  334. case AF_INET6:
  335. _sock6(fSendAddr).sin6_port = htons(port);
  336. _sock6(fRecvAddr).sin6_port = htons(port);
  337. break;
  338. default:
  339. jack_info("JackNetUnixSocket::SetPort: Family not initialized");
  340. }
  341. }
  342. int JackNetUnixSocket::GetPort()
  343. {
  344. return fPort;
  345. }
  346. //address***********************************************************************************************************
  347. int JackNetUnixSocket::SetAddress(const char* ip, int port)
  348. {
  349. if(fFamily == AF_UNSPEC) {
  350. fPort=port;
  351. return ProbeAF(ip,&fSendAddr,&connect);
  352. } else {
  353. SetPort(port);
  354. return inet_pton(fFamily, ip, _ss_addr_p(fSendAddr));
  355. }
  356. }
  357. int JackNetUnixSocket::SetSendIP(const char *ip)
  358. {
  359. if(fFamily == AF_UNSPEC) return -1;
  360. return inet_pton(fFamily, ip, _ss_addr_p(fSendAddr));
  361. }
  362. char* JackNetUnixSocket::GetSendIP()
  363. {
  364. return (char*)inet_ntop(fFamily, _ss_addr_p(fSendAddr),f_addr_buff,INET6_ADDRSTRLEN);
  365. }
  366. int JackNetUnixSocket::SetRecvIP(const char *ip)
  367. {
  368. if(fFamily == AF_UNSPEC) return -1;
  369. return inet_pton(fFamily, ip, _ss_addr_p(fRecvAddr));
  370. }
  371. char* JackNetUnixSocket::GetRecvIP()
  372. {
  373. return (char*)inet_ntop(fFamily, _ss_addr_p(fRecvAddr),f_addr_buff,INET6_ADDRSTRLEN);
  374. }
  375. //utility************************************************************************************************************
  376. int JackNetUnixSocket::GetName(char* name)
  377. {
  378. return gethostname(name, 255);
  379. }
  380. int JackNetUnixSocket::JoinMCastGroup(const char* ip)
  381. {
  382. return JoinMCastGroup(ip,"any");
  383. }
  384. /** Glory and shame of IPv6 interoperability: Multicast
  385. * Not only API is completely incompatible, but even socket is incompatible. I.e. you cannot use V4MAPPED/COMPATIBLE
  386. * sockets/sockaddress for Multicast. Any V4 address is just a legacy unicast socket for IPv6. Moreover, IPv6 API
  387. * implementation itself is a big mess even though there's no time anymore and way back. Here we're using POSIX API.
  388. * When dealing with Multicast - Address Family should be set once and forever for used multicast address. This
  389. * implies we cannot use V4 addresses on V6 sockets. So multicast should have V6ONLY soscket option set to allow v6
  390. * adapter, master or manager coexist on the same host. See ProbeAF/Bind for these tricks.
  391. */
  392. int JackNetUnixSocket::JoinMCastGroup(const char* ip, const char *if_name)
  393. {
  394. int level, option, length;
  395. void *mreq;
  396. char addr[sizeof(in6_addr)];
  397. inet_pton(fFamily, ip, addr);
  398. if(!strcmp(if_name,"any")) { // UNSPEC binding we can do in-place using void pointers
  399. if(fFamily == AF_INET) {
  400. struct ip_mreq multicast_req;
  401. multicast_req.imr_multiaddr.s_addr = *(uint32_t*)(addr);
  402. multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
  403. level = IPPROTO_IP;
  404. option = IP_ADD_MEMBERSHIP;
  405. mreq=&multicast_req;
  406. length = sizeof(ip_mreq);
  407. } else if(fFamily == AF_INET6) {
  408. struct ipv6_mreq mreq6;
  409. memcpy(&mreq6.ipv6mr_multiaddr,addr,sizeof(in6_addr));
  410. mreq6.ipv6mr_interface = 0;
  411. level = IPPROTO_IPV6;
  412. option = IPV6_JOIN_GROUP;
  413. mreq = &mreq6;
  414. length = sizeof(ipv6_mreq);
  415. } else {
  416. jack_error("Unsupported family[%d]",fFamily);
  417. return -1;
  418. }
  419. return SetOption(level, option, mreq, length);
  420. } else { // For anything more complex need to call family-specific routine
  421. if(fFamily == AF_INET)
  422. return BindMCastIface(if_name, IP_ADD_MEMBERSHIP, (struct in_addr *)addr);
  423. else if(fFamily == AF_INET6)
  424. return BindMCast6Iface(if_name, (struct in6_addr *)addr);
  425. else {
  426. jack_error("Unsupported family[%d]",fFamily);
  427. return -1;
  428. }
  429. }
  430. }
  431. int JackNetUnixSocket::BindMCastIface(const char *if_name, const int option, struct in_addr *addr)
  432. {
  433. struct ifaddrs *ifas, *ifa;
  434. struct ip_mreq mreq;
  435. int specific = strcmp("all",if_name);
  436. int ret=-1;
  437. char *if_last=(char *)"any";
  438. if (getifaddrs(&ifas) == -1) {
  439. jack_error("JackNetUnixSocket::BindMCastIface error in getifaddrs");
  440. return -1;
  441. }
  442. mreq.imr_multiaddr.s_addr = addr->s_addr;
  443. for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
  444. if (ifa->ifa_addr == NULL)
  445. continue; // Address is mandatory
  446. if(!ifa->ifa_name || !strcmp(if_last,ifa->ifa_name))
  447. continue; // Name as well, also skip already enabled interface
  448. if(!(ifa->ifa_flags & IFF_MULTICAST) || !(ifa->ifa_flags & IFF_RUNNING))
  449. continue; // And non multicast or down interface
  450. if(ifa->ifa_addr->sa_family != AF_INET)
  451. continue; // And non-matching family
  452. if(!specific || !strcmp(ifa->ifa_name,if_name)) {
  453. mreq.imr_interface.s_addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr;
  454. ret = SetOption(IPPROTO_IP, option, &mreq, sizeof(struct ip_mreq));
  455. if(ret)
  456. break;
  457. if_last = ifa->ifa_name;
  458. jack_log("JackNetUnixSocket::BindMCastIface attaching to %s", if_last);
  459. }
  460. }
  461. freeifaddrs(ifas);
  462. if(!strcmp(if_last,"any"))
  463. jack_error("JackNetUnixSocket::BindMCastIface cannot find valid interface");
  464. return ret;
  465. }
  466. int JackNetUnixSocket::BindMCast6Iface(const char *if_name, struct in6_addr *mip)
  467. {
  468. int i, ret=-1, specific=strcmp("all",if_name);
  469. struct if_nameindex *if_ni = if_nameindex();
  470. struct ipv6_mreq mreq;
  471. if(if_ni) {
  472. memcpy(&mreq.ipv6mr_multiaddr, mip, sizeof(struct in6_addr));
  473. for (i=0; if_ni[i].if_index > 0; i++) {
  474. if(if_ni[i].if_index == 1)
  475. continue; // Skip loopback
  476. mreq.ipv6mr_interface = if_ni[i].if_index;
  477. if(!specific || !strcmp(if_ni[i].if_name,if_name)) {
  478. ret = SetOption(IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq));
  479. if(ret < 0)
  480. break;
  481. }
  482. }
  483. if_freenameindex(if_ni);
  484. }
  485. return ret;
  486. }
  487. //options************************************************************************************************************
  488. int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
  489. {
  490. return setsockopt(fSockfd, level, optname, optval, optlen);
  491. }
  492. int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
  493. {
  494. return getsockopt(fSockfd, level, optname, optval, optlen);
  495. }
  496. //timeout************************************************************************************************************
  497. #if defined(__sun__) || defined(sun)
  498. int JackNetUnixSocket::SetTimeOut(int us)
  499. {
  500. int flags;
  501. fTimeOut = us;
  502. if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
  503. jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
  504. return -1;
  505. }
  506. flags |= O_NONBLOCK;
  507. if (fcntl(fSockfd, F_SETFL, flags) < 0) {
  508. jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
  509. return 1;
  510. }
  511. return 0;
  512. }
  513. int JackNetUnixSocket::WaitRead()
  514. {
  515. if (fTimeOut > 0) {
  516. struct timeval tv;
  517. fd_set fdset;
  518. ssize_t res;
  519. tv.tv_sec = fTimeOut / 1000000;
  520. tv.tv_usec = fTimeOut % 1000000;
  521. FD_ZERO(&fdset);
  522. FD_SET(fSockfd, &fdset);
  523. do {
  524. res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
  525. } while (res < 0 && errno == EINTR);
  526. if (res < 0) {
  527. return res;
  528. } else if (res == 0) {
  529. errno = ETIMEDOUT;
  530. return -1;
  531. }
  532. }
  533. return 0;
  534. }
  535. int JackNetUnixSocket::WaitWrite()
  536. {
  537. if (fTimeOut > 0) {
  538. struct timeval tv;
  539. fd_set fdset;
  540. ssize_t res;
  541. tv.tv_sec = fTimeOut / 1000000;
  542. tv.tv_usec = fTimeOut % 1000000;
  543. FD_ZERO(&fdset);
  544. FD_SET(fSockfd, &fdset);
  545. do {
  546. res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
  547. } while (res < 0 && errno == EINTR);
  548. if (res < 0) {
  549. return res;
  550. } else if (res == 0) {
  551. errno = ETIMEDOUT;
  552. return -1;
  553. }
  554. }
  555. return 0;
  556. }
  557. #else
  558. int JackNetUnixSocket::SetTimeOut(int us)
  559. {
  560. jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
  561. struct timeval timeout;
  562. //less than 1 sec
  563. if (us < 1000000) {
  564. timeout.tv_sec = 0;
  565. timeout.tv_usec = us;
  566. } else {
  567. //more than 1 sec
  568. float sec = float(us) / 1000000.f;
  569. timeout.tv_sec = (int)sec;
  570. float usec = (sec - float(timeout.tv_sec)) * 1000000;
  571. timeout.tv_usec =(int)usec;
  572. }
  573. return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  574. }
  575. #endif
  576. //local loop**********************************************************************************************************
  577. int JackNetUnixSocket::SetLocalLoop()
  578. {
  579. char disable = 0;
  580. unsigned int dis6 = 0;
  581. switch(fFamily) {
  582. case AF_INET:
  583. return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
  584. case AF_INET6:
  585. return SetOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &dis6, sizeof(dis6));
  586. default:
  587. jack_error("JackNetUnixSocket::SetLocalLoop: Family not initialized");
  588. return -1;
  589. }
  590. }
  591. //network operations**************************************************************************************************
  592. int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
  593. {
  594. #if defined(__sun__) || defined(sun)
  595. if (WaitWrite() < 0) {
  596. return -1;
  597. }
  598. #endif
  599. int res;
  600. if ((res = sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<struct sockaddr *>(&fSendAddr), sizeof(fSendAddr))) < 0) {
  601. jack_error("SendTo fd = %ld err = %s", fSockfd, strerror(errno));
  602. }
  603. return res;
  604. }
  605. int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
  606. {
  607. int addr_conv = inet_pton(fFamily, ip, _ss_addr_p(fSendAddr));
  608. if (addr_conv < 1) {
  609. return addr_conv;
  610. }
  611. //fSendAddr.sin_port = htons(fPort);
  612. #if defined(__sun__) || defined(sun)
  613. if (WaitWrite() < 0) {
  614. return -1;
  615. }
  616. #endif
  617. return SendTo(buffer, nbytes, flags);
  618. }
  619. int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
  620. {
  621. #if defined(__sun__) || defined(sun)
  622. if (WaitWrite() < 0) {
  623. return -1;
  624. }
  625. #endif
  626. int res;
  627. if ((res = send(fSockfd, buffer, nbytes, flags)) < 0) {
  628. jack_error("Send fd = %ld err = %s", fSockfd, strerror(errno));
  629. }
  630. return res;
  631. }
  632. int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
  633. {
  634. socklen_t addr_len = sizeof(fRecvAddr);
  635. #if defined(__sun__) || defined(sun)
  636. if (WaitRead() < 0) {
  637. return -1;
  638. }
  639. #endif
  640. int res;
  641. if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<struct sockaddr *>(&fRecvAddr), &addr_len)) < 0) {
  642. jack_error("RecvFrom fd = %ld err = %s", fSockfd, strerror(errno));
  643. }
  644. return res;
  645. }
  646. int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
  647. {
  648. #if defined(__sun__) || defined(sun)
  649. if (WaitRead() < 0) {
  650. return -1;
  651. }
  652. #endif
  653. int res;
  654. if ((res = recv(fSockfd, buffer, nbytes, flags)) < 0) {
  655. jack_error("Recv fd = %ld err = %s", fSockfd, strerror(errno));
  656. }
  657. return res;
  658. }
  659. int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags)
  660. {
  661. jack_log("JackNetUnixSocket::CatchHost");
  662. socklen_t addr_len = sizeof(fSendAddr);
  663. #if defined(__sun__) || defined(sun)
  664. if (WaitRead() < 0) {
  665. return -1;
  666. }
  667. #endif
  668. int res;
  669. if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<struct sockaddr *>(&fSendAddr), &addr_len)) < 0) {
  670. jack_log("CatchHost fd = %ld err = %s", fSockfd, strerror(errno));
  671. }
  672. return res;
  673. }
  674. net_error_t JackNetUnixSocket::GetError()
  675. {
  676. switch (errno) {
  677. case EAGAIN:
  678. case ETIMEDOUT:
  679. return NET_NO_DATA;
  680. case ECONNABORTED:
  681. case ECONNREFUSED:
  682. case ECONNRESET:
  683. case EINVAL:
  684. case EHOSTDOWN:
  685. case EHOSTUNREACH:
  686. case ENETDOWN:
  687. case ENETUNREACH:
  688. return NET_CONN_ERROR;
  689. default:
  690. //return NET_OP_ERROR;
  691. return NET_CONN_ERROR;
  692. }
  693. }
  694. void JackNetUnixSocket::PrintError()
  695. {
  696. switch (errno) {
  697. case EAGAIN:
  698. jack_error("JackNetUnixSocket : EAGAIN");
  699. break;
  700. case ETIMEDOUT:
  701. jack_error("JackNetUnixSocket : ETIMEDOUT");
  702. break;
  703. case ECONNABORTED:
  704. jack_error("JackNetUnixSocket : ECONNABORTED");
  705. break;
  706. case ECONNREFUSED:
  707. jack_error("JackNetUnixSocket : ECONNREFUSED");
  708. break;
  709. case ECONNRESET:
  710. jack_error("JackNetUnixSocket : ECONNRESET");
  711. break;
  712. case EINVAL:
  713. jack_error("JackNetUnixSocket : EINVAL");
  714. break;
  715. case EHOSTDOWN:
  716. jack_error("JackNetUnixSocket : EHOSTDOWN");
  717. break;
  718. case EHOSTUNREACH:
  719. jack_error("JackNetUnixSocket : EHOSTUNREACH");
  720. break;
  721. case ENETDOWN:
  722. jack_error("JackNetUnixSocket : ENETDOWN");
  723. break;
  724. case ENETUNREACH:
  725. jack_error("JackNetUnixSocket : ENETUNREACH");
  726. break;
  727. default:
  728. jack_error("JackNetUnixSocket : %d", errno);
  729. break;
  730. }
  731. }
  732. }