Subversion Repositories eduke32

Rev

Rev 4388 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1552 terminx 1
/**
2
 @file  unix.c
3
 @brief ENet Unix system specific functions
4
*/
3839 hendricks2 5
#ifndef _WIN32
1552 terminx 6
 
4388 terminx 7
#include <sys/types.h>
8
#include <sys/socket.h>
9
#include <sys/ioctl.h>
1552 terminx 10
#include <sys/time.h>
4388 terminx 11
#include <arpa/inet.h>
12
#include <netinet/tcp.h>
13
#include <netdb.h>
1552 terminx 14
#include <unistd.h>
15
#include <string.h>
16
#include <errno.h>
17
#include <time.h>
18
 
19
#define ENET_BUILDING_LIB 1
20
#include "enet/enet.h"
21
 
3036 terminx 22
#ifdef __APPLE__
23
#ifdef HAS_POLL
24
#undef HAS_POLL
25
#endif
26
#ifndef HAS_FCNTL
27
#define HAS_FCNTL 1
28
#endif
29
#ifndef HAS_INET_PTON
30
#define HAS_INET_PTON 1
31
#endif
32
#ifndef HAS_INET_NTOP
33
#define HAS_INET_NTOP 1
34
#endif
35
#ifndef HAS_MSGHDR_FLAGS
36
#define HAS_MSGHDR_FLAGS 1
37
#endif
38
#ifndef HAS_SOCKLEN_T
39
#define HAS_SOCKLEN_T 1
40
#endif
41
#endif
42
 
1552 terminx 43
#ifdef HAS_FCNTL
44
#include <fcntl.h>
45
#endif
46
 
47
#ifdef HAS_POLL
48
#include <sys/poll.h>
49
#endif
50
 
3036 terminx 51
#ifndef HAS_SOCKLEN_T
52
typedef int socklen_t;
53
#endif
54
 
1552 terminx 55
#ifndef MSG_NOSIGNAL
56
#define MSG_NOSIGNAL 0
57
#endif
58
 
59
static enet_uint32 timeBase = 0;
60
 
61
int
62
enet_initialize (void)
63
{
64
    return 0;
65
}
66
 
67
void
68
enet_deinitialize (void)
69
{
70
}
71
 
4646 hendricks2 72
// Why, Xcode? Why?
73
time_t time(time_t *);
74
 
1552 terminx 75
enet_uint32
4388 terminx 76
enet_host_random_seed (void)
77
{
78
    return (enet_uint32) time (NULL);
79
}
80
 
81
enet_uint32
1552 terminx 82
enet_time_get (void)
83
{
84
    struct timeval timeVal;
85
 
86
    gettimeofday (& timeVal, NULL);
87
 
88
    return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
89
}
90
 
91
void
92
enet_time_set (enet_uint32 newTimeBase)
93
{
94
    struct timeval timeVal;
95
 
96
    gettimeofday (& timeVal, NULL);
97
 
98
    timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
99
}
100
 
101
int
102
enet_address_set_host (ENetAddress * address, const char * name)
103
{
104
    struct hostent * hostEntry = NULL;
105
#ifdef HAS_GETHOSTBYNAME_R
106
    struct hostent hostData;
107
    char buffer [2048];
108
    int errnum;
109
 
1587 terminx 110
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1552 terminx 111
    gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
112
#else
113
    hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
114
#endif
115
#else
116
    hostEntry = gethostbyname (name);
117
#endif
118
 
119
    if (hostEntry == NULL ||
120
        hostEntry -> h_addrtype != AF_INET)
121
    {
122
#ifdef HAS_INET_PTON
123
        if (! inet_pton (AF_INET, name, & address -> host))
124
#else
125
        if (! inet_aton (name, (struct in_addr *) & address -> host))
126
#endif
127
            return -1;
128
        return 0;
129
    }
130
 
131
    address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
132
 
133
    return 0;
134
}
135
 
