OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libnetworking/] [rtems_webserver/] [socket.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
 
2
/*
3
 *      sockGen.c -- Posix Socket support module for general posix use
4
 *
5
 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
6
 */
7
 
8
/******************************** Description *********************************/
9
 
10
/*
11
 *      Posix Socket Module.  This supports blocking and non-blocking buffered
12
 *      socket I/O.
13
 */
14
 
15
#if (!WIN) || LITTLEFOOT || WEBS
16
 
17
/********************************** Includes **********************************/
18
 
19
#include        <string.h>
20
#include        <stdlib.h>
21
 
22
#if UEMF
23
        #include        "uemf.h"
24
#else
25
        #include        <socket.h>
26
        #include        <types.h>
27
        #include        <unistd.h>
28
        #include        "emfInternal.h"
29
#endif
30
 
31
#if VXWORKS
32
        #include        <hostLib.h>
33
#endif
34
 
35
#if __rtems__
36
        #include        <sys/select.h>
37
#endif
38
 
39
/************************************ Locals **********************************/
40
 
41
extern socket_t         **socketList;                   /* List of open sockets */
42
extern int                      socketMax;                              /* Maximum size of socket */
43
extern int                      socketHighestFd;                /* Highest socket fd opened */
44
static int                      socketOpenCount = 0;     /* Number of task using sockets */
45
 
46
/***************************** Forward Declarations ***************************/
47
 
48
static void socketAccept(socket_t *sp);
49
static int      socketDoEvent(socket_t *sp);
50
static int      tryAlternateConnect(int sock, struct sockaddr *sockaddr);
51
 
52
/*********************************** Code *************************************/
53
/*
54
 *      Open socket module
55
 */
56
 
57
int socketOpen()
58
{
59
#if CE || WIN
60
    WSADATA     wsaData;
61
#endif
62
 
63
        if (++socketOpenCount > 1) {
64
                return 0;
65
        }
66
 
67
#if CE || WIN
68
        if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
69
                return -1;
70
        }
71
        if (wsaData.wVersion != MAKEWORD(1,1)) {
72
                WSACleanup();
73
                return -1;
74
        }
75
#endif
76
        socketList = NULL;
77
        socketMax = 0;
78
        socketHighestFd = -1;
79
 
80
        return 0;
81
}
82
 
83
/******************************************************************************/
84
/*
85
 *      Close the socket module, by closing all open connections
86
 */
87
 
88
void socketClose()
89
{
90
        int             i;
91
 
92
        if (--socketOpenCount <= 0) {
93
                for (i = socketMax; i >= 0; i--) {
94
                        if (socketList && socketList[i]) {
95
                                socketCloseConnection(i);
96
                        }
97
                }
98
                socketOpenCount = 0;
99
        }
100
}
101
 
102
/******************************************************************************/
103
/*
104
 *      Open a client or server socket. Host is NULL if we want server capability.
105
 */
106
 
107
int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags)
108
{
109
#if ! (NO_GETHOSTBYNAME || VXWORKS)
110
        struct hostent          *hostent;                                       /* Host database entry */
111
#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */
112
        socket_t                        *sp;
113
        struct sockaddr_in      sockaddr;
114
        int                                     sid, bcast, dgram, rc;
115
 
116
        if (port > SOCKET_PORT_MAX) {
117
                return -1;
118
        }
119
/*
120
 *      Allocate a socket structure
121
 */
122
        if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
123
                return -1;
124
        }
125
        sp = socketList[sid];
126
        a_assert(sp);
127
 
128
/*
129
 *      Create the socket address structure
130
 */
131
        memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
132
        sockaddr.sin_family = AF_INET;
133
        sockaddr.sin_port = htons((short) (port & 0xFFFF));
134
 
135
        if (host == NULL) {
136
                sockaddr.sin_addr.s_addr = INADDR_ANY;
137
        } else {
138
                sockaddr.sin_addr.s_addr = inet_addr(host);
139
                if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
140
/*
141
 *                      If the OS does not support gethostbyname functionality, the macro:
142
 *                      NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname.
143
 *                      Unfortunatly there is no easy way to recover, the following code
144
 *                      simply uses the basicGetHost IP for the sockaddr.
145
 */
146
 
147
#if NO_GETHOSTBYNAME
148
                        if (strcmp(host, basicGetHost()) == 0) {
149
                                sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress());
150
                        }
151
                        if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
