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.

604 lines
18KB

  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. namespace Jack
  25. {
  26. //utility *********************************************************************************************************
  27. int GetHostName(char * name, int size)
  28. {
  29. if (gethostname(name, size) == SOCKET_ERROR) {
  30. jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
  31. strcpy(name, "default");
  32. return SOCKET_ERROR;
  33. }
  34. return 0;
  35. }
  36. //construct/destruct***********************************************************************************************
  37. JackNetUnixSocket::JackNetUnixSocket()
  38. {
  39. fSockfd = 0;
  40. fPort = 0;
  41. fTimeOut = 0;
  42. fSendAddr.sin_family = AF_INET;
  43. fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  44. memset(&fSendAddr.sin_zero, 0, 8);
  45. fRecvAddr.sin_family = AF_INET;
  46. fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  47. memset(&fRecvAddr.sin_zero, 0, 8);
  48. }
  49. JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
  50. {
  51. fSockfd = 0;
  52. fPort = port;
  53. fTimeOut = 0;
  54. fSendAddr.sin_family = AF_INET;
  55. fSendAddr.sin_port = htons(port);
  56. inet_aton(ip, &fSendAddr.sin_addr);
  57. memset(&fSendAddr.sin_zero, 0, 8);
  58. fRecvAddr.sin_family = AF_INET;
  59. fRecvAddr.sin_port = htons(port);
  60. fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  61. memset(&fRecvAddr.sin_zero, 0, 8);
  62. }
  63. JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
  64. {
  65. fSockfd = 0;
  66. fTimeOut = 0;
  67. fPort = socket.fPort;
  68. fSendAddr = socket.fSendAddr;
  69. fRecvAddr = socket.fRecvAddr;
  70. }
  71. JackNetUnixSocket::~JackNetUnixSocket()
  72. {
  73. Close();
  74. }
  75. JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
  76. {
  77. if (this != &socket) {
  78. fSockfd = 0;
  79. fPort = socket.fPort;
  80. fSendAddr = socket.fSendAddr;
  81. fRecvAddr = socket.fRecvAddr;
  82. }
  83. return *this;
  84. }
  85. //socket***********************************************************************************************************
  86. int JackNetUnixSocket::NewSocket()
  87. {
  88. if (fSockfd) {
  89. Close();
  90. Reset();
  91. }
  92. fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
  93. /* Enable address reuse */
  94. int res, on = 1;
  95. #ifdef __APPLE__
  96. if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) < 0) {
  97. #else
  98. if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
  99. #endif
  100. StrError(NET_ERROR_CODE);
  101. }
  102. int tos = 0; /* see <netinet/in.h> */
  103. /*
  104. DSCP Field Hex/Bin/Dec Layer 2 Prio Traffic Type Acronym WMM Access Category
  105. 0x38 / 111000 / 56 7 Network Control NC AC_VO
  106. 0x30 / 110000 / 48 6 Voice VO AC_VO
  107. 0x28 / 101000 / 40 5 Video VI AC_VI
  108. 0x20 / 100000 / 32 4 Controlled Load CL AC_VI
  109. 0x18 / 011000 / 24 3 Excellent Effort EE AC_BE
  110. 0x10 / 010000 / 16 2 Spare -- AC_BK
  111. 0x08 / 001000 / 8 1 Background BK AC_BK
  112. 0x00 / 000000 / 0 0 Best Effort BE AC_BE
  113. */
  114. /*
  115. socklen_t len = sizeof(tos);
  116. res = getsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, &len);
  117. printf("getsockopt IPPROTO_IP res = %d tos = %d\n", res, tos);
  118. tos = 46 * 4; // see <netinet/in.h>
  119. res = setsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
  120. printf("setsockopt IPPROTO_IP res = %d tos = %d\n", res, tos );
  121. res = getsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, &len);
  122. printf("getsockopt IPPROTO_IP res = %d tos = %d\n", res, tos);
  123. */
  124. return fSockfd;
  125. }
  126. bool JackNetUnixSocket::IsLocal(char* ip)
  127. {
  128. if (strcmp(ip, "127.0.0.1") == 0) {
  129. return true;
  130. }
  131. char host_name[32];
  132. gethostname(host_name, sizeof(host_name));
  133. struct hostent* host = gethostbyname(host_name);
  134. if (host) {
  135. for (int i = 0; host->h_addr_list[i] != 0; ++i) {
  136. struct in_addr addr;
  137. memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
  138. if (strcmp(inet_ntoa(addr), ip) == 0) {
  139. return true;
  140. }
  141. }
  142. return false;
  143. } else {
  144. return false;
  145. }
  146. }
  147. int JackNetUnixSocket::Bind()
  148. {
  149. return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t));
  150. }
  151. int JackNetUnixSocket::Bind(const char *if_name)
  152. {
  153. struct ip_mreq multicast_req;
  154. int ret = Bind();
  155. if(!ret && strcmp(if_name,"any")) {
  156. multicast_req.imr_multiaddr.s_addr = fSendAddr.sin_addr.s_addr;
  157. ret = BindMCastIface(if_name, IP_MULTICAST_IF, &multicast_req);
  158. }
  159. return ret;
  160. }
  161. int JackNetUnixSocket::BindWith(const char* ip)
  162. {
  163. int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr);
  164. if (addr_conv < 0) {
  165. return addr_conv;
  166. }
  167. return Bind();
  168. }
  169. int JackNetUnixSocket::BindWith(int port)
  170. {
  171. fRecvAddr.sin_port = htons(port);
  172. return Bind();
  173. }
  174. int JackNetUnixSocket::Connect()
  175. {
  176. return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
  177. }
  178. int JackNetUnixSocket::ConnectTo(const char* ip)
  179. {
  180. int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
  181. if (addr_conv < 0) {
  182. return addr_conv;
  183. }
  184. return Connect();
  185. }
  186. void JackNetUnixSocket::Close()
  187. {
  188. if (fSockfd) {
  189. close(fSockfd);
  190. }
  191. fSockfd = 0;
  192. }
  193. void JackNetUnixSocket::Reset()
  194. {
  195. fSendAddr.sin_family = AF_INET;
  196. fSendAddr.sin_port = htons(fPort);
  197. fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  198. memset(&fSendAddr.sin_zero, 0, 8);
  199. fRecvAddr.sin_family = AF_INET;
  200. fRecvAddr.sin_port = htons(fPort);
  201. fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  202. memset(&fRecvAddr.sin_zero, 0, 8);
  203. }
  204. bool JackNetUnixSocket::IsSocket()
  205. {
  206. return(fSockfd) ? true : false;
  207. }
  208. //IP/PORT***********************************************************************************************************
  209. void JackNetUnixSocket::SetPort(int port)
  210. {
  211. fPort = port;
  212. fSendAddr.sin_port = htons(port);
  213. fRecvAddr.sin_port = htons(port);
  214. }
  215. int JackNetUnixSocket::GetPort()
  216. {
  217. return fPort;
  218. }
  219. //address***********************************************************************************************************
  220. int JackNetUnixSocket::SetAddress(const char* ip, int port)
  221. {
  222. int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
  223. if (addr_conv < 0) {
  224. return addr_conv;
  225. }
  226. fSendAddr.sin_port = htons(port);
  227. return 0;
  228. }
  229. char* JackNetUnixSocket::GetSendIP()
  230. {
  231. return inet_ntoa(fSendAddr.sin_addr);
  232. }
  233. char* JackNetUnixSocket::GetRecvIP()
  234. {
  235. return inet_ntoa(fRecvAddr.sin_addr);
  236. }
  237. //utility************************************************************************************************************
  238. int JackNetUnixSocket::GetName(char* name)
  239. {
  240. return gethostname(name, 255);
  241. }
  242. int JackNetUnixSocket::JoinMCastGroup(const char* ip)
  243. {
  244. return JoinMCastGroup(ip,"any");
  245. }
  246. int JackNetUnixSocket::JoinMCastGroup(const char* ip, const char *if_name)
  247. {
  248. struct ip_mreq multicast_req;
  249. inet_aton(ip, &multicast_req.imr_multiaddr);
  250. if(!strcmp(if_name,"any")) {
  251. multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
  252. return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
  253. } else {
  254. return BindMCastIface(if_name, IP_ADD_MEMBERSHIP, &multicast_req);
  255. }
  256. }
  257. int JackNetUnixSocket::BindMCastIface(const char *if_name, const int option, struct ip_mreq *mreq)
  258. {
  259. struct ifaddrs *ifas, *ifa;
  260. int specific = strcmp("all",if_name);
  261. int ret=-1;
  262. char *if_last="any";
  263. if (getifaddrs(&ifas) == -1) {
  264. jack_error("JackNetUnixSocket::BindMCastIface error in getifaddrs");
  265. return -1;
  266. }
  267. for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
  268. if (ifa->ifa_addr == NULL)
  269. continue; // Address is mandatory
  270. if(!ifa->ifa_name || !strcmp(if_last,ifa->ifa_name))
  271. continue; // Name as well, also skip already enabled interface
  272. if(!(ifa->ifa_flags & IFF_MULTICAST) || !(ifa->ifa_flags & IFF_RUNNING))
  273. continue; // And non multicast or down interface
  274. if(ifa->ifa_addr->sa_family != AF_INET)
  275. continue; // And for the moment we're dealing with IPv4 only
  276. if(!specific || !strcmp(ifa->ifa_name,if_name)) {
  277. mreq->imr_interface.s_addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr;
  278. ret = SetOption(IPPROTO_IP, option, mreq, sizeof(struct ip_mreq));
  279. if(ret)
  280. break;
  281. if_last = ifa->ifa_name;
  282. jack_log("JackNetUnixSocket::BindMCastIface attaching to %s", if_last);
  283. }
  284. }
  285. freeifaddrs(ifas);
  286. if(!strcmp(if_last,"any"))
  287. jack_error("JackNetUnixSocket::BindMCastIface cannot find valid interface");
  288. return ret;
  289. }
  290. //options************************************************************************************************************
  291. int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
  292. {
  293. return setsockopt(fSockfd, level, optname, optval, optlen);
  294. }
  295. int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
  296. {
  297. return getsockopt(fSockfd, level, optname, optval, optlen);
  298. }
  299. //timeout************************************************************************************************************
  300. #if defined(__sun__) || defined(sun)
  301. int JackNetUnixSocket::SetTimeOut(int us)
  302. {
  303. int flags;
  304. fTimeOut = us;
  305. if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
  306. jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
  307. return -1;
  308. }
  309. flags |= O_NONBLOCK;
  310. if (fcntl(fSockfd, F_SETFL, flags) < 0) {
  311. jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
  312. return 1;
  313. }
  314. return 0;
  315. }
  316. int JackNetUnixSocket::WaitRead()
  317. {
  318. if (fTimeOut > 0) {
  319. struct timeval tv;
  320. fd_set fdset;
  321. ssize_t res;
  322. tv.tv_sec = fTimeOut / 1000000;
  323. tv.tv_usec = fTimeOut % 1000000;
  324. FD_ZERO(&fdset);
  325. FD_SET(fSockfd, &fdset);
  326. do {
  327. res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
  328. } while (res < 0 && errno == EINTR);
  329. if (res < 0) {
  330. return res;
  331. } else if (res == 0) {
  332. errno = ETIMEDOUT;
  333. return -1;
  334. }
  335. }
  336. return 0;
  337. }
  338. int JackNetUnixSocket::WaitWrite()
  339. {
  340. if (fTimeOut > 0) {
  341. struct timeval tv;
  342. fd_set fdset;
  343. ssize_t res;
  344. tv.tv_sec = fTimeOut / 1000000;
  345. tv.tv_usec = fTimeOut % 1000000;
  346. FD_ZERO(&fdset);
  347. FD_SET(fSockfd, &fdset);
  348. do {
  349. res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
  350. } while (res < 0 && errno == EINTR);
  351. if (res < 0) {
  352. return res;
  353. } else if (res == 0) {
  354. errno = ETIMEDOUT;
  355. return -1;
  356. }
  357. }
  358. return 0;
  359. }
  360. #else
  361. int JackNetUnixSocket::SetTimeOut(int us)
  362. {
  363. jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
  364. struct timeval timeout;
  365. //less than 1 sec
  366. if (us < 1000000) {
  367. timeout.tv_sec = 0;
  368. timeout.tv_usec = us;
  369. } else {
  370. //more than 1 sec
  371. float sec = float(us) / 1000000.f;
  372. timeout.tv_sec = (int)sec;
  373. float usec = (sec - float(timeout.tv_sec)) * 1000000;
  374. timeout.tv_usec =(int)usec;
  375. }
  376. return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  377. }
  378. #endif
  379. //local loop**********************************************************************************************************
  380. int JackNetUnixSocket::SetLocalLoop()
  381. {
  382. char disable = 0;
  383. return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
  384. }
  385. //network operations**************************************************************************************************
  386. int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
  387. {
  388. #if defined(__sun__) || defined(sun)
  389. if (WaitWrite() < 0) {
  390. return -1;
  391. }
  392. #endif
  393. int res;
  394. if ((res = sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t))) < 0) {
  395. jack_error("SendTo fd = %ld err = %s", fSockfd, strerror(errno));
  396. }
  397. return res;
  398. }
  399. int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
  400. {
  401. int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
  402. if (addr_conv < 1) {
  403. return addr_conv;
  404. }
  405. fSendAddr.sin_port = htons(fPort);
  406. #if defined(__sun__) || defined(sun)
  407. if (WaitWrite() < 0) {
  408. return -1;
  409. }
  410. #endif
  411. return SendTo(buffer, nbytes, flags);
  412. }
  413. int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
  414. {
  415. #if defined(__sun__) || defined(sun)
  416. if (WaitWrite() < 0) {
  417. return -1;
  418. }
  419. #endif
  420. int res;
  421. if ((res = send(fSockfd, buffer, nbytes, flags)) < 0) {
  422. jack_error("Send fd = %ld err = %s", fSockfd, strerror(errno));
  423. }
  424. return res;
  425. }
  426. int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
  427. {
  428. socklen_t addr_len = sizeof(socket_address_t);
  429. #if defined(__sun__) || defined(sun)
  430. if (WaitRead() < 0) {
  431. return -1;
  432. }
  433. #endif
  434. int res;
  435. if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len)) < 0) {
  436. jack_error("RecvFrom fd = %ld err = %s", fSockfd, strerror(errno));
  437. }
  438. return res;
  439. }
  440. int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
  441. {
  442. #if defined(__sun__) || defined(sun)
  443. if (WaitRead() < 0) {
  444. return -1;
  445. }
  446. #endif
  447. int res;
  448. if ((res = recv(fSockfd, buffer, nbytes, flags)) < 0) {
  449. jack_error("Recv fd = %ld err = %s", fSockfd, strerror(errno));
  450. }
  451. return res;
  452. }
  453. int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags)
  454. {
  455. jack_log("JackNetUnixSocket::CatchHost");
  456. socklen_t addr_len = sizeof(socket_address_t);
  457. #if defined(__sun__) || defined(sun)
  458. if (WaitRead() < 0) {
  459. return -1;
  460. }
  461. #endif
  462. int res;
  463. if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len)) < 0) {
  464. jack_log("CatchHost fd = %ld err = %s", fSockfd, strerror(errno));
  465. }
  466. return res;
  467. }
  468. net_error_t JackNetUnixSocket::GetError()
  469. {
  470. switch (errno) {
  471. case EAGAIN:
  472. case ETIMEDOUT:
  473. return NET_NO_DATA;
  474. case ECONNABORTED:
  475. case ECONNREFUSED:
  476. case ECONNRESET:
  477. case EINVAL:
  478. case EHOSTDOWN:
  479. case EHOSTUNREACH:
  480. case ENETDOWN:
  481. case ENETUNREACH:
  482. return NET_CONN_ERROR;
  483. default:
  484. //return NET_OP_ERROR;
  485. return NET_CONN_ERROR;
  486. }
  487. }
  488. void JackNetUnixSocket::PrintError()
  489. {
  490. switch (errno) {
  491. case EAGAIN:
  492. jack_error("JackNetUnixSocket : EAGAIN");
  493. break;
  494. case ETIMEDOUT:
  495. jack_error("JackNetUnixSocket : ETIMEDOUT");
  496. break;
  497. case ECONNABORTED:
  498. jack_error("JackNetUnixSocket : ECONNABORTED");
  499. break;
  500. case ECONNREFUSED:
  501. jack_error("JackNetUnixSocket : ECONNREFUSED");
  502. break;
  503. case ECONNRESET:
  504. jack_error("JackNetUnixSocket : ECONNRESET");
  505. break;
  506. case EINVAL:
  507. jack_error("JackNetUnixSocket : EINVAL");
  508. break;
  509. case EHOSTDOWN:
  510. jack_error("JackNetUnixSocket : EHOSTDOWN");
  511. break;
  512. case EHOSTUNREACH:
  513. jack_error("JackNetUnixSocket : EHOSTUNREACH");
  514. break;
  515. case ENETDOWN:
  516. jack_error("JackNetUnixSocket : ENETDOWN");
  517. break;
  518. case ENETUNREACH:
  519. jack_error("JackNetUnixSocket : ENETUNREACH");
  520. break;
  521. default:
  522. jack_error("JackNetUnixSocket : %d", errno);
  523. break;
  524. }
  525. }
  526. }