136
int
137
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
138
{
139
#ifdef HAS_INET_NTOP
140
    if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
141
#else
142
    char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
143
    if (addr != NULL)
4388 terminx 144
    {
145
        size_t addrLen = strlen(addr);
146
        if (addrLen >= nameLength)
147
          return -1;
148
        memcpy (name, addr, addrLen + 1);
149
    }
1552 terminx 150
    else
151
#endif
152
        return -1;
153
    return 0;
154
}
155
 
156
int
157
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
158
{
4388 terminx 159
    struct in_addr in;
3496 hendricks2 160
    struct hostent * hostEntry = NULL;
1552 terminx 161
#ifdef HAS_GETHOSTBYADDR_R
162
    struct hostent hostData;
163
    char buffer [2048];
164
    int errnum;
165
 
166
    in.s_addr = address -> host;
167
 
1587 terminx 168
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1552 terminx 169
    gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
170
#else
171
    hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
172
#endif
173
#else
174
    in.s_addr = address -> host;
175
 
176
    hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
177
#endif
178
 
179
    if (hostEntry == NULL)
180
      return enet_address_get_host_ip (address, name, nameLength);
4388 terminx 181
    else
182
    {
183
       size_t hostLen = strlen (hostEntry -> h_name);
184
       if (hostLen >= nameLength)
185
         return -1;
186
       memcpy (name, hostEntry -> h_name, hostLen + 1);
187
    }
1552 terminx 188
 
189
    return 0;
190
}
191
 
192
int
193
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
194
{
195
    struct sockaddr_in sin;
196
 
197
    memset (& sin, 0, sizeof (struct sockaddr_in));
198
 
199
    sin.sin_family = AF_INET;
200
 
201
    if (address != NULL)
202
    {
203
       sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
204
       sin.sin_addr.s_addr = address -> host;
205
    }
206
    else
207
    {
208
       sin.sin_port = 0;
209
       sin.sin_addr.s_addr = INADDR_ANY;
210
    }
211
 
212
    return bind (socket,
213
                 (struct sockaddr *) & sin,
214
                 sizeof (struct sockaddr_in));
215
}
216
 
4388 terminx 217
int
218
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
219
{
220
    struct sockaddr_in sin;
221
    socklen_t sinLength = sizeof (struct sockaddr_in);
222
 
223
    if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
224
      return -1;
225
 
226
    address -> host = (enet_uint32) sin.sin_addr.s_addr;
227
    address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
228
 
229
    return 0;
230
}
231
 
1552 terminx 232
int
233
enet_socket_listen (ENetSocket socket, int backlog)
234
{
235
    return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
236
}
237
 
238
ENetSocket
239
enet_socket_create (ENetSocketType type)
240
{
241
    return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
242
}
243
 
244
int
245
enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
246
{
247
    int result = -1;
248
    switch (option)
249
    {
250
        case ENET_SOCKOPT_NONBLOCK:
251
#ifdef HAS_FCNTL
252
            result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL));
253
#else
254
            result = ioctl (socket, FIONBIO, & value);
255
#endif
256
            break;
257
 
258
        case ENET_SOCKOPT_BROADCAST:
259
            result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
260
            break;
261
 
262
        case ENET_SOCKOPT_REUSEADDR:
263
            result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
264
            break;
265
 
266
        case ENET_SOCKOPT_RCVBUF:
267
            result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
268
            break;
269
 
270
        case ENET_SOCKOPT_SNDBUF:
271
            result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
272
            break;
273
 
2663 terminx 274
        case ENET_SOCKOPT_RCVTIMEO:
4388 terminx 275
        {
276
            struct timeval timeVal;
277
            timeVal.tv_sec = value / 1000;
278
            timeVal.tv_usec = (value % 1000) * 1000;
279
            result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval));
2663 terminx 280
            break;
4388 terminx 281
        }
2663 terminx 282
 
283
        case ENET_SOCKOPT_SNDTIMEO:
