Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ipv6/src/external/enet/unix.c @ 7394

Last change on this file since 7394 was 7394, checked in by adrfried, 14 years ago

use newest WinSock version

File size: 12.3 KB
Line 
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 <netdb.h>
13#include <unistd.h>
14#include <string.h>
15#include <errno.h>
16#include <time.h>
17
18#define ENET_BUILDING_LIB 1
19#include "enet/enet.h"
20
21#ifdef HAS_FCNTL
22#include <fcntl.h>
23#endif
24
25#ifdef __APPLE__
26#undef HAS_POLL
27#endif
28
29#ifdef HAS_POLL
30#include <sys/poll.h>
31#endif
32
33#ifndef HAS_SOCKLEN_T
34typedef int socklen_t;
35#endif
36
37#ifndef MSG_NOSIGNAL
38#define MSG_NOSIGNAL 0
39#endif
40
41static enet_uint32 timeBase = 0;
42
43int
44enet_initialize (void)
45{
46    return 0;
47}
48
49void
50enet_deinitialize (void)
51{
52}
53
54enet_uint32
55enet_time_get (void)
56{
57    struct timeval timeVal;
58
59    gettimeofday (& timeVal, NULL);
60
61    return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
62}
63
64void
65enet_time_set (enet_uint32 newTimeBase)
66{
67    struct timeval timeVal;
68
69    gettimeofday (& timeVal, NULL);
70   
71    timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
72}
73
74static enet_uint16
75enet_af (ENetAddressFamily family)
76{
77    if (family == ENET_IPV4)
78        return AF_INET;
79    if (family == ENET_IPV6)
80        return AF_INET6;
81    return 0;
82}
83
84static socklen_t
85enet_sa_size (ENetAddressFamily family)
86{
87    if (family == ENET_IPV4)
88        return sizeof (struct sockaddr_in);
89    if (family == ENET_IPV6)
90        return sizeof (struct sockaddr_in6);
91    return 0;
92}
93
94static ENetAddressFamily
95enet_address_set_address (ENetAddress * address, const struct sockaddr * sin)
96{
97    memset (address, 0, sizeof (ENetAddress));
98    if (sin -> sa_family == AF_INET)
99    {
100        address -> host = enet_address_map4 ((((struct sockaddr_in *) sin) -> sin_addr.s_addr));
101        /* address -> scopeID = 0; */
102        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in *) sin) -> sin_port);
103        return ENET_IPV4;
104    }
105    if (sin -> sa_family == AF_INET6)
106    {
107        address -> host = * (ENetHostAddress *) & ((struct sockaddr_in6 *) sin) -> sin6_addr;
108        address -> scopeID = ((struct sockaddr_in6 *) sin) -> sin6_scope_id;
109        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in6 *) sin) -> sin6_port);
110        return ENET_IPV6;
111    }
112    return ENET_NO_ADDRESS_FAMILY;
113}
114
115static int
116enet_address_set_sin (struct sockaddr * sin, const ENetAddress * address, ENetAddressFamily family)
117{
118    memset (sin, 0, enet_sa_size(family));
119    if (family == ENET_IPV4 &&
120      (enet_get_address_family (address) == ENET_IPV4 ||
121      !memcmp (& address -> host, & ENET_HOST_ANY, sizeof(ENetHostAddress))))
122    {
123        ((struct sockaddr_in *) sin) -> sin_family = AF_INET;
124        ((struct sockaddr_in *) sin) -> sin_addr = * (struct in_addr *) & address -> host.addr[12];
125        ((struct sockaddr_in *) sin) -> sin_port = ENET_HOST_TO_NET_16 (address -> port);
126        return 0;
127    }
128    else if (family == ENET_IPV6)
129    {
130        ((struct sockaddr_in6 *) sin) -> sin6_family = AF_INET6;
131        ((struct sockaddr_in6 *) sin) -> sin6_addr = * (struct in6_addr *) & address -> host;
132        ((struct sockaddr_in6 *) sin) -> sin6_scope_id = address -> scopeID;
133        ((struct sockaddr_in6 *) sin) -> sin6_port = ENET_HOST_TO_NET_16 (address -> port);
134        return 0;
135    }
136    return -1;
137}
138
139int
140enet_address_set_host (ENetAddress * address, const char * name)
141{
142    enet_uint16 port = address -> port;
143    struct addrinfo hints;
144    struct addrinfo * result;
145    struct addrinfo * res;
146
147    memset(& hints, 0, sizeof (hints));
148    hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
149    hints.ai_family = AF_UNSPEC;
150
151    if ( getaddrinfo(name, NULL, &hints, &result) )
152        return -1;
153
154    for (res = result; res != NULL; res = res -> ai_next)
155    {
156        if ( enet_address_set_address(address, res -> ai_addr) != ENET_NO_ADDRESS_FAMILY )
157            break;
158    }
159
160    address -> port = port;
161    freeaddrinfo(result);
162    if (res == NULL) return -1;
163
164    return 0;
165}
166
167static int
168enet_address_get_host_x (const ENetAddress * address, char * name, size_t nameLength, int flags)
169{
170    struct sockaddr_storage sin;
171    enet_address_set_sin((struct sockaddr *) & sin, address, ENET_IPV6);
172
173    if ( getnameinfo((struct sockaddr *) & sin, enet_sa_size (ENET_IPV6), name, nameLength, NULL, 0, flags))
174        return -1;
175
176    return 0;
177}
178
179int
180enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
181{
182    return enet_address_get_host_x(address, name, nameLength, NI_NUMERICHOST);
183}
184
185int
186enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
187{
188    return enet_address_get_host_x(address, name, nameLength, 0);
189}
190
191int
192enet_socket_bind (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
193{
194    struct sockaddr_storage sin;
195
196    if (address != NULL)
197    {
198        enet_address_set_sin((struct sockaddr *) & sin, address, family);
199    }
200    else
201    {
202        ENetAddress address_;
203        address_.host = ENET_HOST_ANY;
204        address_.scopeID = 0;
205        address_.port = 0;
206        enet_address_set_sin((struct sockaddr *) & sin, & address_, family);
207    }
208
209    return bind (socket, (struct sockaddr *) & sin, enet_sa_size(family));
210}
211
212int
213enet_socket_listen (ENetSocket socket, int backlog)
214{
215    return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
216}
217
218ENetSocket
219enet_socket_create (ENetSocketType type, ENetAddressFamily family)
220{
221    ENetSocket sock = socket (enet_af (family), type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
222
223#ifdef IPV6_V6ONLY
224    if (family == ENET_IPV6)
225    {
226        int value = 1;
227        setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, & value, sizeof (int));
228    }
229#endif /* IPV6_V6ONLY */
230
231    return sock;
232}
233
234int
235enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
236{
237    int result = -1;
238    switch (option)
239    {
240        case ENET_SOCKOPT_NONBLOCK:
241#ifdef HAS_FCNTL
242            result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL));
243#else
244            result = ioctl (socket, FIONBIO, & value);
245#endif
246            break;
247
248        case ENET_SOCKOPT_BROADCAST:
249            result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
250            break;
251
252        case ENET_SOCKOPT_REUSEADDR:
253            result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
254            break;
255
256        case ENET_SOCKOPT_RCVBUF:
257            result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
258            break;
259
260        case ENET_SOCKOPT_SNDBUF:
261            result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
262            break;
263
264        default:
265            break;
266    }
267    return result == -1 ? -1 : 0;
268}
269
270int
271enet_socket_connect (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
272{
273    struct sockaddr_storage sin;
274    enet_address_set_sin((struct sockaddr *) & sin, address, family);
275
276    return connect (socket, (struct sockaddr *) & sin, enet_sa_size (family));
277}
278
279ENetSocket
280enet_socket_accept (ENetSocket socket, ENetAddress * address, ENetAddressFamily family)
281{
282    int result;
283    struct sockaddr_storage sin;
284    socklen_t sinLength = enet_sa_size (family);
285
286    result = accept (socket, 
287                     address != NULL ? (struct sockaddr *) & sin : NULL, 
288                     address != NULL ? & sinLength : NULL);
289
290    if (result == -1)
291      return ENET_SOCKET_NULL;
292
293    if (address != NULL)
294    {
295        enet_address_set_address(address, (struct sockaddr *) & sin);
296    }
297
298    return result;
299} 
300   
301void
302enet_socket_destroy (ENetSocket socket)
303{
304    close (socket);
305}
306
307int
308enet_socket_send (ENetSocket socket,
309                  const ENetAddress * address,
310                  const ENetBuffer * buffers,
311                  size_t bufferCount,
312                  ENetAddressFamily family)
313{
314    struct msghdr msgHdr;
315    struct sockaddr_storage sin;
316    int sentLength;
317
318    memset (& msgHdr, 0, sizeof (struct msghdr));
319
320    if (address != NULL)
321    {
322        enet_address_set_sin((struct sockaddr *) & sin, address, family);
323        msgHdr.msg_name = & sin;
324        msgHdr.msg_namelen = enet_sa_size (family);
325    }
326
327    msgHdr.msg_iov = (struct iovec *) buffers;
328    msgHdr.msg_iovlen = bufferCount;
329
330    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
331   
332    if (sentLength == -1)
333    {
334       if (errno == EWOULDBLOCK)
335         return 0;
336
337       return -1;
338    }
339
340    return sentLength;
341}
342
343int
344enet_socket_receive (ENetSocket socket,
345                     ENetAddress * address,
346                     ENetBuffer * buffers,
347                     size_t bufferCount,
348                     ENetAddressFamily family)
349{
350    struct msghdr msgHdr;
351    struct sockaddr_storage sin;
352    int recvLength;
353
354    memset (& msgHdr, 0, sizeof (struct msghdr));
355
356    if (address != NULL)
357    {
358        msgHdr.msg_name = & sin;
359        msgHdr.msg_namelen = enet_sa_size (family);
360    }
361
362    msgHdr.msg_iov = (struct iovec *) buffers;
363    msgHdr.msg_iovlen = bufferCount;
364
365    recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
366
367    if (recvLength == -1)
368    {
369       if (errno == EWOULDBLOCK)
370         return 0;
371
372       return -1;
373    }
374
375#ifdef HAS_MSGHDR_FLAGS
376    if (msgHdr.msg_flags & MSG_TRUNC)
377      return -1;
378#endif
379
380    if (address != NULL)
381    {
382        enet_address_set_address(address, (struct sockaddr *) & sin);
383    }
384
385    return recvLength;
386}
387
388int
389enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
390{
391    struct timeval timeVal;
392
393    timeVal.tv_sec = timeout / 1000;
394    timeVal.tv_usec = (timeout % 1000) * 1000;
395
396    return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
397}
398
399int
400enet_socket_wait (ENetSocket socket4, ENetSocket socket6, enet_uint32 * condition, enet_uint32 timeout)
401{
402#ifdef HAS_POLL
403    struct pollfd pollSocket[2];
404    int pollCount;
405
406    pollSocket[0].fd = socket4;
407    pollSocket[1].fd = socket6;
408    pollSocket[0].events = 0;
409    pollSocket[1].events = 0;
410    /* pollSocket[0].revents = 0; */
411    pollSocket[1].revents = 0;
412
413    if (pollSocket[0].fd == ENET_SOCKET_NULL)
414    {
415        pollSocket[0].fd = pollSocket[1].fd;
416        pollSocket[1].fd = ENET_SOCKET_NULL;
417    }
418
419    if (* condition & ENET_SOCKET_WAIT_SEND)
420    {
421        pollSocket[0].events |= POLLOUT;
422        pollSocket[1].events |= POLLOUT;
423    }
424
425    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
426    {
427        pollSocket[0].events |= POLLIN;
428        pollSocket[1].events |= POLLIN;
429    }
430
431    pollCount = poll (pollSocket, pollSocket[1].fd != ENET_SOCKET_NULL ? 2 : 1, timeout);
432
433    if (pollCount < 0)
434      return -1;
435
436    * condition = ENET_SOCKET_WAIT_NONE;
437
438    if (pollCount == 0)
439      return 0;
440
441    if ((pollSocket[0].revents | pollSocket[1].revents) & POLLOUT)
442      * condition |= ENET_SOCKET_WAIT_SEND;
443   
444    if ((pollSocket[0].revents | pollSocket[1].revents) & POLLIN)
445      * condition |= ENET_SOCKET_WAIT_RECEIVE;
446
447    return 0;
448#else
449    fd_set readSet, writeSet;
450    struct timeval timeVal;
451    int selectCount;
452    ENetSocket maxSocket;
453
454    timeVal.tv_sec = timeout / 1000;
455    timeVal.tv_usec = (timeout % 1000) * 1000;
456
457    FD_ZERO (& readSet);
458    FD_ZERO (& writeSet);
459
460    if (* condition & ENET_SOCKET_WAIT_SEND)
461    {
462        if (socket4 != ENET_SOCKET_NULL)
463            FD_SET (socket4, & writeSet);
464        if (socket6 != ENET_SOCKET_NULL)
465            FD_SET (socket6, & writeSet);
466    }
467
468    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
469    {
470        if (socket4 != ENET_SOCKET_NULL)
471            FD_SET (socket4, & readSet);
472        if (socket6 != ENET_SOCKET_NULL)
473            FD_SET (socket6, & readSet);
474    }
475
476    maxSocket = 0;
477    if (socket4 != ENET_SOCKET_NULL)
478        maxSocket = socket4;
479    if (socket6 != ENET_SOCKET_NULL && socket6 > maxSocket)
480        maxSocket = socket6;
481
482    selectCount = select (maxSocket + 1, & readSet, & writeSet, NULL, & timeVal);
483
484    if (selectCount < 0)
485      return -1;
486
487    * condition = ENET_SOCKET_WAIT_NONE;
488
489    if (selectCount == 0)
490      return 0;
491
492    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & writeSet)) ||
493        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & writeSet)) )
494        * condition |= ENET_SOCKET_WAIT_SEND;
495
496    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & readSet)) ||
497        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & readSet)) )
498        * condition |= ENET_SOCKET_WAIT_RECEIVE;
499
500    return 0;
501#endif
502}
503
504#endif
505
Note: See TracBrowser for help on using the repository browser.