source: osgVisual/src/cluster/enet/unix.c @ 92

Last change on this file since 92 was 65, checked in by Torben Dannhauer, 14 years ago

new cluster implementation added: ENet
ENet is a reliable UDP implementation with quite simple usage and high performance for transmission with small or medium size packet.

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