4388 terminx 284
        {
285
            struct timeval timeVal;
286
            timeVal.tv_sec = value / 1000;
287
            timeVal.tv_usec = (value % 1000) * 1000;
288
            result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval));
2663 terminx 289
            break;
4388 terminx 290
        }
2663 terminx 291
 
4388 terminx 292
        case ENET_SOCKOPT_NODELAY:
293
            result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
294
            break;
295
 
1552 terminx 296
        default:
297
            break;
298
    }
299
    return result == -1 ? -1 : 0;
300
}
301
 
302
int
4388 terminx 303
enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
304
{
305
    int result = -1;
306
    socklen_t len;
307
    switch (option)
308
    {
309
        case ENET_SOCKOPT_ERROR:
310
            len = sizeof (int);
311
            result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len);
312
            break;
313
 
314
        default:
315
            break;
316
    }
317
    return result == -1 ? -1 : 0;
318
}
319
 
320
int
1552 terminx 321
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
322
{
323
    struct sockaddr_in sin;
3036 terminx 324
    int result;
1552 terminx 325
 
326
    memset (& sin, 0, sizeof (struct sockaddr_in));
327
 
328
    sin.sin_family = AF_INET;
329
    sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
330
    sin.sin_addr.s_addr = address -> host;
331
 
3036 terminx 332
    result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
333
    if (result == -1 && errno == EINPROGRESS)
334
      return 0;
335
 
336
    return result;
1552 terminx 337
}
338
 
339
ENetSocket
340
enet_socket_accept (ENetSocket socket, ENetAddress * address)
341
{
342
    int result;
343
    struct sockaddr_in sin;
344
    socklen_t sinLength = sizeof (struct sockaddr_in);
345
 
346
    result = accept (socket,
347
                     address != NULL ? (struct sockaddr *) & sin : NULL,
348
                     address != NULL ? & sinLength : NULL);
349
 
350
    if (result == -1)
351
      return ENET_SOCKET_NULL;
352
 
353
    if (address != NULL)
354
    {
355
        address -> host = (enet_uint32) sin.sin_addr.s_addr;
356
        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
357
    }
358
 
359
    return result;
360
}
361
 
3036 terminx 362
int
363
enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
364
{
365
    return shutdown (socket, (int) how);
366
}
367
 
1552 terminx 368
void
369
enet_socket_destroy (ENetSocket socket)
370
{
3036 terminx 371
    if (socket != -1)
4388 terminx 372
      close (socket);
1552 terminx 373
}
374
 
375
int
376
enet_socket_send (ENetSocket socket,
377
                  const ENetAddress * address,
378
                  const ENetBuffer * buffers,
379
                  size_t bufferCount)
380
{
381
    struct msghdr msgHdr;
382
    struct sockaddr_in sin;
4388 terminx 383
    int sentLength;
1552 terminx 384
 
385
    memset (& msgHdr, 0, sizeof (struct msghdr));
386
 
387
    if (address != NULL)
388
    {
389
        memset (& sin, 0, sizeof (struct sockaddr_in));
390
 
391
        sin.sin_family = AF_INET;
392
        sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
393
        sin.sin_addr.s_addr = address -> host;
394
 
395
        msgHdr.msg_name = & sin;
396
        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
397
    }
398
 
399
    msgHdr.msg_iov = (struct iovec *) buffers;
400
    msgHdr.msg_iovlen = bufferCount;
401
 
402
    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
403
 
404
    if (sentLength == -1)
405
    {
406
       if (errno == EWOULDBLOCK)
407
         return 0;
408
 
409
       return -1;
410
    }
411
 
412
    return sentLength;
413
}
414
 
415
int
416
enet_socket_receive (ENetSocket socket,
417
                     ENetAddress * address,
418
                     ENetBuffer * buffers,
419
                     size_t bufferCount)