152
                                socketFree(sid);
153
                                return -1;
154
                        }
155
#elif VXWORKS
156
                        sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host);
157
                        if (sockaddr.sin_addr.s_addr == NULL) {
158
                                errno = ENXIO;
159
                                socketFree(sid);
160
                                return -1;
161
                        }
162
#else
163
                        hostent = gethostbyname(host);
164
                        if (hostent != NULL) {
165
                                memcpy((char *) &sockaddr.sin_addr,
166
                                        (char *) hostent->h_addr_list[0],
167
                                        (size_t) hostent->h_length);
168
                        } else {
169
                                char    *asciiAddress;
170
                                char_t  *address;
171
 
172
                                address = basicGetAddress();
173
                                asciiAddress = ballocUniToAsc(address, gstrlen(address));
174
                                sockaddr.sin_addr.s_addr = inet_addr(asciiAddress);
175
                                bfree(B_L, asciiAddress);
176
                                if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
177
                                        errno = ENXIO;
178
                                        socketFree(sid);
179
                                        return -1;
180
                                }
181
                        }
182
#endif /* (NO_GETHOSTBYNAME || VXWORKS) */
183
                }
184
        }
185
 
186
        bcast = sp->flags & SOCKET_BROADCAST;
187
        if (bcast) {
188
                sp->flags |= SOCKET_DATAGRAM;
189
        }
190
        dgram = sp->flags & SOCKET_DATAGRAM;
191
 
192
/*
193
 *      Create the socket. Support for datagram sockets. Set the close on
194
 *      exec flag so children don't inherit the socket.
195
 */
196
        sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0);
197
        if (sp->sock < 0) {
198
                socketFree(sid);
199
                return -1;
200
        }
201
#ifndef __NO_FCNTL
202
        fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
203
#endif
204
        socketHighestFd = max(socketHighestFd, sp->sock);
205
 
206
/*
207
 *      If broadcast, we need to turn on broadcast capability.
208
 */
209
        if (bcast) {
210
                int broadcastFlag = 1;
211
                if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST,
212
                                (char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) {
213
                        socketFree(sid);
214
                        return -1;
215
                }
216
        }
217
 
218
/*
219
 *      Host is set if we are the client
220
 */
221
        if (host) {
222
/*
223
 *              Connect to the remote server in blocking mode, then go into
224
 *              non-blocking mode if desired.
225
 */
226
                if (!dgram) {
227
                        if (! (sp->flags & SOCKET_BLOCK)) {
228
/*
229
 *                              sockGen.c is only used for Windows products when blocking
230
 *                              connects are expected.  This applies to FieldUpgrader
231
 *                              agents and open source webserver connectws.  Therefore the
232
 *                              asynchronous connect code here is not compiled.
233
 */
234
#if (WIN || CE) && !(LITTLEFOOT || WEBS)
235
                                int flag;
236
 
237
                                sp->flags |= SOCKET_ASYNC;
238
/*
239
 *                              Set to non-blocking for an async connect
240
 */
241
                                flag = 1;
242
                                if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
243
                                        socketFree(sid);
244
                                        return -1;
245
                                }
246
#else
247
                                socketSetBlock(sid, 1);
248
#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */
249
 
250
                        }
251
                        if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr,
252
                                sizeof(sockaddr))) < 0 &&
253
                                (rc = tryAlternateConnect(sp->sock,
254
                                (struct sockaddr *) &sockaddr)) < 0) {
255
#if WIN || CE
256
                                if (socketGetError() != EWOULDBLOCK) {
257
                                        socketFree(sid);
258
                                        return -1;
259
                                }
260
#else
261
                                socketFree(sid);
262
                                return -1;
263
 
264
#endif /* WIN || CE */
265
 
266
                        }
267
                }
268
        } else {
269
/*
270
 *              Bind to the socket endpoint and the call listen() to start listening
271
 */
272
                rc = 1;
273
                setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
274
                if (bind(sp->sock, (struct sockaddr *) &sockaddr,
275
                                sizeof(sockaddr)) < 0) {
276
                        socketFree(sid);
277
                        return -1;
278
                }
279
 
280
                if (! dgram) {
281
                        if (listen(sp->sock, SOMAXCONN) < 0) {
282
                                socketFree(sid);
283
                                return -1;
284
                        }
285
#if !UEMF
286
                        sp->fileHandle = emfCreateFileHandler(sp->sock, SOCKET_READABLE,
287
                                (emfFileProc *) socketAccept, (void *) sp);
288
#else
289
                        sp->flags |= SOCKET_LISTENING;
290
#endif
291
                }
292
                sp->handlerMask |= SOCKET_READABLE;
293
        }
