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.

424 lines
12KB

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