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.

820 lines
29KB

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