294
 
295
/*
296
 *      Set the blocking mode
297
 */
298
 
299
        if (flags & SOCKET_BLOCK) {
300
                socketSetBlock(sid, 1);
301
        } else {
302
                socketSetBlock(sid, 0);
303
        }
304
        return sid;
305
}
306
 
307
/******************************************************************************/
308
/*
309
 *      If the connection failed, swap the first two bytes in the
310
 *      sockaddr structure.  This is a kludge due to a change in
311
 *      VxWorks between versions 5.3 and 5.4, but we want the
312
 *      product to run on either.
313
 */
314
 
315
static int tryAlternateConnect(int sock, struct sockaddr *sockaddr)
316
{
317
#if VXWORKS
318
        char *ptr;
319
 
320
        ptr = (char *)sockaddr;
321
        *ptr = *(ptr+1);
322
        *(ptr+1) = 0;
323
        return connect(sock, sockaddr, sizeof(struct sockaddr));
324
#else
325
        return -1;
326
#endif /* VXWORKS */
327
}
328
 
329
/******************************************************************************/
330
/*
331
 *      Close a socket
332
 */
333
 
334
void socketCloseConnection(int sid)
335
{
336
        socket_t        *sp;
337
 
338
        if ((sp = socketPtr(sid)) == NULL) {
339
                return;
340
        }
341
        socketFree(sid);
342
}
343
 
344
/******************************************************************************/
345
/*
346
 *      Accept a connection. Called as a callback on incoming connection.
347
 */
348
 
349
static void socketAccept(socket_t *sp)
350
{
351
        struct sockaddr_in      addr;
352
        socket_t                        *nsp;
353
        size_t                          len;
354
        char                            *pString;
355
        int                             newSock, nid;
356
 
357
        a_assert(sp);
358
 
359
/*
360
 *      Accept the connection and prevent inheriting by children (F_SETFD)
361
 */
362
        len = sizeof(struct sockaddr_in);
363
        if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, &len)) < 0) {
364
                return;
365
        }
366
#ifndef __NO_FCNTL
367
        fcntl(newSock, F_SETFD, FD_CLOEXEC);
368
#endif
369
        socketHighestFd = max(socketHighestFd, newSock);
370
 
371
/*
372
 *      Create a socket structure and insert into the socket list
373
 */
374
        nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags);
375
        nsp = socketList[nid];
376
        a_assert(nsp);
377
        nsp->sock = newSock;
378
        nsp->flags &= ~SOCKET_LISTENING;
379
 
380
        if (nsp == NULL) {
381
                return;
382
        }
383
/*
384
 *      Set the blocking mode before calling the accept callback.
385
 */
386
 
387
        socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK) ? 1: 0);
388
/*
389
 *      Call the user accept callback. The user must call socketCreateHandler
390
 *      to register for further events of interest.
391
 */
392
        if (sp->accept != NULL) {
393
                pString = inet_ntoa(addr.sin_addr);
394
                if ((sp->accept)(nid, pString, ntohs(addr.sin_port), sp->sid) < 0) {
395
                        socketFree(nid);
396
                }
397
#if VXWORKS
398
                free(pString);
399
#endif
400
        }
401
}
402
 
403
/******************************************************************************/
404
/*
405
 *      Get more input from the socket and return in buf.
406
 *      Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
407
 */
408
 
409
int socketGetInput(int sid, char *buf, int toRead, int *errCode)
410
{
411
        struct sockaddr_in      server;
412
        socket_t                        *sp;
413
        int                             len, bytesRead;
414
 
415
        a_assert(buf);
416
        a_assert(errCode);
417
 
418
        *errCode = 0;
419
 
420
        if ((sp = socketPtr(sid)) == NULL) {
421
                return -1;
422
        }
423
 
424
/*
425
 *      If we have previously seen an EOF condition, then just return
426
 */
427
        if (sp->flags & SOCKET_EOF) {
428
                return 0;
429
        }
430
#if (WIN || CE) && !(LITTLEFOOT || WEBS)
431
        if ( !(sp->flags & SOCKET_BLOCK)
432
                        && ! socketWaitForEvent(sp,  FD_CONNECT, errCode)) {
433
                return -1;
434
        }
435
#endif
436
 
437
/*
438
 *      Read the data
439
 */
440
        if (sp->flags & SOCKET_DATAGRAM) {
441
                len = sizeof(server);
442
                bytesRead = recvfrom(sp->sock, buf, toRead, 0,
443
                        (struct sockaddr *) &server, &len);
444
        } else {
445
                bytesRead = recv(sp->sock, buf, toRead, 0);
446
        }
447
        if (bytesRead < 0) {
448
                if (errno == ECONNRESET) {
449
                        return 0;
450
                }
451
                *errCode = socketGetError();
452
                return -1;
453
        }
454
        return bytesRead;
455
}
456
 
