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.

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