Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

patch libenet to support ipv6

This is only done for Linux so far.

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