Merge branch 'master' into port_register_notification_defer
[jack2.git] / posix / JackNetUnixSocket.cpp
blob7649ca8cbcaf35338709992474ed367407efb8ad
1 /*
2 Copyright (C) 2008 Romain Moret at Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "JackNetUnixSocket.h"
21 #include <unistd.h>
22 #include <fcntl.h>
24 namespace Jack
26 //utility *********************************************************************************************************
27 int GetHostName ( char * name, int size )
29 if ( gethostname ( name, size ) == SOCKET_ERROR )
31 jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) );
32 strcpy ( name, "default" );
33 return SOCKET_ERROR;
35 return 0;
38 //construct/destruct***********************************************************************************************
39 JackNetUnixSocket::JackNetUnixSocket()
41 fSockfd = 0;
42 fPort = 0;
43 fTimeOut = 0;
44 fSendAddr.sin_family = AF_INET;
45 fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
46 memset ( &fSendAddr.sin_zero, 0, 8 );
47 fRecvAddr.sin_family = AF_INET;
48 fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
49 memset ( &fRecvAddr.sin_zero, 0, 8 );
52 JackNetUnixSocket::JackNetUnixSocket ( const char* ip, int port )
54 fSockfd = 0;
55 fPort = port;
56 fTimeOut = 0;
57 fSendAddr.sin_family = AF_INET;
58 fSendAddr.sin_port = htons ( port );
59 inet_aton ( ip, &fSendAddr.sin_addr );
60 memset ( &fSendAddr.sin_zero, 0, 8 );
61 fRecvAddr.sin_family = AF_INET;
62 fRecvAddr.sin_port = htons ( port );
63 fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
64 memset ( &fRecvAddr.sin_zero, 0, 8 );
67 JackNetUnixSocket::JackNetUnixSocket ( const JackNetUnixSocket& socket )
69 fSockfd = 0;
70 fTimeOut = 0;
71 fPort = socket.fPort;
72 fSendAddr = socket.fSendAddr;
73 fRecvAddr = socket.fRecvAddr;
76 JackNetUnixSocket::~JackNetUnixSocket()
78 Close();
81 JackNetUnixSocket& JackNetUnixSocket::operator= ( const JackNetUnixSocket& socket )
83 if ( this != &socket )
85 fSockfd = 0;
86 fPort = socket.fPort;
87 fSendAddr = socket.fSendAddr;
88 fRecvAddr = socket.fRecvAddr;
90 return *this;
93 //socket***********************************************************************************************************
94 int JackNetUnixSocket::NewSocket()
96 if ( fSockfd )
98 Close();
99 Reset();
101 fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 );
102 return fSockfd;
105 int JackNetUnixSocket::Bind()
107 return bind ( fSockfd, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), sizeof ( socket_address_t ) );
110 int JackNetUnixSocket::BindWith ( const char* ip )
112 int addr_conv = inet_aton ( ip, &fRecvAddr.sin_addr );
113 if ( addr_conv < 0 )
114 return addr_conv;
115 return Bind();
118 int JackNetUnixSocket::BindWith ( int port )
120 fRecvAddr.sin_port = htons ( port );
121 return Bind();
124 int JackNetUnixSocket::Connect()
126 return connect ( fSockfd, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) );
129 int JackNetUnixSocket::ConnectTo ( const char* ip )
131 int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
132 if ( addr_conv < 0 )
133 return addr_conv;
134 return Connect();
137 void JackNetUnixSocket::Close()
139 if ( fSockfd )
140 close ( fSockfd );
141 fSockfd = 0;
144 void JackNetUnixSocket::Reset()
146 fSendAddr.sin_family = AF_INET;
147 fSendAddr.sin_port = htons ( fPort );
148 fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
149 memset ( &fSendAddr.sin_zero, 0, 8 );
150 fRecvAddr.sin_family = AF_INET;
151 fRecvAddr.sin_port = htons ( fPort );
152 fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
153 memset ( &fRecvAddr.sin_zero, 0, 8 );
156 bool JackNetUnixSocket::IsSocket()
158 return ( fSockfd ) ? true : false;
161 //IP/PORT***********************************************************************************************************
162 void JackNetUnixSocket::SetPort ( int port )
164 fPort = port;
165 fSendAddr.sin_port = htons ( port );
166 fRecvAddr.sin_port = htons ( port );
169 int JackNetUnixSocket::GetPort()
171 return fPort;
174 //address***********************************************************************************************************
175 int JackNetUnixSocket::SetAddress ( const char* ip, int port )
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;
184 char* JackNetUnixSocket::GetSendIP()
186 return inet_ntoa ( fSendAddr.sin_addr );
189 char* JackNetUnixSocket::GetRecvIP()
191 return inet_ntoa ( fRecvAddr.sin_addr );
194 //utility************************************************************************************************************
195 int JackNetUnixSocket::GetName ( char* name )
197 return gethostname ( name, 255 );
200 int JackNetUnixSocket::JoinMCastGroup ( const char* ip )
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 ) );
208 //options************************************************************************************************************
209 int JackNetUnixSocket::SetOption ( int level, int optname, const void* optval, socklen_t optlen )
211 return setsockopt ( fSockfd, level, optname, optval, optlen );
214 int JackNetUnixSocket::GetOption ( int level, int optname, void* optval, socklen_t* optlen )
216 return getsockopt ( fSockfd, level, optname, optval, optlen );
219 //timeout************************************************************************************************************
221 #if defined(__sun__) || defined(sun)
222 int JackNetUnixSocket::SetTimeOut ( int us )
224 int flags;
225 fTimeOut = us;
227 if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
228 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
229 return -1;
232 flags |= O_NONBLOCK;
233 if (fcntl(fSockfd, F_SETFL, flags) < 0) {
234 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
235 return 1;
238 return 0;
241 int JackNetUnixSocket::WaitRead()
243 if (fTimeOut > 0) {
245 struct timeval tv;
246 fd_set fdset;
247 ssize_t res;
249 tv.tv_sec = fTimeOut / 1000000;
250 tv.tv_usec = fTimeOut % 1000000;
252 FD_ZERO(&fdset);
253 FD_SET(fSockfd, &fdset);
255 do {
256 res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
257 } while (res < 0 && errno == EINTR);
259 if (res < 0) {
260 return res;
261 } else if (res == 0) {
262 errno = ETIMEDOUT;
263 return -1;
267 return 0;
270 int JackNetUnixSocket::WaitWrite()
272 if (fTimeOut > 0) {
274 struct timeval tv;
275 fd_set fdset;
276 ssize_t res;
278 tv.tv_sec = fTimeOut / 1000000;
279 tv.tv_usec = fTimeOut % 1000000;
281 FD_ZERO(&fdset);
282 FD_SET(fSockfd, &fdset);
284 do {
285 res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
286 } while (res < 0 && errno == EINTR);
288 if (res < 0) {
289 return res;
290 } else if (res == 0) {
291 errno = ETIMEDOUT;
292 return -1;
296 return 0;
299 #else
300 int JackNetUnixSocket::SetTimeOut ( int us )
302 jack_log ( "JackNetUnixSocket::SetTimeout %d usecs", us );
304 //negative timeout, or exceding 10s, return
305 if ( ( us < 0 ) || ( us > 10000000 ) )
306 return SOCKET_ERROR;
307 struct timeval timeout;
309 //less than 1sec
310 if ( us < 1000000 )
312 timeout.tv_sec = 0;
313 timeout.tv_usec = us;
315 //more than 1sec
316 else
318 float sec = static_cast<float> ( us ) / 1000000.f;
319 timeout.tv_sec = ( int ) sec;
320 float usec = ( sec - static_cast<float> ( timeout.tv_sec ) ) * 1000000;
321 timeout.tv_usec = ( int ) usec;
323 return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) );
325 #endif
327 //local loop**********************************************************************************************************
328 int JackNetUnixSocket::SetLocalLoop()
330 char disable = 0;
331 return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) );
334 //network operations**************************************************************************************************
335 int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags )
337 #if defined(__sun__) || defined(sun)
338 if (WaitWrite() < 0)
339 return -1;
340 #endif
341 return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) );
344 int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip )
346 int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
347 if ( addr_conv < 1 )
348 return addr_conv;
349 #if defined(__sun__) || defined(sun)
350 if (WaitWrite() < 0)
351 return -1;
352 #endif
353 return SendTo ( buffer, nbytes, flags );
356 int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags )
358 #if defined(__sun__) || defined(sun)
359 if (WaitWrite() < 0)
360 return -1;
361 #endif
362 return send ( fSockfd, buffer, nbytes, flags );
365 int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags )
367 socklen_t addr_len = sizeof ( socket_address_t );
368 #if defined(__sun__) || defined(sun)
369 if (WaitRead() < 0)
370 return -1;
371 #endif
372 return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), &addr_len );
375 int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags )
377 #if defined(__sun__) || defined(sun)
378 if (WaitRead() < 0)
379 return -1;
380 #endif
381 return recv ( fSockfd, buffer, nbytes, flags );
384 int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags )
386 socklen_t addr_len = sizeof ( socket_address_t );
387 #if defined(__sun__) || defined(sun)
388 if (WaitRead() < 0)
389 return -1;
390 #endif
391 return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), &addr_len );
394 net_error_t JackNetUnixSocket::GetError()
396 switch ( errno )
398 case EAGAIN:
399 case ETIMEDOUT:
400 return NET_NO_DATA;
402 case ECONNABORTED:
403 case ECONNREFUSED:
404 case ECONNRESET:
405 case EINVAL:
406 case EHOSTDOWN:
407 case EHOSTUNREACH:
408 case ENETDOWN:
409 case ENETUNREACH:
410 return NET_CONN_ERROR;
412 default:
413 return NET_OP_ERROR;