source: osgVisual/trunk/src/cluster/enet/unix.c @ 217

Last change on this file since 217 was 96, checked in by Torben Dannhauer, 14 years ago
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
34// todo check if new solution works
35//typedef int socklen_t;
36typedef __socklen_t socklen_t;
37#endif
38
39#ifndef MSG_NOSIGNAL
40#define MSG_NOSIGNAL 0
41#endif
42
43static enet_uint32 timeBase = 0;
44
45int
46enet_initialize (void)
47{
48    return 0;
49}
50
51void
52enet_deinitialize (void)
53{
54}
55
56enet_uint32
57enet_time_get (void)
58{
59    struct timeval timeVal;
60
61    gettimeofday (& timeVal, NULL);
62
63    return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
64}
65
66void
67enet_time_set (enet_uint32 newTimeBase)
68{
69    struct timeval timeVal;
70
71    gettimeofday (& timeVal, NULL);
72   
73    timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
74}
75
76int
77enet_address_set_host (ENetAddress * address, const char * name)
78{
79    struct hostent * hostEntry = NULL;
80#ifdef HAS_GETHOSTBYNAME_R
81    struct hostent hostData;
82    char buffer [2048];
83    int errnum;
84
85#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
86    gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
87#else
88    hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
89#endif
90#else
91    hostEntry = gethostbyname (name);
92#endif
93
94    if (hostEntry == NULL ||
95        hostEntry -> h_addrtype != AF_INET)
96    {
97#ifdef HAS_INET_PTON
98        if (! inet_pton (AF_INET, name, & address -> host))
99#else
100        if (! inet_aton (name, (struct in_addr *) & address -> host))
101#endif
102            return -1;
103        return 0;
104    }
105
106    address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
107
108    return 0;
109}
110
111int
112enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
113{
114#ifdef HAS_INET_NTOP
115    if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
116#else
117    char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
118    if (addr != NULL)
119        strncpy (name, addr, nameLength);
120    else
121#endif
122        return -1;
123    return 0;
124}
125
126int
127enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
128{
129    struct in_addr in;
130    struct hostent * hostEntry = NULL;
131#ifdef HAS_GETHOSTBYADDR_R
132    struct hostent hostData;
133    char buffer [2048];
134    int errnum;
135
136    in.s_addr = address -> host;
137
138#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
139    gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
140#else
141    hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
142#endif
143#else
144    in.s_addr = address -> host;
145
146    hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
147#endif
148
149    if (hostEntry == NULL)
150      return enet_address_get_host_ip (address, name, nameLength);
151
152    strncpy (name, hostEntry -> h_name, nameLength);
153
154    return 0;
155}
156
157int
158enet_socket_bind (ENetSocket socket, const ENetAddress * address)
159{
160    struct sockaddr_in sin;
161
162    memset (& sin, 0, sizeof (struct sockaddr_in));
163
164    sin.sin_family = AF_INET;
165
166    if (address != NULL)
167    {
168       sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
169       sin.sin_addr.s_addr = address -> host;
170    }
171    else
172    {
173       sin.sin_port = 0;
174       sin.sin_addr.s_addr = INADDR_ANY;
175    }
176
177    return bind (socket,
178                 (struct sockaddr *) & sin,
179                 sizeof (struct sockaddr_in)); 
180}
181
182int 
183enet_socket_listen (ENetSocket socket, int backlog)
184{
185    return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
186}
187
188ENetSocket
189enet_socket_create (ENetSocketType type)
190{
191    return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
192}
193
194int
195enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
196{
197    int result = -1;
198    switch (option)
199    {
200        case ENET_SOCKOPT_NONBLOCK:
201#ifdef HAS_FCNTL
202            result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL));
203#else
204            result = ioctl (socket, FIONBIO, & value);
205#endif
206            break;
207
208        case ENET_SOCKOPT_BROADCAST:
209            result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
210            break;
211
212        case ENET_SOCKOPT_REUSEADDR:
213            result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
214            break;
215
216        case ENET_SOCKOPT_RCVBUF:
217            result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
218            break;
219
220        case ENET_SOCKOPT_SNDBUF:
221            result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
222            break;
223
224        default:
225            break;
226    }
227    return result == -1 ? -1 : 0;
228}
229
230int
231enet_socket_connect (ENetSocket socket, const ENetAddress * address)
232{
233    struct sockaddr_in sin;
234
235    memset (& sin, 0, sizeof (struct sockaddr_in));
236
237    sin.sin_family = AF_INET;
238    sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
239    sin.sin_addr.s_addr = address -> host;
240
241    return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
242}
243
244ENetSocket
245enet_socket_accept (ENetSocket socket, ENetAddress * address)
246{
247    int result;
248    struct sockaddr_in sin;
249    socklen_t sinLength = sizeof (struct sockaddr_in);
250
251    result = accept (socket, 
252                     address != NULL ? (struct sockaddr *) & sin : NULL, 
253                     address != NULL ? & sinLength : NULL);
254   
255    if (result == -1)
256      return ENET_SOCKET_NULL;
257
258    if (address != NULL)
259    {
260        address -> host = (enet_uint32) sin.sin_addr.s_addr;
261        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
262    }
263
264    return result;
265} 
266   
267void
268enet_socket_destroy (ENetSocket socket)
269{
270    close (socket);
271}
272
273int
274enet_socket_send (ENetSocket socket,
275                  const ENetAddress * address,
276                  const ENetBuffer * buffers,
277                  size_t bufferCount)
278{
279    struct msghdr msgHdr;
280    struct sockaddr_in sin;
281    int sentLength;
282
283    memset (& msgHdr, 0, sizeof (struct msghdr));
284
285    if (address != NULL)
286    {
287        memset (& sin, 0, sizeof (struct sockaddr_in));
288
289        sin.sin_family = AF_INET;
290        sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
291        sin.sin_addr.s_addr = address -> host;
292
293        msgHdr.msg_name = & sin;
294        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
295    }
296
297    msgHdr.msg_iov = (struct iovec *) buffers;
298    msgHdr.msg_iovlen = bufferCount;
299
300    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
301   
302    if (sentLength == -1)
303    {
304       if (errno == EWOULDBLOCK)
305         return 0;
306
307       return -1;
308    }
309
310    return sentLength;
311}
312
313int
314enet_socket_receive (ENetSocket socket,
315                     ENetAddress * address,
316                     ENetBuffer * buffers,
317                     size_t bufferCount)
318{
319    struct msghdr msgHdr;
320    struct sockaddr_in sin;
321    int recvLength;
322
323    memset (& msgHdr, 0, sizeof (struct msghdr));
324
325    if (address != NULL)
326    {
327        msgHdr.msg_name = & sin;
328        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
329    }
330
331    msgHdr.msg_iov = (struct iovec *) buffers;
332    msgHdr.msg_iovlen = bufferCount;
333
334    recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
335
336    if (recvLength == -1)
337    {
338       if (errno == EWOULDBLOCK)
339         return 0;
340
341       return -1;
342    }
343
344#ifdef HAS_MSGHDR_FLAGS
345    if (msgHdr.msg_flags & MSG_TRUNC)
346      return -1;
347#endif
348
349    if (address != NULL)
350    {
351        address -> host = (enet_uint32) sin.sin_addr.s_addr;
352        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
353    }
354
355    return recvLength;
356}
357
358int
359enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
360{
361    struct timeval timeVal;
362
363    timeVal.tv_sec = timeout / 1000;
364    timeVal.tv_usec = (timeout % 1000) * 1000;
365
366    return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
367}
368
369int
370enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
371{
372#ifdef HAS_POLL
373    struct pollfd pollSocket;
374    int pollCount;
375   
376    pollSocket.fd = socket;
377    pollSocket.events = 0;
378
379    if (* condition & ENET_SOCKET_WAIT_SEND)
380      pollSocket.events |= POLLOUT;
381
382    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
383      pollSocket.events |= POLLIN;
384
385    pollCount = poll (& pollSocket, 1, timeout);
386
387    if (pollCount < 0)
388      return -1;
389
390    * condition = ENET_SOCKET_WAIT_NONE;
391
392    if (pollCount == 0)
393      return 0;
394
395    if (pollSocket.revents & POLLOUT)
396      * condition |= ENET_SOCKET_WAIT_SEND;
397   
398    if (pollSocket.revents & POLLIN)
399      * condition |= ENET_SOCKET_WAIT_RECEIVE;
400
401    return 0;
402#else
403    fd_set readSet, writeSet;
404    struct timeval timeVal;
405    int selectCount;
406
407    timeVal.tv_sec = timeout / 1000;
408    timeVal.tv_usec = (timeout % 1000) * 1000;
409
410    FD_ZERO (& readSet);
411    FD_ZERO (& writeSet);
412
413    if (* condition & ENET_SOCKET_WAIT_SEND)
414      FD_SET (socket, & writeSet);
415
416    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
417      FD_SET (socket, & readSet);
418
419    selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
420
421    if (selectCount < 0)
422      return -1;
423
424    * condition = ENET_SOCKET_WAIT_NONE;
425
426    if (selectCount == 0)
427      return 0;
428
429    if (FD_ISSET (socket, & writeSet))
430      * condition |= ENET_SOCKET_WAIT_SEND;
431
432    if (FD_ISSET (socket, & readSet))
433      * condition |= ENET_SOCKET_WAIT_RECEIVE;
434
435    return 0;
436#endif
437}
438
439#endif
440
Note: See TracBrowser for help on using the repository browser.