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.

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