457
/******************************************************************************/
458
/*
459
 *      Process an event on the event queue
460
 */
461
 
462
#ifndef UEMF
463
 
464
static int socketEventProc(void *data, int mask)
465
{
466
        socket_t                *sp;
467
        ringq_t                 *rq;
468
        int                     sid;
469
 
470
        sid = (int) data;
471
 
472
        a_assert(sid >= 0 && sid < socketMax);
473
        a_assert(socketList[sid]);
474
 
475
        if ((sp = socketPtr(sid)) == NULL) {
476
                return 1;
477
        }
478
 
479
/*
480
 *      If now writable and flushing in the background, continue flushing
481
 */
482
        if (mask & SOCKET_WRITABLE) {
483
                if (sp->flags & SOCKET_FLUSHING) {
484
                        rq = &sp->outBuf;
485
                        if (ringqLen(rq) > 0) {
486
                                socketFlush(sp->sid);
487
                        } else {
488
                                sp->flags &= ~SOCKET_FLUSHING;
489
                        }
490
                }
491
        }
492
 
493
/*
494
 *      Now invoke the users socket handler. NOTE: the handler may delete the
495
 *      socket, so we must be very careful after calling the handler.
496
 */
497
        if (sp->handler && (sp->handlerMask & mask)) {
498
                (sp->handler)(sid, mask & sp->handlerMask, sp->handler_data);
499
        }
500
        if (socketList && sid < socketMax && socketList[sid] == sp) {
501
                socketRegisterInterest(sp, sp->handlerMask);
502
        }
503
        return 1;
504
}
505
#endif /* ! UEMF */
506
 
507
/******************************************************************************/
508
/*
509
 *      Define the events of interest
510
 */
511
 
512
void socketRegisterInterest(socket_t *sp, int handlerMask)
513
{
514
        a_assert(sp);
515
 
516
        sp->handlerMask = handlerMask;
517
#if !UEMF
518
        if (handlerMask) {
519
                sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask,
520
                        (emfFileProc *) socketEventProc, (void *) sp->sid);
521
        } else {
522
                emfDeleteFileHandler(sp->fileHandle);
523
        }
524
#endif /* ! UEMF */
525
}
526
 
527
/******************************************************************************/
528
/*
529
 *      Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
530
 *      or -1 on exception (UEMF only)
531
 */
532
 
533
int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode)
534
{
535
        int     mask;
536
 
537
        a_assert(sp);
538
 
539
        mask = sp->handlerMask;
540
        sp->handlerMask |= handlerMask;
541
        while (socketSelect(sp->sid, 1000)) {
542
                if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) {
543
                        break;
544
                }
545
        }
546
        sp->handlerMask = mask;
547
        if (sp->currentEvents & SOCKET_EXCEPTION) {
548
                return -1;
549
        } else if (sp->currentEvents & handlerMask) {
550
                return 1;
551
        }
552
        if (errCode) {
553
                *errCode = errno = EWOULDBLOCK;
554
        }
555
        return 0;
556
}
557
 
558
/******************************************************************************/
559
/*
560
 *      Return TRUE if there is a socket with an event ready to process,
561
 */
562
 
563
int socketReady(int sid)
564
{
565
        socket_t        *sp;
566
        int                     all;
567
 
568
        all = 0;
569
        if (sid < 0) {
570
                sid = 0;
571
                all = 1;
572
        }
573
 
574
        for (; sid < socketMax; sid++) {
575
                if ((sp = socketList[sid]) == NULL) {
576
                        if (! all) {
577
                                break;
578
                        } else {
579
                                continue;
580
                        }
581
                }
582
                if (sp->currentEvents & sp->handlerMask) {
583
                        return 1;
584
                }
585
/*
586
 *              If there is input data, also call select to test for new events
587
 */
588
                if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid)) {
589
                        socketSelect(sid, 0);
590
                        return 1;
591
                }
