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.

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