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