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.

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