592
                if (! all) {
593
                        break;
594
                }
595
        }
596
        return 0;
597
}
598
 
599
/******************************************************************************/
600
/*
601
 *      Wait for a handle to become readable or writable and return a number of
602
 *      noticed events. Timeout is in milliseconds.
603
 */
604
 
605
#if WIN || CE
606
 
607
int socketSelect(int sid, int timeout)
608
{
609
        struct timeval  tv;
610
        socket_t                *sp;
611
        fd_set                  readFds, writeFds, exceptFds;
612
        int                     nEvents;
613
        int                             all, socketHighestFd;   /* Highest socket fd opened */
614
 
615
        FD_ZERO(&readFds);
616
        FD_ZERO(&writeFds);
617
        FD_ZERO(&exceptFds);
618
        socketHighestFd = -1;
619
 
620
        tv.tv_sec = timeout / 1000;
621
        tv.tv_usec = (timeout % 1000) * 1000;
622
 
623
/*
624
 *      Set the select event masks for events to watch
625
 */
626
        all = nEvents = 0;
627
 
628
        if (sid < 0) {
629
                all++;
630
                sid = 0;
631
        }
632
 
633
        for (; sid < socketMax; sid++) {
634
                if ((sp = socketList[sid]) == NULL) {
635
                        continue;
636
                }
637
                a_assert(sp);
638
/*
639
 *              Set the appropriate bit in the ready masks for the sp->sock.
640
 */
641
                if (sp->handlerMask & SOCKET_READABLE) {
642
                        FD_SET(sp->sock, &readFds);
643
                        nEvents++;
644
                        if (socketInputBuffered(sid) > 0) {
645
                                tv.tv_sec = 0;
646
                                tv.tv_usec = 0;
647
                        }
648
                }
649
                if (sp->handlerMask & SOCKET_WRITABLE) {
650
                        FD_SET(sp->sock, &writeFds);
651
                        nEvents++;
652
                }
653
                if (sp->handlerMask & SOCKET_EXCEPTION) {
654
                        FD_SET(sp->sock, &exceptFds);
655
                        nEvents++;
656
                }
657
                if (! all) {
658
                        break;
659
                }
660
        }
661
 
662
/*
663
 *      Windows select() fails if no descriptors are set, instead of just sleeping
664
 *      like other, nice select() calls. So, if WIN, sleep.
665
 */
666
        if (nEvents == 0) {
667
                Sleep(timeout);
668
                return 0;
669
        }
670
 
671
/*
672
 *      Wait for the event or a timeout.
673
 */
674
        nEvents = select(socketHighestFd+1, &readFds, &writeFds, &exceptFds, &tv);
675
 
676
        if (all) {
677
                sid = 0;
678
        }
679
        for (; sid < socketMax; sid++) {
680
                if ((sp = socketList[sid]) == NULL) {
681
                        continue;
682
                }
683
 
684
                if (FD_ISSET(sp->sock, &readFds) || socketInputBuffered(sid) > 0) {
685
                                sp->currentEvents |= SOCKET_READABLE;
686
                }
687
                if (FD_ISSET(sp->sock, &writeFds)) {
688
                                sp->currentEvents |= SOCKET_WRITABLE;
689
                }
690
                if (FD_ISSET(sp->sock, &exceptFds)) {
691
                                sp->currentEvents |= SOCKET_EXCEPTION;
692
                }
693
                if (! all) {
694
                        break;
695
                }
696
        }
697
 
698
        return nEvents;
699
}
700
 
701
#else /* not WIN || CE */
702
 
