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.

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