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 |
69 | enet_initialize (void) |
70 | { |
71 | return 0; |
72 | } |
73 | |
74 | void |
75 | enet_deinitialize (void) |
76 | { |
77 | } |
78 | |
79 | enet_uint32 |
80 | enet_host_random_seed (void) |
81 | { |
82 | return (enet_uint32) time (NULL); |
83 | } |
84 | |
85 | enet_uint32 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
284 | enet_socket_listen (ENetSocket socket, int backlog) |
285 | { |
286 | return listen (socket, backlog < 0 ? SOMAXCONN : backlog); |
287 | } |
288 | |
289 | ENetSocket |
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 |
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 |
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 |
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 |
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 |
414 | enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how) |
415 | { |
416 | return shutdown (socket, (int) how); |
417 | } |
418 | |
419 | void |
420 | enet_socket_destroy (ENetSocket socket) |
421 | { |
422 | if (socket != -1) |
423 | close (socket); |
424 | } |
425 | |
426 | int |
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 |
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 |
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 |
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 | |