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.

540 lines
16KB

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