Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/enet-1.1/unix.c @ 29

Last change on this file since 29 was 13, checked in by landauf, 17 years ago

added enet

File size: 9.0 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(__FreeBSD__)
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(__FreeBSD__)
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
155ENetSocket
156enet_socket_create (ENetSocketType type, const ENetAddress * address)
157{
158    ENetSocket newSocket = socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
159    int receiveBufferSize = ENET_HOST_RECEIVE_BUFFER_SIZE,
160        sendBufferSize = ENET_HOST_SEND_BUFFER_SIZE,
161        allowBroadcasting = 1;
162#ifndef HAS_FCNTL
163    int nonBlocking = 1;
164#endif
165    struct sockaddr_in sin;
166
167    if (newSocket == ENET_SOCKET_NULL)
168      return ENET_SOCKET_NULL;
169
170    if (type == ENET_SOCKET_TYPE_DATAGRAM)
171    {
172#ifdef HAS_FCNTL
173        fcntl (newSocket, F_SETFL, O_NONBLOCK | fcntl (newSocket, F_GETFL));
174#else
175        ioctl (newSocket, FIONBIO, & nonBlocking);
176#endif
177
178        setsockopt (newSocket, SOL_SOCKET, SO_RCVBUF, (char *) & receiveBufferSize, sizeof (int));
179        setsockopt (newSocket, SOL_SOCKET, SO_SNDBUF, (char *) & sendBufferSize, sizeof (int));
180        setsockopt (newSocket, SOL_SOCKET, SO_BROADCAST, (char *) & allowBroadcasting, sizeof (int));
181    }
182   
183    if (address == NULL)
184      return newSocket;
185
186    memset (& sin, 0, sizeof (struct sockaddr_in));
187
188    sin.sin_family = AF_INET;
189    sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
190    sin.sin_addr.s_addr = address -> host;
191
192    if (bind (newSocket, 
193              (struct sockaddr *) & sin,
194              sizeof (struct sockaddr_in)) == -1 ||
195        (type == ENET_SOCKET_TYPE_STREAM &&
196          address -> port != ENET_PORT_ANY &&
197          listen (newSocket, SOMAXCONN) == -1))
198    {
199       close (newSocket);
200
201       return ENET_SOCKET_NULL;
202    }
203
204    return newSocket;
205}
206
207int
208enet_socket_connect (ENetSocket socket, const ENetAddress * address)
209{
210    struct sockaddr_in sin;
211
212    memset (& sin, 0, sizeof (struct sockaddr_in));
213
214    sin.sin_family = AF_INET;
215    sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
216    sin.sin_addr.s_addr = address -> host;
217
218    return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
219}
220
221ENetSocket
222enet_socket_accept (ENetSocket socket, ENetAddress * address)
223{
224    int result;
225    struct sockaddr_in sin;
226    socklen_t sinLength = sizeof (struct sockaddr_in);
227
228    result = accept (socket, 
229                     address != NULL ? (struct sockaddr *) & sin : NULL, 
230                     address != NULL ? & sinLength : NULL);
231   
232    if (result == -1)
233      return ENET_SOCKET_NULL;
234
235    if (address != NULL)
236    {
237        address -> host = (enet_uint32) sin.sin_addr.s_addr;
238        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
239    }
240
241    return result;
242} 
243   
244void
245enet_socket_destroy (ENetSocket socket)
246{
247    close (socket);
248}
249
250int
251enet_socket_send (ENetSocket socket,
252                  const ENetAddress * address,
253                  const ENetBuffer * buffers,
254                  size_t bufferCount)
255{
256    struct msghdr msgHdr;
257    struct sockaddr_in sin;
258    int sentLength;
259
260    memset (& msgHdr, 0, sizeof (struct msghdr));
261
262    if (address != NULL)
263    {
264        sin.sin_family = AF_INET;
265        sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
266        sin.sin_addr.s_addr = address -> host;
267
268        msgHdr.msg_name = & sin;
269        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
270    }
271
272    msgHdr.msg_iov = (struct iovec *) buffers;
273    msgHdr.msg_iovlen = bufferCount;
274
275    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
276   
277    if (sentLength == -1)
278    {
279       if (errno == EWOULDBLOCK)
280         return 0;
281
282       return -1;
283    }
284
285    return sentLength;
286}
287
288int
289enet_socket_receive (ENetSocket socket,
290                     ENetAddress * address,
291                     ENetBuffer * buffers,
292                     size_t bufferCount)
293{
294    struct msghdr msgHdr;
295    struct sockaddr_in sin;
296    int recvLength;
297
298    memset (& msgHdr, 0, sizeof (struct msghdr));
299
300    if (address != NULL)
301    {
302        msgHdr.msg_name = & sin;
303        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
304    }
305
306    msgHdr.msg_iov = (struct iovec *) buffers;
307    msgHdr.msg_iovlen = bufferCount;
308
309    recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
310
311    if (recvLength == -1)
312    {
313       if (errno == EWOULDBLOCK)
314         return 0;
315
316       return -1;
317    }
318
319#ifdef HAS_MSGHDR_FLAGS
320    if (msgHdr.msg_flags & MSG_TRUNC)
321      return -1;
322#endif
323
324    if (address != NULL)
325    {
326        address -> host = (enet_uint32) sin.sin_addr.s_addr;
327        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
328    }
329
330    return recvLength;
331}
332
333int
334enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
335{
336#ifdef HAS_POLL
337    struct pollfd pollSocket;
338    int pollCount;
339   
340    pollSocket.fd = socket;
341    pollSocket.events = 0;
342
343    if (* condition & ENET_SOCKET_WAIT_SEND)
344      pollSocket.events |= POLLOUT;
345
346    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
347      pollSocket.events |= POLLIN;
348
349    pollCount = poll (& pollSocket, 1, timeout);
350
351    if (pollCount < 0)
352      return -1;
353
354    * condition = ENET_SOCKET_WAIT_NONE;
355
356    if (pollCount == 0)
357      return 0;
358
359    if (pollSocket.revents & POLLOUT)
360      * condition |= ENET_SOCKET_WAIT_SEND;
361   
362    if (pollSocket.revents & POLLIN)
363      * condition |= ENET_SOCKET_WAIT_RECEIVE;
364
365    return 0;
366#else
367    fd_set readSet, writeSet;
368    struct timeval timeVal;
369    int selectCount;
370
371    timeVal.tv_sec = timeout / 1000;
372    timeVal.tv_usec = (timeout % 1000) * 1000;
373
374    FD_ZERO (& readSet);
375    FD_ZERO (& writeSet);
376
377    if (* condition & ENET_SOCKET_WAIT_SEND)
378      FD_SET (socket, & writeSet);
379
380    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
381      FD_SET (socket, & readSet);
382
383    selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
384
385    if (selectCount < 0)
386      return -1;
387
388    * condition = ENET_SOCKET_WAIT_NONE;
389
390    if (selectCount == 0)
391      return 0;
392
393    if (FD_ISSET (socket, & writeSet))
394      * condition |= ENET_SOCKET_WAIT_SEND;
395
396    if (FD_ISSET (socket, & readSet))
397      * condition |= ENET_SOCKET_WAIT_RECEIVE;
398
399    return 0;
400#endif
401}
402
403#endif
404
Note: See TracBrowser for help on using the repository browser.