2 Copyright (C) 2008-2011 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 "JackError.h"
31 //utility *********************************************************************************************************
32 int GetHostName(char * name
, int size
)
34 if (gethostname(name
, size
) == SOCKET_ERROR
) {
35 jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE
));
36 strcpy(name
, "default");
42 //construct/destruct***********************************************************************************************
43 JackNetUnixSocket::JackNetUnixSocket()
48 fSendAddr
.sin_family
= AF_INET
;
49 fSendAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
50 memset(&fSendAddr
.sin_zero
, 0, 8);
51 fRecvAddr
.sin_family
= AF_INET
;
52 fRecvAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
53 memset(&fRecvAddr
.sin_zero
, 0, 8);
56 JackNetUnixSocket::JackNetUnixSocket(const char* ip
, int port
)
61 fSendAddr
.sin_family
= AF_INET
;
62 fSendAddr
.sin_port
= htons(port
);
63 inet_aton(ip
, &fSendAddr
.sin_addr
);
64 memset(&fSendAddr
.sin_zero
, 0, 8);
65 fRecvAddr
.sin_family
= AF_INET
;
66 fRecvAddr
.sin_port
= htons(port
);
67 fRecvAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
68 memset(&fRecvAddr
.sin_zero
, 0, 8);
71 JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket
& socket
)
76 fSendAddr
= socket
.fSendAddr
;
77 fRecvAddr
= socket
.fRecvAddr
;
80 JackNetUnixSocket::~JackNetUnixSocket()
85 JackNetUnixSocket
& JackNetUnixSocket::operator=(const JackNetUnixSocket
& socket
)
87 if (this != &socket
) {
90 fSendAddr
= socket
.fSendAddr
;
91 fRecvAddr
= socket
.fRecvAddr
;
96 //socket***********************************************************************************************************
97 int JackNetUnixSocket::NewSocket()
103 fSockfd
= socket(AF_INET
, SOCK_DGRAM
, 0);
105 /* Enable address reuse */
108 if ((res
= setsockopt(fSockfd
, SOL_SOCKET
, SO_REUSEPORT
, &on
, sizeof(on
))) < 0) {
110 if ((res
= setsockopt(fSockfd
, SOL_SOCKET
, SO_REUSEADDR
, &on
, sizeof(on
))) < 0) {
112 StrError(NET_ERROR_CODE
);
115 int tos
= 0; /* see <netinet/in.h> */
118 DSCP Field Hex/Bin/Dec Layer 2 Prio Traffic Type Acronym WMM Access Category
119 0x38 / 111000 / 56 7 Network Control NC AC_VO
120 0x30 / 110000 / 48 6 Voice VO AC_VO
121 0x28 / 101000 / 40 5 Video VI AC_VI
122 0x20 / 100000 / 32 4 Controlled Load CL AC_VI
123 0x18 / 011000 / 24 3 Excellent Effort EE AC_BE
124 0x10 / 010000 / 16 2 Spare -- AC_BK
125 0x08 / 001000 / 8 1 Background BK AC_BK
126 0x00 / 000000 / 0 0 Best Effort BE AC_BE
129 socklen_t len
= sizeof(tos
);
131 res
= getsockopt(fSockfd
, IPPROTO_IP
, IP_TOS
, &tos
, &len
);
133 tos
= 46 * 4; // see <netinet/in.h>
134 res
= setsockopt(fSockfd
, IPPROTO_IP
, IP_TOS
, &tos
, sizeof(tos
));
139 bool JackNetUnixSocket::IsLocal(char* ip
)
141 if (strcmp(ip
, "127.0.0.1") == 0) {
146 gethostname(host_name
, sizeof(host_name
));
148 struct hostent
* host
= gethostbyname(host_name
);
150 for (int i
= 0; host
->h_addr_list
[i
] != 0; ++i
) {
152 memcpy(&addr
, host
->h_addr_list
[i
], sizeof(struct in_addr
));
153 if (strcmp(inet_ntoa(addr
), ip
) == 0) {
163 int JackNetUnixSocket::Bind()
165 return ::bind(fSockfd
, reinterpret_cast<socket_address_t
*>(&fRecvAddr
), sizeof(socket_address_t
));
168 int JackNetUnixSocket::BindWith(const char* ip
)
170 int addr_conv
= inet_aton(ip
, &fRecvAddr
.sin_addr
);
177 int JackNetUnixSocket::BindWith(int port
)
179 fRecvAddr
.sin_port
= htons(port
);
183 int JackNetUnixSocket::Connect()
185 return connect(fSockfd
, reinterpret_cast<socket_address_t
*>(&fSendAddr
), sizeof(socket_address_t
));
188 int JackNetUnixSocket::ConnectTo(const char* ip
)
190 int addr_conv
= inet_aton(ip
, &fSendAddr
.sin_addr
);
197 void JackNetUnixSocket::Close()
205 void JackNetUnixSocket::Reset()
207 fSendAddr
.sin_family
= AF_INET
;
208 fSendAddr
.sin_port
= htons(fPort
);
209 fSendAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
210 memset(&fSendAddr
.sin_zero
, 0, 8);
211 fRecvAddr
.sin_family
= AF_INET
;
212 fRecvAddr
.sin_port
= htons(fPort
);
213 fRecvAddr
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
214 memset(&fRecvAddr
.sin_zero
, 0, 8);
217 bool JackNetUnixSocket::IsSocket()
219 return(fSockfd
) ? true : false;
222 //IP/PORT***********************************************************************************************************
223 void JackNetUnixSocket::SetPort(int port
)
226 fSendAddr
.sin_port
= htons(port
);
227 fRecvAddr
.sin_port
= htons(port
);
230 int JackNetUnixSocket::GetPort()
235 //address***********************************************************************************************************
236 int JackNetUnixSocket::SetAddress(const char* ip
, int port
)
238 int addr_conv
= inet_aton(ip
, &fSendAddr
.sin_addr
);
242 fSendAddr
.sin_port
= htons(port
);
246 char* JackNetUnixSocket::GetSendIP()
248 return inet_ntoa(fSendAddr
.sin_addr
);
251 char* JackNetUnixSocket::GetRecvIP()
253 return inet_ntoa(fRecvAddr
.sin_addr
);
256 //utility************************************************************************************************************
257 int JackNetUnixSocket::GetName(char* name
)
259 return gethostname(name
, 255);
262 int JackNetUnixSocket::JoinMCastGroup(const char* ip
)
264 struct ip_mreq multicast_req
;
265 inet_aton(ip
, &multicast_req
.imr_multiaddr
);
266 multicast_req
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
267 return SetOption(IPPROTO_IP
, IP_ADD_MEMBERSHIP
, &multicast_req
, sizeof(multicast_req
));
270 //options************************************************************************************************************
271 int JackNetUnixSocket::SetOption(int level
, int optname
, const void* optval
, socklen_t optlen
)
273 return setsockopt(fSockfd
, level
, optname
, optval
, optlen
);
276 int JackNetUnixSocket::GetOption(int level
, int optname
, void* optval
, socklen_t
* optlen
)
278 return getsockopt(fSockfd
, level
, optname
, optval
, optlen
);
281 //timeout************************************************************************************************************
283 #if defined(__sun__) || defined(sun)
284 int JackNetUnixSocket::SetTimeOut(int us
)
289 if ((flags
= fcntl(fSockfd
, F_GETFL
, 0)) < 0) {
290 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
295 if (fcntl(fSockfd
, F_SETFL
, flags
) < 0) {
296 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
303 int JackNetUnixSocket::WaitRead()
311 tv
.tv_sec
= fTimeOut
/ 1000000;
312 tv
.tv_usec
= fTimeOut
% 1000000;
315 FD_SET(fSockfd
, &fdset
);
318 res
= select(fSockfd
+ 1, &fdset
, NULL
, NULL
, &tv
);
319 } while (res
< 0 && errno
== EINTR
);
323 } else if (res
== 0) {
332 int JackNetUnixSocket::WaitWrite()
340 tv
.tv_sec
= fTimeOut
/ 1000000;
341 tv
.tv_usec
= fTimeOut
% 1000000;
344 FD_SET(fSockfd
, &fdset
);
347 res
= select(fSockfd
+ 1, NULL
, &fdset
, NULL
, &tv
);
348 } while (res
< 0 && errno
== EINTR
);
352 } else if (res
== 0) {
362 int JackNetUnixSocket::SetTimeOut(int us
)
364 jack_log("JackNetUnixSocket::SetTimeout %d usecs", us
);
365 struct timeval timeout
;
370 timeout
.tv_usec
= us
;
373 float sec
= float(us
) / 1000000.f
;
374 timeout
.tv_sec
= (int)sec
;
375 float usec
= (sec
- float(timeout
.tv_sec
)) * 1000000;
376 timeout
.tv_usec
=(int)usec
;
378 return SetOption(SOL_SOCKET
, SO_RCVTIMEO
, &timeout
, sizeof(timeout
));
382 //local loop**********************************************************************************************************
383 int JackNetUnixSocket::SetLocalLoop()
386 return SetOption(IPPROTO_IP
, IP_MULTICAST_LOOP
, &disable
, sizeof(disable
));
389 //network operations**************************************************************************************************
390 int JackNetUnixSocket::SendTo(const void* buffer
, size_t nbytes
, int flags
)
392 #if defined(__sun__) || defined(sun)
393 if (WaitWrite() < 0) {
398 if ((res
= sendto(fSockfd
, buffer
, nbytes
, flags
, reinterpret_cast<socket_address_t
*>(&fSendAddr
), sizeof(socket_address_t
))) < 0) {
399 jack_error("SendTo fd = %ld err = %s", fSockfd
, strerror(errno
));
404 int JackNetUnixSocket::SendTo(const void* buffer
, size_t nbytes
, int flags
, const char* ip
)
406 int addr_conv
= inet_aton(ip
, &fSendAddr
.sin_addr
);
410 fSendAddr
.sin_port
= htons(fPort
);
411 #if defined(__sun__) || defined(sun)
412 if (WaitWrite() < 0) {
416 return SendTo(buffer
, nbytes
, flags
);
419 int JackNetUnixSocket::Send(const void* buffer
, size_t nbytes
, int flags
)
421 #if defined(__sun__) || defined(sun)
422 if (WaitWrite() < 0) {
427 if ((res
= send(fSockfd
, buffer
, nbytes
, flags
)) < 0) {
428 jack_error("Send fd = %ld err = %s", fSockfd
, strerror(errno
));
433 int JackNetUnixSocket::RecvFrom(void* buffer
, size_t nbytes
, int flags
)
435 socklen_t addr_len
= sizeof(socket_address_t
);
436 #if defined(__sun__) || defined(sun)
437 if (WaitRead() < 0) {
442 if ((res
= recvfrom(fSockfd
, buffer
, nbytes
, flags
, reinterpret_cast<socket_address_t
*>(&fRecvAddr
), &addr_len
)) < 0) {
443 jack_error("RecvFrom fd = %ld err = %s", fSockfd
, strerror(errno
));
448 int JackNetUnixSocket::Recv(void* buffer
, size_t nbytes
, int flags
)
450 #if defined(__sun__) || defined(sun)
451 if (WaitRead() < 0) {
456 if ((res
= recv(fSockfd
, buffer
, nbytes
, flags
)) < 0) {
457 jack_error("Recv fd = %ld err = %s", fSockfd
, strerror(errno
));
462 int JackNetUnixSocket::CatchHost(void* buffer
, size_t nbytes
, int flags
)
464 socklen_t addr_len
= sizeof(socket_address_t
);
465 #if defined(__sun__) || defined(sun)
466 if (WaitRead() < 0) {
471 if ((res
= recvfrom(fSockfd
, buffer
, nbytes
, flags
, reinterpret_cast<socket_address_t
*>(&fSendAddr
), &addr_len
)) < 0) {
472 jack_log("CatchHost fd = %ld err = %s", fSockfd
, strerror(errno
));
477 net_error_t
JackNetUnixSocket::GetError()
492 return NET_CONN_ERROR
;
495 //return NET_OP_ERROR;
496 return NET_CONN_ERROR
;
500 void JackNetUnixSocket::PrintError()
505 jack_error("JackNetUnixSocket : EAGAIN");
508 jack_error("JackNetUnixSocket : ETIMEDOUT");
511 jack_error("JackNetUnixSocket : ECONNABORTED");
514 jack_error("JackNetUnixSocket : ECONNREFUSED");
517 jack_error("JackNetUnixSocket : ECONNRESET");
520 jack_error("JackNetUnixSocket : EINVAL");
523 jack_error("JackNetUnixSocket : EHOSTDOWN");
526 jack_error("JackNetUnixSocket : EHOSTUNREACH");
529 jack_error("JackNetUnixSocket : ENETDOWN");
532 jack_error("JackNetUnixSocket : ENETUNREACH");
535 jack_error("JackNetUnixSocket : %d", errno
);