703
int socketSelect(int sid, int timeout)
704
{
705
        socket_t                *sp;
706
        struct timeval  tv;
707
        fd_mask                 *readFds, *writeFds, *exceptFds;
708
        int                     all, len, nwords, index, bit, nEvents;
709
 
710
/*
711
 *      Allocate and zero the select masks
712
 */
713
        nwords = (socketHighestFd + NFDBITS) / NFDBITS;
714
        len = nwords * sizeof(int);
715
 
716
        readFds = balloc(B_L, len);
717
        memset(readFds, 0, len);
718
        writeFds = balloc(B_L, len);
719
        memset(writeFds, 0, len);
720
        exceptFds = balloc(B_L, len);
721
        memset(exceptFds, 0, len);
722
 
723
        tv.tv_sec = timeout / 1000;
724
        tv.tv_usec = (timeout % 1000) * 1000;
725
 
726
/*
727
 *      Set the select event masks for events to watch
728
 */
729
        all = nEvents = 0;
730
 
731
        if (sid < 0) {
732
                all++;
733
                sid = 0;
734
        }
735
 
736
        for (; sid < socketMax; sid++) {
737
                if ((sp = socketList[sid]) == NULL) {
738
                        if (all == 0) {
739
                                break;
740
                        } else {
741
                                continue;
742
                        }
743
                }
744
                a_assert(sp);
745
 
746
/*
747
 *              Initialize the ready masks and compute the mask offsets.
748
 */
749
                index = sp->sock / (NBBY * sizeof(fd_mask));
750
                bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
751
 
752
/*
753
 *              Set the appropriate bit in the ready masks for the sp->sock.
754
 */
755
                if (sp->handlerMask & SOCKET_READABLE) {
756
                        readFds[index] |= bit;
757
                        nEvents++;
758
                        if (socketInputBuffered(sid) > 0) {
759
                                tv.tv_sec = 0;
760
                                tv.tv_usec = 0;
761
                        }
762
                }
763
                if (sp->handlerMask & SOCKET_WRITABLE) {
764
                        writeFds[index] |= bit;
765
                        nEvents++;
766
                }
767
                if (sp->handlerMask & SOCKET_EXCEPTION) {
768
                        exceptFds[index] |= bit;
769
                        nEvents++;
770
                }
771
                if (! all) {
772
                        break;
773
                }
774
        }
775
 
776
/*
777
 *      Wait for the event or a timeout. Reset nEvents to be the number of actual
778
 *      events now.
779
 */
780
        nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
781
                (fd_set *) writeFds, (fd_set *) exceptFds, &tv);
782
 
783
        if (nEvents > 0) {
784
                if (all) {
785
                        sid = 0;
786
                }
787
                for (; sid < socketMax; sid++) {
788
                        if ((sp = socketList[sid]) == NULL) {
789
                                if (all == 0) {
790
                                        break;
791
                                } else {
792
                                        continue;
793
                                }
794
                        }
795
 
796
                        index = sp->sock / (NBBY * sizeof(fd_mask));
797
                        bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
798
 
799
                        if (readFds[index] & bit || socketInputBuffered(sid) > 0) {
800
                                sp->currentEvents |= SOCKET_READABLE;
801
                        }
802
                        if (writeFds[index] & bit) {
803
                                sp->currentEvents |= SOCKET_WRITABLE;
804
                        }
805
                        if (exceptFds[index] & bit) {
806
                                sp->currentEvents |= SOCKET_EXCEPTION;
807
                        }
808
                        if (! all) {
809
                                break;
810
                        }
811
                }
812
        }
813
 
814
        bfree(B_L, readFds);
815
        bfree(B_L, writeFds);
816
        bfree(B_L, exceptFds);
817
 
818
        return nEvents;
819
}
820
#endif /* WIN || CE */
821
 
822
/******************************************************************************/
823
/*
824
 *      Process socket events
825
 */
826
 
827
void socketProcess(int sid)
828
{
829
        socket_t        *sp;
830
        int                     all;
831
 
832
        all = 0;
833
        if (sid < 0) {
834
                all = 1;
835
                sid = 0;
836
        }
837
/*
838
 *      Process each socket
839
 */
840
        for (; sid < socketMax; sid++) {
841
                if ((sp = socketList[sid]) == NULL) {
842
                        if (! all) {
843
                                break;
844
                        } else {
845
                                continue;
846
                        }
847
                }
848
                if (socketReady(sid)) {
849
                        socketDoEvent(sp);
850
                }
851
                if (! all) {
852
                        break;
853
                }
854
        }
855
}
856
 
857
/******************************************************************************/
858
/*
859
 *      Process an event on the event queue
860
 */
861
 
862
static int socketDoEvent(socket_t *sp)
863
{
864
        ringq_t *rq;
865
        int     sid;
866
 
867
        a_assert(sp);
868
 
869
    sid = sp->sid;
870
        if (sp->currentEvents & SOCKET_READABLE) {
871
                if (sp->flags & SOCKET_LISTENING) {
872
                        socketAccept(sp);
873
                        sp->currentEvents = 0;
874
                        return 1;
875
                }
876
 
877
        } else {
878
/*
879
 *              If there is still read data in the buffers, trigger the read handler
880
 *              NOTE: this may busy spin if the read handler doesn't read the data
881
 */
882
                if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid)) {
883
                        sp->currentEvents |= SOCKET_READABLE;
884
                }
