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.

517 lines
15KB

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