Init engine fields, cleanup.
[jack2.git] / posix / JackNetUnixSocket.cpp
blobd110c5c9d0f83cd378556fb4d2ddae8953e51e8a
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 );
103 /* Enable address reuse */
104 int res, on = 1;
105 if ((res = setsockopt( fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
106 StrError(NET_ERROR_CODE);
109 return fSockfd;
112 int JackNetUnixSocket::Bind()
114 return bind ( fSockfd, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), sizeof ( socket_address_t ) );
117 int JackNetUnixSocket::BindWith ( const char* ip )
119 int addr_conv = inet_aton ( ip, &fRecvAddr.sin_addr );
120 if ( addr_conv < 0 )
121 return addr_conv;
122 return Bind();
125 int JackNetUnixSocket::BindWith ( int port )
127 fRecvAddr.sin_port = htons ( port );
128 return Bind();
131 int JackNetUnixSocket::Connect()
133 return connect ( fSockfd, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) );
136 int JackNetUnixSocket::ConnectTo ( const char* ip )
138 int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
139 if ( addr_conv < 0 )
140 return addr_conv;
141 return Connect();
144 void JackNetUnixSocket::Close()
146 if ( fSockfd )
147 close ( fSockfd );
148 fSockfd = 0;
151 void JackNetUnixSocket::Reset()
153 fSendAddr.sin_family = AF_INET;
154 fSendAddr.sin_port = htons ( fPort );
155 fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
156 memset ( &fSendAddr.sin_zero, 0, 8 );
157 fRecvAddr.sin_family = AF_INET;
158 fRecvAddr.sin_port = htons ( fPort );
159 fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
160 memset ( &fRecvAddr.sin_zero, 0, 8 );
163 bool JackNetUnixSocket::IsSocket()
165 return ( fSockfd ) ? true : false;
168 //IP/PORT***********************************************************************************************************
169 void JackNetUnixSocket::SetPort ( int port )
171 fPort = port;
172 fSendAddr.sin_port = htons ( port );
173 fRecvAddr.sin_port = htons ( port );
176 int JackNetUnixSocket::GetPort()
178 return fPort;
181 //address***********************************************************************************************************
182 int JackNetUnixSocket::SetAddress ( const char* ip, int port )
184 int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
185 if ( addr_conv < 0 )
186 return addr_conv;
187 fSendAddr.sin_port = htons ( port );
188 return 0;
191 char* JackNetUnixSocket::GetSendIP()
193 return inet_ntoa ( fSendAddr.sin_addr );
196 char* JackNetUnixSocket::GetRecvIP()
198 return inet_ntoa ( fRecvAddr.sin_addr );
201 //utility************************************************************************************************************
202 int JackNetUnixSocket::GetName ( char* name )
204 return gethostname ( name, 255 );
207 int JackNetUnixSocket::JoinMCastGroup ( const char* ip )
209 struct ip_mreq multicast_req;
210 inet_aton ( ip, &multicast_req.imr_multiaddr );
211 multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY );
212 return SetOption ( IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof ( multicast_req ) );
215 //options************************************************************************************************************
216 int JackNetUnixSocket::SetOption ( int level, int optname, const void* optval, socklen_t optlen )
218 return setsockopt ( fSockfd, level, optname, optval, optlen );
221 int JackNetUnixSocket::GetOption ( int level, int optname, void* optval, socklen_t* optlen )
223 return getsockopt ( fSockfd, level, optname, optval, optlen );
226 //timeout************************************************************************************************************
228 #if defined(__sun__) || defined(sun)
229 int JackNetUnixSocket::SetTimeOut ( int us )
231 int flags;
232 fTimeOut = us;
234 if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
235 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
236 return -1;
239 flags |= O_NONBLOCK;
240 if (fcntl(fSockfd, F_SETFL, flags) < 0) {
241 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
242 return 1;
245 return 0;
248 int JackNetUnixSocket::WaitRead()
250 if (fTimeOut > 0) {
252 struct timeval tv;
253 fd_set fdset;
254 ssize_t res;
256 tv.tv_sec = fTimeOut / 1000000;
257 tv.tv_usec = fTimeOut % 1000000;
259 FD_ZERO(&fdset);
260 FD_SET(fSockfd, &fdset);
262 do {
263 res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
264 } while (res < 0 && errno == EINTR);
266 if (res < 0) {
267 return res;
268 } else if (res == 0) {
269 errno = ETIMEDOUT;
270 return -1;
274 return 0;
277 int JackNetUnixSocket::WaitWrite()
279 if (fTimeOut > 0) {
281 struct timeval tv;
282 fd_set fdset;
283 ssize_t res;
285 tv.tv_sec = fTimeOut / 1000000;
286 tv.tv_usec = fTimeOut % 1000000;
288 FD_ZERO(&fdset);
289 FD_SET(fSockfd, &fdset);
291 do {
292 res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
293 } while (res < 0 && errno == EINTR);
295 if (res < 0) {
296 return res;
297 } else if (res == 0) {
298 errno = ETIMEDOUT;
299 return -1;
303 return 0;
306 #else
307 int JackNetUnixSocket::SetTimeOut ( int us )
309 jack_log ( "JackNetUnixSocket::SetTimeout %d usecs", us );
311 //negative timeout, or exceding 10s, return
312 if ( ( us < 0 ) || ( us > 10000000 ) )
313 return SOCKET_ERROR;
314 struct timeval timeout;
316 //less than 1sec
317 if ( us < 1000000 )
319 timeout.tv_sec = 0;
320 timeout.tv_usec = us;
322 //more than 1sec
323 else
325 float sec = static_cast<float> ( us ) / 1000000.f;
326 timeout.tv_sec = ( int ) sec;
327 float usec = ( sec - static_cast<float> ( timeout.tv_sec ) ) * 1000000;
328 timeout.tv_usec = ( int ) usec;
330 return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) );
332 #endif
334 //local loop**********************************************************************************************************
335 int JackNetUnixSocket::SetLocalLoop()
337 char disable = 0;
338 return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) );
341 //network operations**************************************************************************************************
342 int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags )
344 #if defined(__sun__) || defined(sun)
345 if (WaitWrite() < 0)
346 return -1;
347 #endif
348 return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) );
351 int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip )
353 int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
354 if ( addr_conv < 1 )
355 return addr_conv;
356 #if defined(__sun__) || defined(sun)
357 if (WaitWrite() < 0)
358 return -1;
359 #endif
360 return SendTo ( buffer, nbytes, flags );
363 int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags )
365 #if defined(__sun__) || defined(sun)
366 if (WaitWrite() < 0)
367 return -1;
368 #endif
369 return send ( fSockfd, buffer, nbytes, flags );
372 int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags )
374 socklen_t addr_len = sizeof ( socket_address_t );
375 #if defined(__sun__) || defined(sun)
376 if (WaitRead() < 0)
377 return -1;
378 #endif
379 return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), &addr_len );
382 int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags )
384 #if defined(__sun__) || defined(sun)
385 if (WaitRead() < 0)
386 return -1;
387 #endif
388 return recv ( fSockfd, buffer, nbytes, flags );
391 int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags )
393 socklen_t addr_len = sizeof ( socket_address_t );
394 #if defined(__sun__) || defined(sun)
395 if (WaitRead() < 0)
396 return -1;
397 #endif
398 return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), &addr_len );
401 net_error_t JackNetUnixSocket::GetError()
403 switch ( errno )
405 case EAGAIN:
406 case ETIMEDOUT:
407 return NET_NO_DATA;
409 case ECONNABORTED:
410 case ECONNREFUSED:
411 case ECONNRESET:
412 case EINVAL:
413 case EHOSTDOWN:
414 case EHOSTUNREACH:
415 case ENETDOWN:
416 case ENETUNREACH:
417 return NET_CONN_ERROR;
419 default:
420 return NET_OP_ERROR;