Jack2: JackNetUnixSocket.cpp Source File

Jack2 1.9.12

JackNetUnixSocket.cpp
1 /*
2 Copyright (C) 2008-2011 Romain Moret at Grame
3
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.
8
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.
13
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.
17
18 */
19
20 #include "JackNetUnixSocket.h"
21 #include "JackError.h"
22
23 #include <unistd.h>
24 #include <fcntl.h>
25
26 using namespace std;
27
28 namespace Jack
29 {
30 //utility *********************************************************************************************************
31 int GetHostName(char * name, int size)
32 {
33 if (gethostname(name, size) == SOCKET_ERROR) {
34 jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
35 strcpy(name, "default");
36 return SOCKET_ERROR;
37 }
38 return 0;
39 }
40
41 //construct/destruct***********************************************************************************************
42 JackNetUnixSocket::JackNetUnixSocket()
43 {
44 fSockfd = 0;
45 fPort = 0;
46 fTimeOut = 0;
47 fSendAddr.sin_family = AF_INET;
48 fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
49 memset(&fSendAddr.sin_zero, 0, 8);
50 fRecvAddr.sin_family = AF_INET;
51 fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
52 memset(&fRecvAddr.sin_zero, 0, 8);
53 }
54
55 JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
56 {
57 fSockfd = 0;
58 fPort = port;
59 fTimeOut = 0;
60 fSendAddr.sin_family = AF_INET;
61 fSendAddr.sin_port = htons(port);
62 inet_aton(ip, &fSendAddr.sin_addr);
63 memset(&fSendAddr.sin_zero, 0, 8);
64 fRecvAddr.sin_family = AF_INET;
65 fRecvAddr.sin_port = htons(port);
66 fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
67 memset(&fRecvAddr.sin_zero, 0, 8);
68 }
69
70 JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
71 {
72 fSockfd = 0;
73 fTimeOut = 0;
74 fPort = socket.fPort;
75 fSendAddr = socket.fSendAddr;
76 fRecvAddr = socket.fRecvAddr;
77 }
78
79 JackNetUnixSocket::~JackNetUnixSocket()
80 {
81 Close();
82 }
83
84 JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
85 {
86 if (this != &socket) {
87 fSockfd = 0;
88 fPort = socket.fPort;
89 fSendAddr = socket.fSendAddr;
90 fRecvAddr = socket.fRecvAddr;
91 }
92 return *this;
93 }
94
95 //socket***********************************************************************************************************
96 int JackNetUnixSocket::NewSocket()
97 {
98 if (fSockfd) {
99 Close();
100 Reset();
101 }
102 fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
103
104 /* Enable address reuse */
105 int res, on = 1;
106 #ifdef __APPLE__
107 if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) < 0) {
108 #else
109 if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
110 #endif
111 StrError(NET_ERROR_CODE);
112 }
113
114 int tos = 0; /* see <netinet/in.h> */
115
116 /*
117 DSCP Field Hex/Bin/Dec Layer 2 Prio Traffic Type Acronym WMM Access Category
118 0x38 / 111000 / 56 7 Network Control NC AC_VO
119 0x30 / 110000 / 48 6 Voice VO AC_VO
120 0x28 / 101000 / 40 5 Video VI AC_VI
121 0x20 / 100000 / 32 4 Controlled Load CL AC_VI
122 0x18 / 011000 / 24 3 Excellent Effort EE AC_BE
123 0x10 / 010000 / 16 2 Spare -- AC_BK
124 0x08 / 001000 / 8 1 Background BK AC_BK
125 0x00 / 000000 / 0 0 Best Effort BE AC_BE
126 */
127
128 /*
129 socklen_t len = sizeof(tos);
130
131 res = getsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, &len);
132 printf("getsockopt IPPROTO_IP res = %d tos = %d\n", res, tos);
133
134 tos = 46 * 4; // see <netinet/in.h>
135 res = setsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
136
137 printf("setsockopt IPPROTO_IP res = %d tos = %d\n", res, tos );
138
139 res = getsockopt(fSockfd, IPPROTO_IP, IP_TOS, &tos, &len);
140 printf("getsockopt IPPROTO_IP res = %d tos = %d\n", res, tos);
141 */
142
143 return fSockfd;
144 }
145
146 bool JackNetUnixSocket::IsLocal(char* ip)
147 {
148 if (strcmp(ip, "127.0.0.1") == 0) {
149 return true;
150 }
151
152 char host_name[32];
153 gethostname(host_name, sizeof(host_name));
154
155 struct hostent* host = gethostbyname(host_name);
156 if (host) {
157 for (int i = 0; host->h_addr_list[i] != 0; ++i) {
158 struct in_addr addr;
159 memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
160 if (strcmp(inet_ntoa(addr), ip) == 0) {
161 return true;
162 }
163 }
164 return false;
165 } else {
166 return false;
167 }
168 }
169
170 int JackNetUnixSocket::Bind()
171 {
172 return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t));
173 }
174
175 int JackNetUnixSocket::BindWith(const char* ip)
176 {
177 int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr);
178 if (addr_conv < 0) {
179 return addr_conv;
180 }
181 return Bind();
182 }
183
184 int JackNetUnixSocket::BindWith(int port)
185 {
186 fRecvAddr.sin_port = htons(port);
187 return Bind();
188 }
189
190 int JackNetUnixSocket::Connect()
191 {
192 return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
193 }
194
195 int JackNetUnixSocket::ConnectTo(const char* ip)
196 {
197 int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
198 if (addr_conv < 0) {
199 return addr_conv;
200 }
201 return Connect();
202 }
203
204 void JackNetUnixSocket::Close()
205 {
206 if (fSockfd) {
207 close(fSockfd);
208 }
209 fSockfd = 0;
210 }
211
212 void JackNetUnixSocket::Reset()
213 {
214 fSendAddr.sin_family = AF_INET;
215 fSendAddr.sin_port = htons(fPort);
216 fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
217 memset(&fSendAddr.sin_zero, 0, 8);
218 fRecvAddr.sin_family = AF_INET;
219 fRecvAddr.sin_port = htons(fPort);
220 fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
221 memset(&fRecvAddr.sin_zero, 0, 8);
222 }
223
224 bool JackNetUnixSocket::IsSocket()
225 {
226 return(fSockfd) ? true : false;
227 }
228
229 //IP/PORT***********************************************************************************************************
230 void JackNetUnixSocket::SetPort(int port)
231 {
232 fPort = port;
233 fSendAddr.sin_port = htons(port);
234 fRecvAddr.sin_port = htons(port);
235 }
236
237 int JackNetUnixSocket::GetPort()
238 {
239 return fPort;
240 }
241
242 //address***********************************************************************************************************
243 int JackNetUnixSocket::SetAddress(const char* ip, int port)
244 {
245 int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
246 if (addr_conv < 0) {
247 return addr_conv;
248 }
249 fSendAddr.sin_port = htons(port);
250 return 0;
251 }
252
253 char* JackNetUnixSocket::GetSendIP()
254 {
255 return inet_ntoa(fSendAddr.sin_addr);
256 }
257
258 char* JackNetUnixSocket::GetRecvIP()
259 {
260 return inet_ntoa(fRecvAddr.sin_addr);
261 }
262
263 //utility************************************************************************************************************
264 int JackNetUnixSocket::GetName(char* name)
265 {
266 return gethostname(name, 255);
267 }
268
269 int JackNetUnixSocket::JoinMCastGroup(const char* ip)
270 {
271 struct ip_mreq multicast_req;
272 inet_aton(ip, &multicast_req.imr_multiaddr);
273 multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
274 return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
275 }
276
277 //options************************************************************************************************************
278 int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
279 {
280 return setsockopt(fSockfd, level, optname, optval, optlen);
281 }
282
283 int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
284 {
285 return getsockopt(fSockfd, level, optname, optval, optlen);
286 }
287
288 //timeout************************************************************************************************************
289
290 #if defined(__sun__) || defined(sun)
291 int JackNetUnixSocket::SetTimeOut(int us)
292 {
293 int flags;
294 fTimeOut = us;
295
296 if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
297 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
298 return -1;
299 }
300
301 flags |= O_NONBLOCK;
302 if (fcntl(fSockfd, F_SETFL, flags) < 0) {
303 jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
304 return 1;
305 }
306
307 return 0;
308 }
309
310 int JackNetUnixSocket::WaitRead()
311 {
312 if (fTimeOut > 0) {
313
314 struct timeval tv;
315 fd_set fdset;
316 ssize_t res;
317
318 tv.tv_sec = fTimeOut / 1000000;
319 tv.tv_usec = fTimeOut % 1000000;
320
321 FD_ZERO(&fdset);
322 FD_SET(fSockfd, &fdset);
323
324 do {
325 res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
326 } while (res < 0 && errno == EINTR);
327
328 if (res < 0) {
329 return res;
330 } else if (res == 0) {
331 errno = ETIMEDOUT;
332 return -1;
333 }
334 }
335
336 return 0;
337 }
338
339 int JackNetUnixSocket::WaitWrite()
340 {
341 if (fTimeOut > 0) {
342
343 struct timeval tv;
344 fd_set fdset;
345 ssize_t res;
346
347 tv.tv_sec = fTimeOut / 1000000;
348 tv.tv_usec = fTimeOut % 1000000;
349
350 FD_ZERO(&fdset);
351 FD_SET(fSockfd, &fdset);
352
353 do {
354 res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
355 } while (res < 0 && errno == EINTR);
356
357 if (res < 0) {
358 return res;
359 } else if (res == 0) {
360 errno = ETIMEDOUT;
361 return -1;
362 }
363 }
364
365 return 0;
366 }
367
368 #else
369 int JackNetUnixSocket::SetTimeOut(int us)
370 {
371 jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
372 struct timeval timeout;
373
374 //less than 1 sec
375 if (us < 1000000) {
376 timeout.tv_sec = 0;
377 timeout.tv_usec = us;
378 } else {
379 //more than 1 sec
380 float sec = float(us) / 1000000.f;
381 timeout.tv_sec = (int)sec;
382 float usec = (sec - float(timeout.tv_sec)) * 1000000;
383 timeout.tv_usec =(int)usec;
384 }
385 return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
386 }
387 #endif
388
389 //local loop**********************************************************************************************************
390 int JackNetUnixSocket::SetLocalLoop()
391 {
392 char disable = 0;
393 return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
394 }
395
396 //network operations**************************************************************************************************
397 int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
398 {
399 #if defined(__sun__) || defined(sun)
400 if (WaitWrite() < 0) {
401 return -1;
402 }
403 #endif
404 int res;
405 if ((res = sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t))) < 0) {
406 jack_error("SendTo fd = %ld err = %s", fSockfd, strerror(errno));
407 }
408 return res;
409 }
410
411 int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
412 {
413 int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
414 if (addr_conv < 1) {
415 return addr_conv;
416 }
417 fSendAddr.sin_port = htons(fPort);
418 #if defined(__sun__) || defined(sun)
419 if (WaitWrite() < 0) {
420 return -1;
421 }
422 #endif
423 return SendTo(buffer, nbytes, flags);
424 }
425
426 int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
427 {
428 #if defined(__sun__) || defined(sun)
429 if (WaitWrite() < 0) {
430 return -1;
431 }
432 #endif
433 int res;
434 if ((res = send(fSockfd, buffer, nbytes, flags)) < 0) {
435 jack_error("Send fd = %ld err = %s", fSockfd, strerror(errno));
436 }
437 return res;
438 }
439
440 int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
441 {
442 socklen_t addr_len = sizeof(socket_address_t);
443 #if defined(__sun__) || defined(sun)
444 if (WaitRead() < 0) {
445 return -1;
446 }
447 #endif
448 int res;
449 if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len)) < 0) {
450 jack_error("RecvFrom fd = %ld err = %s", fSockfd, strerror(errno));
451 }
452 return res;
453 }
454
455 int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
456 {
457 #if defined(__sun__) || defined(sun)
458 if (WaitRead() < 0) {
459 return -1;
460 }
461 #endif
462 int res;
463 if ((res = recv(fSockfd, buffer, nbytes, flags)) < 0) {
464 jack_error("Recv fd = %ld err = %s", fSockfd, strerror(errno));
465 }
466 return res;
467 }
468
469 int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags)
470 {
471 socklen_t addr_len = sizeof(socket_address_t);
472 #if defined(__sun__) || defined(sun)
473 if (WaitRead() < 0) {
474 return -1;
475 }
476 #endif
477 int res;
478 if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len)) < 0) {
479 jack_log("CatchHost fd = %ld err = %s", fSockfd, strerror(errno));
480 }
481 return res;
482 }
483
484 net_error_t JackNetUnixSocket::GetError()
485 {
486 switch (errno) {
487 case EAGAIN:
488 case ETIMEDOUT:
489 return NET_NO_DATA;
490
491 case ECONNABORTED:
492 case ECONNREFUSED:
493 case ECONNRESET:
494 case EINVAL:
495 case EHOSTDOWN:
496 case EHOSTUNREACH:
497 case ENETDOWN:
498 case ENETUNREACH:
499 return NET_CONN_ERROR;
500
501 default:
502 //return NET_OP_ERROR;
503 return NET_CONN_ERROR;
504 }
505 }
506
507 void JackNetUnixSocket::PrintError()
508 {
509 switch (errno) {
510
511 case EAGAIN:
512 jack_error("JackNetUnixSocket : EAGAIN");
513 break;
514 case ETIMEDOUT:
515 jack_error("JackNetUnixSocket : ETIMEDOUT");
516 break;
517 case ECONNABORTED:
518 jack_error("JackNetUnixSocket : ECONNABORTED");
519 break;
520 case ECONNREFUSED:
521 jack_error("JackNetUnixSocket : ECONNREFUSED");
522 break;
523 case ECONNRESET:
524 jack_error("JackNetUnixSocket : ECONNRESET");
525 break;
526 case EINVAL:
527 jack_error("JackNetUnixSocket : EINVAL");
528 break;
529 case EHOSTDOWN:
530 jack_error("JackNetUnixSocket : EHOSTDOWN");
531 break;
532 case EHOSTUNREACH:
533 jack_error("JackNetUnixSocket : EHOSTUNREACH");
534 break;
535 case ENETDOWN:
536 jack_error("JackNetUnixSocket : ENETDOWN");
537 break;
538 case ENETUNREACH:
539 jack_error("JackNetUnixSocket : ENETUNREACH");
540 break;
541 default:
542 jack_error("JackNetUnixSocket : %d", errno);
543 break;
544 }
545 }
546 }
jack_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92