1/**
2 @file unix.c
3 @brief ENet Unix system specific functions
4*/
5#ifndef _WIN32
6
7#include <sys/types.h>
8#include <sys/socket.h>
9#include <sys/ioctl.h>
10#include <sys/time.h>
11#include <arpa/inet.h>
12#include <netinet/tcp.h>
13#include <netdb.h>
14#include <unistd.h>
15#include <string.h>
16#include <errno.h>
17#include <time.h>
18
19#define ENET_BUILDING_LIB 1
20#include "enet/enet.h"
21
22#ifdef __APPLE__
23#ifdef HAS_POLL
24#undef HAS_POLL
25#endif
26#ifndef HAS_FCNTL
27#define HAS_FCNTL 1
28#endif
29#ifndef HAS_INET_PTON
30#define HAS_INET_PTON 1
31#endif
32#ifndef HAS_INET_NTOP
33#define HAS_INET_NTOP 1
34#endif
35#ifndef HAS_MSGHDR_FLAGS
36#define HAS_MSGHDR_FLAGS 1
37#endif
38#ifndef HAS_SOCKLEN_T
39#define HAS_SOCKLEN_T 1
40#endif
41#ifndef HAS_GETADDRINFO
42#define HAS_GETADDRINFO 1
43#endif
44#ifndef HAS_GETNAMEINFO
45#define HAS_GETNAMEINFO 1
46#endif
47#endif
48
49#ifdef HAS_FCNTL
50#include <fcntl.h>
51#endif
52
53#ifdef HAS_POLL
54#include <sys/poll.h>
55#endif
56
57#include "common/config.h"
58#ifndef HAS_SOCKLEN_T
59typedef int socklen_t;
60#endif
61
62#ifndef MSG_NOSIGNAL
63#define MSG_NOSIGNAL 0
64#endif
65
66static enet_uint32 timeBase = 0;
67
68int
69enet_initialize (void)
70{
71 return 0;
72}
73
74void
75enet_deinitialize (void)
76{
77}
78
79enet_uint32
80enet_host_random_seed (void)
81{
82 return (enet_uint32) time (NULL);
83}
84
85enet_uint32
86enet_time_get (void)
87{
88 struct timeval timeVal;
89
90 gettimeofday (& timeVal, NULL);
91
92 return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
93}
94
95void
96enet_time_set (enet_uint32 newTimeBase)
97{
98 struct timeval timeVal;
99
100 gettimeofday (& timeVal, NULL);
101
102 timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
103}
104
105int
106enet_address_set_host (ENetAddress * address, const char * name)
107{
108#ifdef HAS_GETADDRINFO
109 struct addrinfo hints, * resultList = NULL, * result = NULL;
110
111 memset (& hints, 0, sizeof (hints));
112 hints.ai_family = AF_INET;
113
114 if (getaddrinfo (name, NULL, NULL, & resultList) != 0)
115 return -1;
116
117 for (result = resultList; result != NULL; result = result -> ai_next)
118 {
119 if (result -> ai_family == AF_INET && result -> ai_addr != NULL && result -> ai_addrlen >= sizeof (struct sockaddr_in))
120 {
121 struct sockaddr_in * sin = (struct sockaddr_in *) result -> ai_addr;
122
123 address -> host = sin -> sin_addr.s_addr;
124
125 freeaddrinfo (resultList);
126
127 return 0;
128 }
129 }
130
131 if (resultList != NULL)
132 freeaddrinfo (resultList);
133#else
134 struct hostent * hostEntry = NULL;
135#ifdef HAS_GETHOSTBYNAME_R
136 struct hostent hostData;
137 char buffer [2048];
138 int errnum;
139
140#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
141 gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
142#else
143 hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
144#endif
145#else
146 hostEntry = gethostbyname (name);
147#endif
148
149 if (hostEntry != NULL && hostEntry -> h_addrtype == AF_INET)
150 {
151 address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
152
153 return 0;
154 }
155#endif
156
157#ifdef HAS_INET_PTON
158 if (! inet_pton (AF_INET, name, & address -> host))
159#else
160 if (! inet_aton (name, (struct in_addr *) & address -> host))
161#endif
162 return -1;
163
164 return 0;
165}
166
167int
168enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
169{
170#ifdef HAS_INET_NTOP
171 if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
172#else
173 char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
174 if (addr != NULL)
175 {
176 size_t addrLen = strlen(addr);
177 if (addrLen >= nameLength)
178 return -1;
179 memcpy (name, addr, addrLen + 1);
180 }
181 else
182#endif
183 return -1;
184 return 0;
185}
186
187int
188enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
189{
190#ifdef HAS_GETNAMEINFO
191 struct sockaddr_in sin;
192 int err;
193
194 memset (& sin, 0, sizeof (struct sockaddr_in));
195
196 sin.sin_family = AF_INET;
197 sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
198 sin.sin_addr.s_addr = address -> host;
199
200 err = getnameinfo ((struct sockaddr *) & sin, sizeof (sin), name, nameLength, NULL, 0, NI_NAMEREQD);
201 if (! err)
202 {
203 if (name != NULL && nameLength > 0 && ! memchr (name, '\0', nameLength))
204 return -1;
205 return 0;
206 }
207 if (err != EAI_NONAME)
208 return -1;
209#else
210 struct in_addr in;
211 struct hostent * hostEntry = NULL;
212#ifdef HAS_GETHOSTBYADDR_R
213 struct hostent hostData;
214 char buffer [2048];
215 int errnum;
216
217 in.s_addr = address -> host;
218
219#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
220 gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
221#else
222 hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
223#endif
224#else
225 in.s_addr = address -> host;
226
227 hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
228#endif
229
230 if (hostEntry != NULL)
231 {
232 size_t hostLen = strlen (hostEntry -> h_name);
233 if (hostLen >= nameLength)
234 return -1;
235 memcpy (name, hostEntry -> h_name, hostLen + 1);
236 return 0;
237 }
238#endif
239
240 return enet_address_get_host_ip (address, name, nameLength);
241}
242
243int
244enet_socket_bind (ENetSocket socket, const ENetAddress * address)
245{
246 struct sockaddr_in sin;
247
248 memset (& sin, 0, sizeof (struct sockaddr_in));
249
250 sin.sin_family = AF_INET;
251
252 if (address != NULL)
253 {
254 sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
255 sin.sin_addr.s_addr = address -> host;
256 }
257 else
258 {
259 sin.sin_port = 0;
260 sin.sin_addr.s_addr = INADDR_ANY;
261 }
262
263 return bind (socket,
264 (struct sockaddr *) & sin,
265 sizeof (struct sockaddr_in));
266}
267
268int
269enet_socket_get_address (ENetSocket socket, ENetAddress * address)
270{
271 struct sockaddr_in sin;
272 socklen_t sinLength = sizeof (struct sockaddr_in);
273
274 if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
275 return -1;
276
277 address -> host = (enet_uint32) sin.sin_addr.s_addr;
278 address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
279
280 return 0;
281}
282
283int
284enet_socket_listen (ENetSocket socket, int backlog)
285{
286 return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
287}
288
289ENetSocket
290enet_socket_create (ENetSocketType type)
291{
292 return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
293}
294
295int
296enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
297{
298 int result = -1;
299 switch (option)
300 {
301 case ENET_SOCKOPT_NONBLOCK:
302#ifdef HAS_FCNTL
303 result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK));
304#else
305 result = ioctl (socket, FIONBIO, & value);
306#endif
307 break;
308
309 case ENET_SOCKOPT_BROADCAST:
310 result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
311 break;
312
313 case ENET_SOCKOPT_REUSEADDR:
314 result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
315 break;
316
317 case ENET_SOCKOPT_RCVBUF:
318 result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
319 break;
320
321 case ENET_SOCKOPT_SNDBUF:
322 result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
323 break;
324
325 case ENET_SOCKOPT_RCVTIMEO:
326 {
327 struct timeval timeVal;
328 timeVal.tv_sec = value / 1000;
329 timeVal.tv_usec = (value % 1000) * 1000;
330 result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval));
331 break;
332 }
333
334 case ENET_SOCKOPT_SNDTIMEO:
335 {
336 struct timeval timeVal;
337 timeVal.tv_sec = value / 1000;
338 timeVal.tv_usec = (value % 1000) * 1000;
339 result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval));
340 break;
341 }
342
343 case ENET_SOCKOPT_NODELAY:
344 result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
345 break;
346
347 default:
348 break;
349 }
350 return result == -1 ? -1 : 0;
351}
352
353int
354enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
355{
356 int result = -1;
357 socklen_t len;
358 switch (option)
359 {
360 case ENET_SOCKOPT_ERROR:
361 len = sizeof (int);
362 result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len);
363 break;
364
365 default:
366 break;
367 }
368 return result == -1 ? -1 : 0;
369}
370
371int
372enet_socket_connect (ENetSocket socket, const ENetAddress * address)
373{
374 struct sockaddr_in sin;
375 int result;
376
377 memset (& sin, 0, sizeof (struct sockaddr_in));
378
379 sin.sin_family = AF_INET;
380 sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
381 sin.sin_addr.s_addr = address -> host;
382
383 result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
384 if (result == -1 && errno == EINPROGRESS)
385 return 0;
386
387 return result;
388}
389
390ENetSocket
391enet_socket_accept (ENetSocket socket, ENetAddress * address)
392{
393 int result;
394 struct sockaddr_in sin;
395 socklen_t sinLength = sizeof (struct sockaddr_in);
396
397 result = accept (socket,
398 address != NULL ? (struct sockaddr *) & sin : NULL,
399 address != NULL ? & sinLength : NULL);
400
401 if (result == -1)
402 return ENET_SOCKET_NULL;
403
404 if (address != NULL)
405 {
406 address -> host = (enet_uint32) sin.sin_addr.s_addr;
407 address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
408 }
409
410 return result;
411}
412
413int
414enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
415{
416 return shutdown (socket, (int) how);
417}
418
419void
420enet_socket_destroy (ENetSocket socket)
421{
422 if (socket != -1)
423 close (socket);
424}
425
426int
427enet_socket_send (ENetSocket socket,
428 const ENetAddress * address,
429 const ENetBuffer * buffers,
430 size_t bufferCount)
431{
432 struct msghdr msgHdr;
433 struct sockaddr_in sin;
434 int sentLength;
435
436 memset (& msgHdr, 0, sizeof (struct msghdr));
437
438 if (address != NULL)
439 {
440 memset (& sin, 0, sizeof (struct sockaddr_in));
441
442 sin.sin_family = AF_INET;
443 sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
444 sin.sin_addr.s_addr = address -> host;
445
446 msgHdr.msg_name = & sin;
447 msgHdr.msg_namelen = sizeof (struct sockaddr_in);
448 }
449
450 msgHdr.msg_iov = (struct iovec *) buffers;
451 msgHdr.msg_iovlen = bufferCount;
452
453 sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
454
455 if (sentLength == -1)
456 {
457 if (errno == EWOULDBLOCK)
458 return 0;
459
460 return -1;
461 }
462
463 return sentLength;
464}
465
466int
467enet_socket_receive (ENetSocket socket,
468 ENetAddress * address,
469 ENetBuffer * buffers,
470 size_t bufferCount)
471{
472 struct msghdr msgHdr;
473 struct sockaddr_in sin;
474 int recvLength;
475
476 memset (& msgHdr, 0, sizeof (struct msghdr));
477
478 if (address != NULL)
479 {
480 msgHdr.msg_name = & sin;
481 msgHdr.msg_namelen = sizeof (struct sockaddr_in);
482 }
483
484 msgHdr.msg_iov = (struct iovec *) buffers;
485 msgHdr.msg_iovlen = bufferCount;
486
487 recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
488
489 if (recvLength == -1)
490 {
491 if (errno == EWOULDBLOCK)
492 return 0;
493
494 return -1;
495 }
496
497#ifdef HAS_MSGHDR_FLAGS
498 if (msgHdr.msg_flags & MSG_TRUNC)
499 return -1;
500#endif
501
502 if (address != NULL)
503 {
504 address -> host = (enet_uint32) sin.sin_addr.s_addr;
505 address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
506 }
507
508 return recvLength;
509}
510
511int
512enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
513{
514 struct timeval timeVal;
515
516 timeVal.tv_sec = timeout / 1000;
517 timeVal.tv_usec = (timeout % 1000) * 1000;
518
519 return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
520}
521
522int
523enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
524{
525#ifdef HAS_POLL
526 struct pollfd pollSocket;
527 int pollCount;
528
529 pollSocket.fd = socket;
530 pollSocket.events = 0;
531
532 if (* condition & ENET_SOCKET_WAIT_SEND)
533 pollSocket.events |= POLLOUT;
534
535 if (* condition & ENET_SOCKET_WAIT_RECEIVE)
536 pollSocket.events |= POLLIN;
537
538 pollCount = poll (& pollSocket, 1, timeout);
539
540 if (pollCount < 0)
541 {
542 if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
543 {
544 * condition = ENET_SOCKET_WAIT_INTERRUPT;
545
546 return 0;
547 }
548
549 return -1;
550 }
551
552 * condition = ENET_SOCKET_WAIT_NONE;
553
554 if (pollCount == 0)
555 return 0;
556
557 if (pollSocket.revents & POLLOUT)
558 * condition |= ENET_SOCKET_WAIT_SEND;
559
560 if (pollSocket.revents & POLLIN)
561 * condition |= ENET_SOCKET_WAIT_RECEIVE;
562
563 return 0;
564#else
565 fd_set readSet, writeSet;
566 struct timeval timeVal;
567 int selectCount;
568
569 timeVal.tv_sec = timeout / 1000;
570 timeVal.tv_usec = (timeout % 1000) * 1000;
571
572 FD_ZERO (& readSet);
573 FD_ZERO (& writeSet);
574
575 if (* condition & ENET_SOCKET_WAIT_SEND)
576 FD_SET (socket, & writeSet);
577
578 if (* condition & ENET_SOCKET_WAIT_RECEIVE)
579 FD_SET (socket, & readSet);
580
581 selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
582
583 if (selectCount < 0)
584 {
585 if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
586 {
587 * condition = ENET_SOCKET_WAIT_INTERRUPT;
588
589 return 0;
590 }
591
592 return -1;
593 }
594
595 * condition = ENET_SOCKET_WAIT_NONE;
596
597 if (selectCount == 0)
598 return 0;
599
600 if (FD_ISSET (socket, & writeSet))
601 * condition |= ENET_SOCKET_WAIT_SEND;
602
603 if (FD_ISSET (socket, & readSet))
604 * condition |= ENET_SOCKET_WAIT_RECEIVE;
605
606 return 0;
607#endif
608}
609
610#endif
611
612