420
{
421
    struct msghdr msgHdr;
422
    struct sockaddr_in sin;
4388 terminx 423
    int recvLength;
1552 terminx 424
 
425
    memset (& msgHdr, 0, sizeof (struct msghdr));
426
 
427
    if (address != NULL)
428
    {
429
        msgHdr.msg_name = & sin;
430
        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
431
    }
432
 
433
    msgHdr.msg_iov = (struct iovec *) buffers;
434
    msgHdr.msg_iovlen = bufferCount;
435
 
436
    recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
437
 
438
    if (recvLength == -1)
439
    {
440
       if (errno == EWOULDBLOCK)
441
         return 0;
442
 
443
       return -1;
444
    }
445
 
446
#ifdef HAS_MSGHDR_FLAGS
447
    if (msgHdr.msg_flags & MSG_TRUNC)
448
      return -1;
449
#endif
450
 
451
    if (address != NULL)
452
    {
453
        address -> host = (enet_uint32) sin.sin_addr.s_addr;
454
        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
455
    }
456
 
457
    return recvLength;
458
}
459
 
460
int
461
enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
462
{
463
    struct timeval timeVal;
464
 
465
    timeVal.tv_sec = timeout / 1000;
466
    timeVal.tv_usec = (timeout % 1000) * 1000;
467
 
468
    return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
469
}
470
 
471
int
472
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
473
{
474
#ifdef HAS_POLL
475
    struct pollfd pollSocket;
476
    int pollCount;
477
 
478
    pollSocket.fd = socket;
479
    pollSocket.events = 0;
480
 
481
    if (* condition & ENET_SOCKET_WAIT_SEND)
482
      pollSocket.events |= POLLOUT;
483
 
484
    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
485
      pollSocket.events |= POLLIN;
486
 
487
    pollCount = poll (& pollSocket, 1, timeout);
488
 
489
    if (pollCount < 0)
4388 terminx 490
    {
491
        if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
492
        {
493
            * condition = ENET_SOCKET_WAIT_INTERRUPT;
1552 terminx 494
 
4388 terminx 495
            return 0;
496
        }
497
 
498
        return -1;
499
    }
500
 
1552 terminx 501
    * condition = ENET_SOCKET_WAIT_NONE;
502
 
503
    if (pollCount == 0)
504
      return 0;
505
 
506
    if (pollSocket.revents & POLLOUT)
507
      * condition |= ENET_SOCKET_WAIT_SEND;
508
 
509
    if (pollSocket.revents & POLLIN)
510
      * condition |= ENET_SOCKET_WAIT_RECEIVE;
511
 
512
    return 0;
513
#else
514
    fd_set readSet, writeSet;
515
    struct timeval timeVal;
516
    int selectCount;
517
 
518
    timeVal.tv_sec = timeout / 1000;
519
    timeVal.tv_usec = (timeout % 1000) * 1000;
520
 
521
    FD_ZERO (& readSet);
522
    FD_ZERO (& writeSet);
523
 
524
    if (* condition & ENET_SOCKET_WAIT_SEND)
525
      FD_SET (socket, & writeSet);
526
 
527
    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
528
      FD_SET (socket, & readSet);
529
 
530
    selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
531
 
532
    if (selectCount < 0)
4388 terminx 533
    {
534
        if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
535
        {
536
            * condition = ENET_SOCKET_WAIT_INTERRUPT;
1552 terminx 537
 
4388 terminx 538
            return 0;
539
        }
540
 
541
        return -1;
542
    }
543
 
1552 terminx 544
    * condition = ENET_SOCKET_WAIT_NONE;
545
 
546
    if (selectCount == 0)
547
      return 0;
548
 
549
    if (FD_ISSET (socket, & writeSet))
550
      * condition |= ENET_SOCKET_WAIT_SEND;
551
 
552
    if (FD_ISSET (socket, & readSet))
553
      * condition |= ENET_SOCKET_WAIT_RECEIVE;
554
 
555
    return 0;
556
#endif
557
}
558
 
559
#endif
560