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.

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