885
        }
886
 
887
 
888
/*
889
 *      If now writable and flushing in the background, continue flushing
890
 */
891
        if (sp->currentEvents & SOCKET_WRITABLE) {
892
                if (sp->flags & SOCKET_FLUSHING) {
893
                        rq = &sp->outBuf;
894
                        if (ringqLen(rq) > 0) {
895
                                socketFlush(sp->sid);
896
                        } else {
897
                                sp->flags &= ~SOCKET_FLUSHING;
898
                        }
899
                }
900
        }
901
 
902
/*
903
 *      Now invoke the users socket handler. NOTE: the handler may delete the
904
 *      socket, so we must be very careful after calling the handler.
905
 */
906
        if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
907
                (sp->handler)(sid, sp->handlerMask & sp->currentEvents,
908
                        sp->handler_data);
909
/*
910
 *              Make sure socket pointer is still valid, then reset the currentEvents.
911
 */
912
                if (socketList && sid < socketMax && socketList[sid] == sp) {
913
                        sp->currentEvents = 0;
914
                }
915
        }
916
        return 1;
917
}
918
 
919
/******************************************************************************/
920
/*
921
 *      Set the socket blocking mode
922
 */
923
 
924
int socketSetBlock(int sid, int on)
925
{
926
        socket_t                *sp;
927
        unsigned long   flag;
928
        int                             iflag;
929
        int                             oldBlock;
930
 
931
        flag = iflag = !on;
932
 
933
        if ((sp = socketPtr(sid)) == NULL) {
934
                a_assert(0);
935
                return 0;
936
        }
937
        oldBlock = (sp->flags & SOCKET_BLOCK);
938
        sp->flags &= ~(SOCKET_BLOCK);
939
        if (on) {
940
                sp->flags |= SOCKET_BLOCK;
941
        }
942
 
943
/*
944
 *      Put the socket into block / non-blocking mode
945
 */
946
        if (sp->flags & SOCKET_BLOCK) {
947
#if CE || WIN
948
                ioctlsocket(sp->sock, FIONBIO, &flag);
949
#elif ECOS
950
                int off;
951
                off = 0;
952
                ioctl(sp->sock, FIONBIO, &off);
953
#elif VXWORKS
954
                ioctl(sp->sock, FIONBIO, (int)&iflag);
955
#else
956
                fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK);
957
#endif
958
 
959
        } else {
960
#if CE || WIN
961
                ioctlsocket(sp->sock, FIONBIO, &flag);
962
#elif ECOS
963
                int on;
964
                on = 1;
965
                ioctl(sp->sock, FIONBIO, &on);
966
#elif VXWORKS
967
                ioctl(sp->sock, FIONBIO, (int)&iflag);
968
#else
969
                fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK);
970
#endif
971
        }
972
        return oldBlock;
973
}
974
 
975
/******************************************************************************/
976
/*
977
 *      Return true if a readable socket has buffered data. - not public
978
 */
979
 
980
int socketDontBlock()
981
{
982
        socket_t        *sp;
983
        int                     i;
984
 
985
        for (i = 0; i < socketMax; i++) {
986
                if ((sp = socketList[i]) == NULL ||
987
                                (sp->handlerMask & SOCKET_READABLE) == 0) {
988
                        continue;
989
                }
990
                if (socketInputBuffered(i) > 0) {
991
                        return 1;
992
                }
993
        }
994
        return 0;
995
}
996
 
997
/******************************************************************************/
998
/*
999
 *      Return true if a particular socket buffered data. - not public
1000
 */
1001
 
1002
int socketSockBuffered(int sock)
1003
{
1004
        socket_t        *sp;
1005
        int                     i;
1006
 
1007
        for (i = 0; i < socketMax; i++) {
1008
                if ((sp = socketList[i]) == NULL || sp->sock != sock) {
1009
                        continue;
1010
                }
1011
                return socketInputBuffered(i);
1012
        }
1013
        return 0;
1014
}
1015
 
1016
#endif /* (!WIN) | LITTLEFOOT | WEBS */
1017
 
1018
/******************************************************************************/

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.