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
59 typedef int socklen_t;
60 #endif
61 
62 #ifndef MSG_NOSIGNAL
63 #define MSG_NOSIGNAL 0
64 #endif
65 
66 static enet_uint32 timeBase = 0;
67 
68 int
enet_initialize(void)69 enet_initialize (void)
70 {
71     return 0;
72 }
73 
74 void
enet_deinitialize(void)75 enet_deinitialize (void)
76 {
77 }
78 
79 enet_uint32
enet_host_random_seed(void)80 enet_host_random_seed (void)
81 {
82     return (enet_uint32) time (NULL);
83 }
84 
85 enet_uint32
enet_time_get(void)86 enet_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 
95 void
enet_time_set(enet_uint32 newTimeBase)96 enet_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 
105 int
enet_address_set_host(ENetAddress * address,const char * name)106 enet_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 
167 int
enet_address_get_host_ip(const ENetAddress * address,char * name,size_t nameLength)168 enet_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 
187 int
enet_address_get_host(const ENetAddress * address,char * name,size_t nameLength)188 enet_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 
243 int
enet_socket_bind(ENetSocket socket,const ENetAddress * address)244 enet_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 
268 int
enet_socket_get_address(ENetSocket socket,ENetAddress * address)269 enet_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 
283 int
enet_socket_listen(ENetSocket socket,int backlog)284 enet_socket_listen (ENetSocket socket, int backlog)
285 {
286     return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
287 }
288 
289 ENetSocket
enet_socket_create(ENetSocketType type)290 enet_socket_create (ENetSocketType type)
291 {
292     return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
293 }
294 
295 int
enet_socket_set_option(ENetSocket socket,ENetSocketOption option,int value)296 enet_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 
353 int
enet_socket_get_option(ENetSocket socket,ENetSocketOption option,int * value)354 enet_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 
371 int
enet_socket_connect(ENetSocket socket,const ENetAddress * address)372 enet_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 
390 ENetSocket
enet_socket_accept(ENetSocket socket,ENetAddress * address)391 enet_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 
413 int
enet_socket_shutdown(ENetSocket socket,ENetSocketShutdown how)414 enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
415 {
416     return shutdown (socket, (int) how);
417 }
418 
419 void
enet_socket_destroy(ENetSocket socket)420 enet_socket_destroy (ENetSocket socket)
421 {
422     if (socket != -1)
423       close (socket);
424 }
425 
426 int
enet_socket_send(ENetSocket socket,const ENetAddress * address,const ENetBuffer * buffers,size_t bufferCount)427 enet_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 
466 int
enet_socket_receive(ENetSocket socket,ENetAddress * address,ENetBuffer * buffers,size_t bufferCount)467 enet_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 
511 int
enet_socketset_select(ENetSocket maxSocket,ENetSocketSet * readSet,ENetSocketSet * writeSet,enet_uint32 timeout)512 enet_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 
522 int
enet_socket_wait(ENetSocket socket,enet_uint32 * condition,enet_uint32 timeout)523 enet_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