Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

using two separate sockets for ipv4 and ipv6

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