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.

444 lines
13KB

  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. namespace Jack
  20. {
  21. //utility *********************************************************************************************************
  22. int GetHostName(char * name, int size)
  23. {
  24. if (gethostname(name, size) == SOCKET_ERROR) {
  25. jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
  26. strcpy(name, "default");
  27. return SOCKET_ERROR;
  28. }
  29. return 0;
  30. }
  31. //construct/destruct***********************************************************************************************
  32. JackNetUnixSocket::JackNetUnixSocket()
  33. {
  34. fSockfd = 0;
  35. fPort = 0;
  36. fTimeOut = 0;
  37. fSendAddr.sin_family = AF_INET;
  38. fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  39. memset(&fSendAddr.sin_zero, 0, 8);
  40. fRecvAddr.sin_family = AF_INET;
  41. fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  42. memset(&fRecvAddr.sin_zero, 0, 8);
  43. }
  44. JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
  45. {
  46. fSockfd = 0;
  47. fPort = port;
  48. fTimeOut = 0;
  49. fSendAddr.sin_family = AF_INET;
  50. fSendAddr.sin_port = htons(port);
  51. inet_aton(ip, &fSendAddr.sin_addr);
  52. memset(&fSendAddr.sin_zero, 0, 8);
  53. fRecvAddr.sin_family = AF_INET;
  54. fRecvAddr.sin_port = htons(port);
  55. fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  56. memset(&fRecvAddr.sin_zero, 0, 8);
  57. }
  58. JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
  59. {
  60. fSockfd = 0;
  61. fTimeOut = 0;
  62. fPort = socket.fPort;
  63. fSendAddr = socket.fSendAddr;
  64. fRecvAddr = socket.fRecvAddr;
  65. }
  66. JackNetUnixSocket::~JackNetUnixSocket()
  67. {
  68. Close();
  69. }
  70. JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
  71. {
  72. if (this != &socket) {
  73. fSockfd = 0;
  74. fPort = socket.fPort;
  75. fSendAddr = socket.fSendAddr;
  76. fRecvAddr = socket.fRecvAddr;
  77. }
  78. return *this;
  79. }
  80. //socket***********************************************************************************************************
  81. int JackNetUnixSocket::NewSocket()
  82. {
  83. if (fSockfd) {
  84. Close();
  85. Reset();
  86. }
  87. fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
  88. /* Enable address reuse */
  89. int res, on = 1;
  90. #ifdef __APPLE__
  91. if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) < 0) {
  92. #else
  93. if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
  94. #endif
  95. StrError(NET_ERROR_CODE);
  96. }
  97. return fSockfd;
  98. }
  99. bool JackNetUnixSocket::IsLocal(char* ip)
  100. {
  101. if (strcmp(ip, "127.0.0.1") == 0) {
  102. return true;
  103. }
  104. char host_name[32];
  105. gethostname(host_name, sizeof(host_name));
  106. struct hostent* host = gethostbyname(host_name);
  107. if (host) {
  108. for (int i = 0; host->h_addr_list[i] != 0; ++i) {
  109. struct in_addr addr;
  110. memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
  111. if (strcmp(inet_ntoa(addr), ip) == 0) {
  112. return true;
  113. }
  114. }
  115. return false;
  116. } else {
  117. return false;
  118. }
  119. }
  120. int JackNetUnixSocket::Bind()
  121. {
  122. return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t));
  123. }
  124. int JackNetUnixSocket::BindWith(const char* ip)
  125. {
  126. int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr);
  127. if (addr_conv < 0)
  128. return addr_conv;
  129. return Bind();
  130. }
  131. int JackNetUnixSocket::BindWith(int port)
  132. {
  133. fRecvAddr.sin_port = htons(port);
  134. return Bind();
  135. }
  136. int JackNetUnixSocket::Connect()
  137. {
  138. return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
  139. }
  140. int JackNetUnixSocket::ConnectTo(const char* ip)
  141. {
  142. int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
  143. if (addr_conv < 0)
  144. return addr_conv;
  145. return Connect();
  146. }
  147. void JackNetUnixSocket::Close()
  148. {
  149. if (fSockfd)
  150. close(fSockfd);
  151. fSockfd = 0;
  152. }
  153. void JackNetUnixSocket::Reset()
  154. {
  155. fSendAddr.sin_family = AF_INET;
  156. fSendAddr.sin_port = htons(fPort);
  157. fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  158. memset(&fSendAddr.sin_zero, 0, 8);
  159. fRecvAddr.sin_family = AF_INET;
  160. fRecvAddr.sin_port = htons(fPort);
  161. fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  162. memset(&fRecvAddr.sin_zero, 0, 8);
  163. }
  164. bool JackNetUnixSocket::IsSocket()
  165. {
  166. return(fSockfd) ? true : false;
  167. }
  168. //IP/PORT***********************************************************************************************************
  169. void JackNetUnixSocket::SetPort(int port)
  170. {
  171. fPort = port;
  172. fSendAddr.sin_port = htons(port);
  173. fRecvAddr.sin_port = htons(port);
  174. }
  175. int JackNetUnixSocket::GetPort()
  176. {
  177. return fPort;
  178. }
  179. //address***********************************************************************************************************
  180. int JackNetUnixSocket::SetAddress(const char* ip, int port)
  181. {
  182. int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
  183. if (addr_conv < 0)
  184. return addr_conv;
  185. fSendAddr.sin_port = htons(port);
  186. return 0;
  187. }
  188. char* JackNetUnixSocket::GetSendIP()
  189. {
  190. return inet_ntoa(fSendAddr.sin_addr);
  191. }
  192. char* JackNetUnixSocket::GetRecvIP()
  193. {
  194. return inet_ntoa(fRecvAddr.sin_addr);
  195. }
  196. //utility************************************************************************************************************
  197. int JackNetUnixSocket::GetName(char* name)
  198. {
  199. return gethostname(name, 255);
  200. }
  201. int JackNetUnixSocket::JoinMCastGroup(const char* ip)
  202. {
  203. struct ip_mreq multicast_req;
  204. inet_aton(ip, &multicast_req.imr_multiaddr);
  205. multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
  206. return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
  207. }
  208. //options************************************************************************************************************
  209. int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
  210. {
  211. return setsockopt(fSockfd, level, optname, optval, optlen);
  212. }
  213. int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
  214. {
  215. return getsockopt(fSockfd, level, optname, optval, optlen);
  216. }
  217. //timeout************************************************************************************************************
  218. #if defined(__sun__) || defined(sun)
  219. int JackNetUnixSocket::SetTimeOut(int us)
  220. {
  221. int flags;
  222. fTimeOut = us;
  223. if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
  224. jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
  225. return -1;
  226. }
  227. flags |= O_NONBLOCK;
  228. if (fcntl(fSockfd, F_SETFL, flags) < 0) {
  229. jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
  230. return 1;
  231. }
  232. return 0;
  233. }
  234. int JackNetUnixSocket::WaitRead()
  235. {
  236. if (fTimeOut > 0) {
  237. struct timeval tv;
  238. fd_set fdset;
  239. ssize_t res;
  240. tv.tv_sec = fTimeOut / 1000000;
  241. tv.tv_usec = fTimeOut % 1000000;
  242. FD_ZERO(&fdset);
  243. FD_SET(fSockfd, &fdset);
  244. do {
  245. res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
  246. } while(res < 0 && errno == EINTR);
  247. if (res < 0) {
  248. return res;
  249. } else if (res == 0) {
  250. errno = ETIMEDOUT;
  251. return -1;
  252. }
  253. }
  254. return 0;
  255. }
  256. int JackNetUnixSocket::WaitWrite()
  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, NULL, &fdset, 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. #else
  279. int JackNetUnixSocket::SetTimeOut(int us)
  280. {
  281. jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
  282. struct timeval timeout;
  283. //less than 1sec
  284. if (us < 1000000) {
  285. timeout.tv_sec = 0;
  286. timeout.tv_usec = us;
  287. } else {
  288. //more than 1sec
  289. float sec = float(us) / 1000000.f;
  290. timeout.tv_sec = (int)sec;
  291. float usec = (sec - float(timeout.tv_sec)) * 1000000;
  292. timeout.tv_usec =(int)usec;
  293. }
  294. return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  295. }
  296. #endif
  297. //local loop**********************************************************************************************************
  298. int JackNetUnixSocket::SetLocalLoop()
  299. {
  300. char disable = 0;
  301. return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
  302. }
  303. //network operations**************************************************************************************************
  304. int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
  305. {
  306. #if defined(__sun__) || defined(sun)
  307. if (WaitWrite() < 0)
  308. return -1;
  309. #endif
  310. return sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
  311. }
  312. int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
  313. {
  314. int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
  315. if (addr_conv < 1)
  316. return addr_conv;
  317. #if defined(__sun__) || defined(sun)
  318. if (WaitWrite() < 0)
  319. return -1;
  320. #endif
  321. return SendTo(buffer, nbytes, flags);
  322. }
  323. int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
  324. {
  325. #if defined(__sun__) || defined(sun)
  326. if (WaitWrite() < 0)
  327. return -1;
  328. #endif
  329. return send(fSockfd, buffer, nbytes, flags);
  330. }
  331. int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
  332. {
  333. socklen_t addr_len = sizeof(socket_address_t);
  334. #if defined(__sun__) || defined(sun)
  335. if (WaitRead() < 0)
  336. return -1;
  337. #endif
  338. return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len);
  339. }
  340. int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
  341. {
  342. #if defined(__sun__) || defined(sun)
  343. if (WaitRead() < 0)
  344. return -1;
  345. #endif
  346. return recv(fSockfd, buffer, nbytes, flags);
  347. }
  348. int JackNetUnixSocket::CatchHost(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. #endif
  355. return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len);
  356. }
  357. net_error_t JackNetUnixSocket::GetError()
  358. {
  359. switch(errno)
  360. {
  361. case EAGAIN:
  362. case ETIMEDOUT:
  363. return NET_NO_DATA;
  364. case ECONNABORTED:
  365. case ECONNREFUSED:
  366. case ECONNRESET:
  367. case EINVAL:
  368. case EHOSTDOWN:
  369. case EHOSTUNREACH:
  370. case ENETDOWN:
  371. case ENETUNREACH:
  372. return NET_CONN_ERROR;
  373. default:
  374. //return NET_OP_ERROR;
  375. return NET_CONN_ERROR;
  376. }
  377. }
  378. }