source: rtems/cpukit/httpd/socket.c @ c1cdaa0

4.104.114.84.95
Last change on this file since c1cdaa0 was c1cdaa0, checked in by Joel Sherrill <joel.sherrill@…>, on 10/27/99 at 12:50:33

Patch from Emmanuel Raguet <raguet@…> and Eric Valette
<valette@…> to add a port of the GoAhead? web server
(httpd) to the RTEMS build tree. They have successfully used
this BSP on i386/pc386 and PowerPC/mcp750.

Mark and Joel spoke with Nick Berliner <nickb@…> on
26 Oct 1999 about this port and got verbal approval to include
it in RTEMS distributions.

  • Property mode set to 100644
File size: 21.5 KB
Line 
1/*
2 * socket.c -- Socket support module for UNIX
3 *
4 * Copyright (c) Go Ahead, 1995-1999
5 */
6
7/******************************** Description *********************************/
8
9/*
10 *      SCO Unix Socket Module.  This supports non-blocking buffered socket I/O.
11 */
12
13/********************************** Includes **********************************/
14
15#include        <errno.h>
16#include        <fcntl.h>
17#include        <string.h>
18#include        <stdlib.h>
19#include        <unistd.h>
20
21#include        "uemf.h"
22
23/*********************************** Defines **********************************/
24
25typedef struct {
26        char                    host[64];                               /* Host name */
27        ringq_t                 inBuf;                                  /* Input ring queue */
28        ringq_t                 outBuf;                                 /* Output ring queue */
29        ringq_t                 lineBuf;                                /* Line ring queue */
30        socketAccept_t  accept;                                 /* Accept handler */
31        socketHandler_t handler;                                /* User I/O handler */
32        int                             handler_data;                   /* User handler data */
33        int                             sid;                                    /* Index into socket[] */
34        int                             port;                                   /* Port to listen on */
35        int                             flags;                                  /* Current state flags */
36        int                             readyMask;                              /* Events now ready */
37        int                             interestMask;                   /* Events interest */
38        int                             error;                                  /* Last error */
39        int                             sock;                                   /* Actual socket handle */
40} socket_t;
41
42/************************************ Locals **********************************/
43
44static socket_t**       socketList;                             /* List of open sockets */
45static int                      socketMax;                              /* Maximum size of socket */
46static int                      socketHighestFd = -1;   /* Highest socket fd opened */
47
48/***************************** Forward Declarations ***************************/
49
50static int      socketAlloc(char* host, int port, socketAccept_t accept, int flags);
51static void socketFree(int sid);
52static void socketAccept(socket_t* sp);
53static int      socketGetInput(int sid, char* buf, int toRead, int* errCode);
54static int      socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode);
55static int      socketDoEvent(socket_t *sp);
56static int      socketGetError();
57static int      socketWaitForEvent(socket_t* sp, int events, int* errCode);
58static int      socketNonBlock(socket_t *sp);
59static socket_t* socketPtr(int sid);
60
61/*********************************** Code *************************************/
62/*
63 *      Open socket module
64 */
65
66int socketOpen()
67{
68        return 0;
69}
70
71/******************************************************************************/
72/*
73 *      Close the socket module, by closing all open connections
74 */
75
76void socketClose()
77{
78        int             i;
79
80        for (i = socketMax; i >= 0; i--) {
81                if (socketList && socketList[i]) {
82                        socketCloseConnection(i);
83                }
84        }
85}
86
87/******************************************************************************/
88/*
89 *      Open a client or server socket. Host is NULL if we want server capability.
90 */
91
92int socketOpenConnection(char* host, int port, socketAccept_t accept, int flags)
93{
94        socket_t                        *sp;
95        struct sockaddr_in      sockaddr;
96        struct hostent          *hostent;               /* Host database entry */
97        int                                     sid, rc;
98
99/*
100 *      Allocate a socket structure
101 */
102        if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
103                return -1;
104        }
105        sp = socketList[sid];
106        a_assert(sp);
107
108/*
109 *      Create the socket address structure
110 */
111        memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
112        sockaddr.sin_family = AF_INET;
113        sockaddr.sin_port = htons((short) (port & 0xFFFF));
114
115        if (host == NULL) {
116                sockaddr.sin_addr.s_addr = INADDR_ANY;
117        } else {
118                sockaddr.sin_addr.s_addr = inet_addr(host);
119                if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
120                        hostent = gethostbyname(host);
121                        if (hostent != NULL) {
122                                memcpy((char *) &sockaddr.sin_addr,
123                                        (char *) hostent->h_addr_list[0],
124                                        (size_t) hostent->h_length);
125                        } else {
126                                errno = ENXIO;
127                                socketFree(sid);
128                                return -1;
129                        }
130                }
131        }
132
133/*
134 *      Create the socket. Set the close on exec flag so children don't
135 *      inherit the socket.
136 */
137        sp->sock = socket(AF_INET, SOCK_STREAM, 0);
138        if (sp->sock < 0) {
139                socketFree(sid);
140                return -1;
141        }
142        fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
143        socketHighestFd = max(socketHighestFd, sp->sock);
144
145/*
146 *      Host is set if we are the client
147 */
148        if (host) {
149/*
150 *              Connect to the remote server
151 */
152                if (connect(sp->sock, (struct sockaddr *) &sockaddr,
153                                sizeof(sockaddr)) < 0) {
154                        socketFree(sid);
155                        return -1;
156                }
157                socketNonBlock(sp);
158
159        } else {
160/*
161 *              Bind to the socket endpoint with resule and the call listen() 
162 **             to start listening
163 */
164                rc = 1;
165                setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
166                if (bind(sp->sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr))
167                                < 0) {
168                        socketFree(sid);
169                        return -1;
170                }
171                sp->flags |= SOCKET_LISTENING;
172
173                if (listen(sp->sock, SOMAXCONN) < 0) {
174                        socketFree(sid);
175                        return -1;
176                }
177                sp->interestMask = SOCKET_READABLE;
178        }
179        return sid;
180}
181
182/******************************************************************************/
183/*
184 *      Close a socket
185 */
186
187void socketCloseConnection(int sid)
188{
189        socket_t*       sp;
190
191        if ((sp = socketPtr(sid)) == NULL) {
192                return;
193        }
194
195/*
196 *      We always flush all output before closing. Unlink from the emf event
197 *      mechanism and then free (and close) the connection
198 */
199        socketFlush(sid, 1);
200        socketFree(sid);
201}
202
203/******************************************************************************/
204/*
205 *      Accept a connection. Called by socketDoEvent
206 */
207
208static void socketAccept(socket_t* sp)
209{
210        struct sockaddr_in      addr;
211        socket_t                        *nsp;
212        size_t                          len;
213        int                             newSock, nid;
214
215        a_assert(sp);
216
217/*
218 *      Accept the connection and prevent inheriting by children (F_SETFD)
219 */
220        len = sizeof(struct sockaddr_in);
221        if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, &len)) < 0) {
222                return;
223        }
224        fcntl(newSock, F_SETFD, FD_CLOEXEC);
225        socketHighestFd = max(socketHighestFd, newSock);
226
227/*
228 *      Create a socket structure and insert into the socket list
229 */
230        nid = socketAlloc(sp->host, sp->port, sp->accept, 0);
231        nsp = socketList[nid];
232        a_assert(nsp);
233        nsp->sock = newSock;
234
235        if (nsp == NULL) {
236                return;
237        }
238/*
239 *      Call the user accept callback, the user must call socketCreateHandler
240 *      to register for further events of interest.
241 */
242        if (sp->accept != NULL) {
243                if ((sp->accept)(nid, inet_ntoa(addr.sin_addr),
244                                ntohs(addr.sin_port)) < 0) {
245                        socketFree(nid);
246                        return;
247                }
248        }
249        socketNonBlock(nsp);
250}
251
252/******************************************************************************/
253/*
254 *      Write to a socket. This may block if the underlying socket cannot
255 *      absorb the data. Returns -1 on error, otherwise the number of bytes
256 *      written.
257 */
258
259int     socketWrite(int sid, char* buf, int bufsize)
260{
261        socket_t*       sp;
262        ringq_t*        rq;
263        int                     len, bytesWritten, room;
264
265        a_assert(buf);
266        a_assert(bufsize >= 0);
267
268        if ((sp = socketPtr(sid)) == NULL) {
269                return -1;
270        }
271       
272/*
273 *      Loop adding as much data to the output ringq as we can absorb
274 *      Flush when the ringq is too full and continue.
275 */
276        rq = &sp->outBuf;
277        for (bytesWritten = 0; bufsize > 0; ) {
278                if ((room = ringqPutBlkMax(rq)) == 0) {
279                        if (socketFlush(sid, 0) < 0) {
280                                return -1;
281                        }
282                        if ((room = ringqPutBlkMax(rq)) == 0) {
283                                break;
284                        }
285                        continue;
286                }
287                len = min(room, bufsize);
288                ringqPutBlk(rq, (unsigned char*) buf, len);
289                bytesWritten += len;
290                bufsize -= len;
291                buf += len;
292        }
293        return bytesWritten;
294}
295
296/******************************************************************************/
297/*
298 *      Read from a socket. Return the number of bytes read if successful. This
299 *      may be less than the requested "bufsize" and may be zero. Return -1 for
300 *      errors. Return 0 for EOF. Otherwise return the number of bytes read. Since
301 *      this may be zero, callers should use socketEof() to distinguish between
302 *      this and EOF. Note: this ignores the line buffer, so a previous socketGets
303 *      which read a partial line may cause a subsequent socketRead to miss
304 *      some data.
305 */
306
307int     socketRead(int sid, char* buf, int bufsize)
308{
309        socket_t*       sp;
310        ringq_t*        rq;
311        int                     len, room, errCode, bytesRead;
312
313        a_assert(buf);
314        a_assert(bufsize > 0);
315
316        if ((sp = socketPtr(sid)) == NULL) {
317                return -1;
318        }
319
320        if (sp->flags & SOCKET_EOF) {
321                return 0;
322        }
323
324        rq = &sp->inBuf;
325        for (bytesRead = 0; bufsize > 0; ) {
326                len = min(ringqLen(rq), bufsize);
327                if (len <= 0) {
328                        room = ringqPutBlkMax(rq);
329                        len = socketGetInput(sid, (char*) rq->endp, room, &errCode);
330                        if (len < 0) {
331                                if (errCode == EWOULDBLOCK) {
332                                        if (bytesRead >= 0) {
333                                                return bytesRead;
334                                        }
335                                }
336                                return -1;
337
338                        } else if (len == 0) {
339/*
340 *                              This is EOF, but we may have already read some data so pass that
341 *                              back first before notifying EOF. The next read will return 0
342 *                              to indicate EOF.
343 */
344                                return bytesRead;
345                        }
346                        ringqPutBlkAdj(rq, len);
347                        len = min(len, bufsize);
348                }
349                memcpy(&buf[bytesRead], rq->servp, len);
350                ringqGetBlkAdj(rq, len);
351                bufsize -= len;
352                bytesRead += len;
353        }
354        return bytesRead;
355}
356
357/******************************************************************************/
358/*
359 *      Get a string from a socket. This returns data in *buf in a malloced string
360 *      after trimming the '\n'. If there is zero bytes returned, *buf will be set
361 *      to NULL. It returns -1 for error, EOF or when no complete line yet read.
362 *      Otherwise the length of the line is returned. If a partial line is read
363 *      socketInputBuffered or socketEof can be used to distinguish between EOF
364 *      and partial line still buffered. This routine eats and ignores carriage
365 *  returns.
366 */
367
368int     socketGets(int sid, char** buf)
369{
370        socket_t*       sp;
371        ringq_t*        lq;
372        char            c;
373        int                     rc, len;
374
375        a_assert(buf);
376
377        if ((sp = socketPtr(sid)) == NULL) {
378                return -1;
379        }
380        lq = &sp->lineBuf;
381
382        while (1) {
383
384                if ((rc = socketRead(sid, &c, 1)) < 0) {
385                        return rc;
386
387                } else if (rc == 0) {
388/*
389 *                      If there is a partial line and we are at EOF, pretend we saw a '\n'
390 */
391                        if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
392                                c = '\n';
393                        } else {
394                                return -1;
395                        }
396                }
397/*
398 *              If a newline is seen, return the data excluding the new line to the
399 *              caller. If carriage return is seen, just eat it.
400 */
401                if (c == '\n') {
402                        len = ringqLen(lq);
403                        if (len > 0) {
404                                if ((*buf = balloc(B_L, len + 1)) == NULL) {
405                                        return -1;
406                                }
407                                memset(*buf, 0, len + 1);
408                                ringqGetBlk(lq, (unsigned char*) *buf, len);
409                        } else {
410                                *buf = NULL;
411                        }
412                        return len;
413
414                } else if (c == '\r') {
415                        continue;
416                }
417                ringqPutc(lq, c);
418        }
419}
420
421/******************************************************************************/
422/*
423 *      Flush a socket. Do not wait, just initiate output and return.
424 *      This will return -1 on errors and 0 if successful.
425 */
426
427int socketFlush(int sid, int block)
428{
429        socket_t*       sp;
430        ringq_t*        rq;
431        int                     len, bytesWritten, errCode;
432
433        a_assert(block == 0 || block == 1);
434
435        if ((sp = socketPtr(sid)) == NULL) {
436                return -1;
437        }
438        rq = &sp->outBuf;
439
440/*
441 *      Set the background flushing flag which socketDoEvent will check to
442 *      continue the flush.
443 */
444        if (!block) {
445                sp->flags |= SOCKET_FLUSHING;
446        }
447
448/*
449 *      Break from loop if not blocking after initiating output. If we are blocking
450 *      we wait for a write event.
451 */
452        while (ringqLen(rq) > 0) {
453                len = ringqGetBlkMax(&sp->outBuf);
454                bytesWritten = socketDoOutput(sp, (char*) rq->servp, len, &errCode);
455                if (bytesWritten < 0) {
456                        if (errCode == EINTR) {
457                                continue;
458                        } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) {
459                                if (! block) {
460                                        return 0;
461                                }
462                                if (socketWaitForEvent(sp, SOCKET_WRITABLE | SOCKET_EXCEPTION,
463                                                &errCode)) {
464                                        continue;
465                                }
466                        }
467                        return -1;
468                }
469                ringqGetBlkAdj(rq, bytesWritten);
470                if (! block) {
471                        break;
472                }
473        }
474        return 0;
475}
476
477/******************************************************************************/
478/*
479 *      Return the count of input characters buffered. We look at both the line
480 *      buffer and the input (raw) buffer. Return -1 on error or EOF.
481 */
482
483int socketInputBuffered(int sid)
484{
485        socket_t*       sp;
486
487        if ((sp = socketPtr(sid)) == NULL) {
488                return -1;
489        }
490        if (socketEof(sid)) {
491                return -1;
492        }
493        return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
494}
495
496/******************************************************************************/
497/*
498 *      Return true if EOF
499 */
500
501int socketEof(int sid)
502{
503        socket_t*       sp;
504
505        if ((sp = socketPtr(sid)) == NULL) {
506                return -1;
507        }
508        return sp->flags & SOCKET_EOF;
509}
510
511/******************************************************************************/
512/*
513 *      Create a user handler for this socket. The handler called whenever there
514 *      is an event of interest as defined by interestMask (SOCKET_READABLE, ...)
515 */
516
517void socketCreateHandler(int sid, int interestMask, socketHandler_t handler,
518        int data)
519{
520        socket_t*       sp;
521
522        if ((sp = socketPtr(sid)) == NULL) {
523                return;
524        }
525        sp->handler = handler;
526        sp->handler_data = data;
527        sp->interestMask = interestMask;
528}
529
530/******************************************************************************/
531/*
532 *      Delete a handler
533 */
534
535void socketDeleteHandler(int sid)
536{
537        socket_t*       sp;
538
539        if ((sp = socketPtr(sid)) == NULL) {
540                return;
541        }
542        sp->handler = NULL;
543        sp->interestMask = 0;
544}
545
546/******************************************************************************/
547/*
548 *      Get more input from the socket and return in buf.
549 *      Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
550 */
551
552static int socketGetInput(int sid, char* buf, int toRead, int* errCode)
553{
554        struct sockaddr_in      server;
555        socket_t*                       sp;
556        int                             len, bytesRead;
557       
558        a_assert(buf);
559        a_assert(errCode);
560
561        *errCode = 0;
562
563        if ((sp = socketPtr(sid)) == NULL) {
564                return -1;
565        }
566
567/*
568 *      If we have previously seen an EOF condition, then just return
569 */
570        if (sp->flags & SOCKET_EOF) {
571                return 0;
572        }
573
574/*
575 *      Read the data
576 */
577        if (sp->flags & SOCKET_BROADCAST) {
578                server.sin_family = AF_INET;
579                server.sin_addr.s_addr = INADDR_BROADCAST;
580                server.sin_port = htons((short)(sp->port & 0xFFFF));
581                len = sizeof(server);
582                bytesRead = recvfrom(sp->sock, buf, toRead, 0,
583                        (struct sockaddr*) &server, &len);
584        } else {
585                bytesRead = recv(sp->sock, buf, toRead, 0);
586        }
587
588        if (bytesRead < 0) {
589                if (errno == ECONNRESET) {
590                        return 0;
591                }
592                *errCode = socketGetError();
593                return -1;
594
595        } else if (bytesRead == 0) {
596                sp->flags |= SOCKET_EOF;
597        }
598        return bytesRead;
599}
600
601/******************************************************************************/
602/*
603 *      Socket output procedure. Return -1 on errors otherwise return the number
604 *      of bytes written.
605 */
606
607static int socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode)
608{
609        struct sockaddr_in      server;
610        int                             bytes;
611
612        a_assert(sp);
613        a_assert(buf);
614        a_assert(toWrite > 0);
615        a_assert(errCode);
616
617        *errCode = 0;
618
619/*
620 *      Write the data
621 */
622        if (sp->flags & SOCKET_BROADCAST) {
623                server.sin_family = AF_INET;
624                server.sin_addr.s_addr = INADDR_BROADCAST;
625                server.sin_port = htons((short)(sp->port & 0xFFFF));
626                bytes = sendto(sp->sock, buf, toWrite, 0,
627                        (struct sockaddr*) &server, sizeof(server));
628        } else {
629                bytes = send(sp->sock, buf, toWrite, 0);
630        }
631
632        if (bytes == 0 && bytes != toWrite) {
633                *errCode = EWOULDBLOCK;
634                return -1;
635        }
636
637        if (bytes < 0) {
638                *errCode = socketGetError();
639        }
640        return bytes;
641}
642
643/******************************************************************************/
644/*
645 *      Return TRUE if there is a socket with an event ready to process,
646 */
647
648int socketReady()
649{
650        socket_t        *sp;
651        int                     i;
652       
653        for (i = 0; i < socketMax; i++) {
654                if ((sp = socketList[i]) == NULL) {
655                        continue;
656                }
657                if (sp->readyMask & sp->interestMask) {
658                        return 1;
659                }
660        }
661        return 0;
662}
663
664/******************************************************************************/
665/*
666 *      Wait for a handle to become readable or writable and return a number of
667 *      noticed events.
668 */
669
670int socketSelect()
671{
672        socket_t        *sp;
673        fd_mask         *readFds, *writeFds, *exceptFds;
674        int             sid, len, nwords, index, bit, nEvents;
675
676/*
677 *      Allocate and zero the select masks
678 */
679        nwords = (socketHighestFd + NFDBITS - 1) / NFDBITS;
680        len = nwords * sizeof(int);
681
682        readFds = balloc(B_L, len);
683        memset(readFds, 0, len);
684        writeFds = balloc(B_L, len);
685        memset(writeFds, 0, len);
686        exceptFds = balloc(B_L, len);
687        memset(exceptFds, 0, len);
688
689/*
690 *      Set the select event masks for events to watch
691 */
692        for (sid = 0; sid < socketMax; sid++) {
693                if ((sp = socketList[sid]) == NULL) {
694                        continue;
695                }
696                a_assert(sp);
697
698/*
699 *              Initialize the ready masks and compute the mask offsets.
700 */
701                index = sp->sock / (NBBY * sizeof(fd_mask));
702                bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
703               
704/*
705 *              Set the appropriate bit in the ready masks for the sp->sock.
706 */
707                if (sp->interestMask & SOCKET_READABLE) {
708                        readFds[index] |= bit;
709                }
710                if (sp->interestMask & SOCKET_WRITABLE) {
711                        writeFds[index] |= bit;
712                }
713                if (sp->interestMask & SOCKET_EXCEPTION) {
714                        exceptFds[index] |= bit;
715                }
716        }
717
718/*
719 *      Wait for the event or a timeout.
720 */
721        nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
722                (fd_set *) writeFds, (fd_set *) exceptFds, NULL);
723        if (nEvents > 0) {
724                for (sid = 0; sid < socketMax; sid++) {
725                        if ((sp = socketList[sid]) == NULL) {
726                                continue;
727                        }
728
729                        index = sp->sock / (NBBY * sizeof(fd_mask));
730                        bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
731               
732                        if (readFds[index] & bit) {
733                                sp->readyMask |= SOCKET_READABLE;
734                        }
735                        if (writeFds[index] & bit) {
736                                sp->readyMask |= SOCKET_WRITABLE;
737                        }
738                        if (exceptFds[index] & bit) {
739                                sp->readyMask |= SOCKET_EXCEPTION;
740                        }
741                }
742        }
743
744        bfree(B_L, readFds);
745        bfree(B_L, writeFds);
746        bfree(B_L, exceptFds);
747
748        return nEvents;
749}
750
751/******************************************************************************/
752/*
753 *      Process socket events
754 */
755
756void socketProcess()
757{
758        socket_t        *sp;
759        int                     sid;
760
761/*
762 *      Process each socket
763 */
764        for (sid = 0; sid < socketMax; sid++) {
765                if ((sp = socketList[sid]) == NULL) {
766                        continue;
767                }
768                if ((sp->readyMask & sp->interestMask) ||
769                                ((sp->interestMask & SOCKET_READABLE) &&
770                                socketInputBuffered(sid))) {
771                        socketDoEvent(sp);
772                }
773        }
774}
775
776/******************************************************************************/
777/*
778 *      Process and event on the event queue
779 */
780
781static int socketDoEvent(socket_t *sp)
782{
783        ringq_t*                rq;
784        int                     sid;
785
786        a_assert(sp);
787
788    sid = sp->sid;
789        if (sp->readyMask & SOCKET_READABLE) {
790                if (sp->flags & SOCKET_LISTENING) {
791                        socketAccept(sp);
792                        sp->readyMask = 0;
793                        return 1;
794                }
795        } else {
796/*
797 *              If there is still read data in the buffers, trigger the read handler
798 *              NOTE: this may busy spin if the read handler doesn't read the data
799 */
800                if (sp->interestMask & SOCKET_READABLE && socketInputBuffered(sid)) {
801                        sp->readyMask |= SOCKET_READABLE;
802                }
803        }
804
805
806/*
807 *      If now writable and flushing in the background, continue flushing
808 */
809        if (sp->readyMask & SOCKET_WRITABLE) {
810                if (sp->flags & SOCKET_FLUSHING) {
811                        rq = &sp->outBuf;
812                        if (ringqLen(rq) > 0) {
813                                socketFlush(sp->sid, 0);
814                        } else {
815                                sp->flags &= ~SOCKET_FLUSHING;
816                        }
817                }
818        }
819
820/*
821 *      Now invoke the users socket handler. NOTE: the handler may delete the
822 *      socket, so we must be very careful after calling the handler.
823 */
824        if (sp->handler && (sp->interestMask & sp->readyMask)) {
825                (sp->handler)(sid, sp->interestMask & sp->readyMask,
826                        sp->handler_data);
827/*
828 *              Make sure socket pointer is still valid, then set the readyMask
829 *              to 0.
830 */
831                if (socketPtr(sid)) {
832                        sp->readyMask = 0;
833                }
834        }
835        return 1;
836}
837
838/******************************************************************************/
839/*
840 *      Allocate a new socket structure
841 */
842
843static int socketAlloc(char* host, int port, socketAccept_t accept, int flags)
844{
845        socket_t        *sp;
846        int                     sid;
847
848        if ((sid = hAlloc((void***) &socketList)) < 0) {
849                return -1;
850        }
851        if ((sp = (socket_t*) balloc(B_L, sizeof(socket_t))) == NULL) {
852                hFree((void***) &socket, sid);
853                return -1;
854        }
855        memset(sp, 0, sizeof(socket_t));
856        socketList[sid] = sp;
857        if (sid >= socketMax)
858                socketMax = sid + 1;
859
860        sp->sid = sid;
861        sp->accept = accept;
862        sp->port = port;
863        sp->flags = flags;
864
865        if (host) {
866                strncpy(sp->host, host, sizeof(sp->host));
867        }
868
869        ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
870        ringqOpen(&sp->outBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
871        ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1);
872
873        return sid;
874}
875
876/******************************************************************************/
877/*
878 *      Free a socket structure
879 */
880
881static void socketFree(int sid)
882{
883        socket_t*       sp;
884        int                     i;
885
886        if ((sp = socketPtr(sid)) == NULL) {
887                return;
888        }
889        if (sp->sock >= 0) {
890                close(sp->sock);
891        }
892
893        ringqClose(&sp->inBuf);
894        ringqClose(&sp->outBuf);
895        ringqClose(&sp->lineBuf);
896
897        bfree(B_L, sp);
898        socketMax = hFree((void***) &socketList, sid);
899
900/*
901 *      Calculate the new highest socket number
902 */
903        socketHighestFd = -1;
904        for (i = 0; i < socketMax; i++) {
905                if ((sp = socketList[i]) == NULL) {
906                        continue;
907                }
908                socketHighestFd = max(socketHighestFd, sp->sock);
909        }
910}
911
912/******************************************************************************/
913/*
914 *      Validate a socket handle
915 */
916
917static socket_t* socketPtr(int sid)
918{
919        if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
920                a_assert(NULL);
921                return NULL;
922        }
923
924        a_assert(socketList[sid]);
925        return socketList[sid];
926}
927
928/******************************************************************************/
929/*
930 *      Get the operating system error code
931 */
932
933static int socketGetError()
934{
935        return errno;
936}
937
938/******************************************************************************/
939/*
940 *      Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
941 */
942
943static int socketWaitForEvent(socket_t* sp, int interestMask, int* errCode)
944{
945        a_assert(sp);
946
947        while (socketSelect()) {
948                if (sp->readyMask & interestMask) {
949                        break;
950                }
951        }
952        if (sp->readyMask & SOCKET_EXCEPTION) {
953                return -1;
954        } else if (sp->readyMask & SOCKET_WRITABLE) {
955                return 0;
956        } else {
957                *errCode = errno = EWOULDBLOCK;
958                return -1;
959        }
960}
961
962/******************************************************************************/
963/*
964 *      Put the socket into non-blocking mode
965 */
966
967static int socketNonBlock(socket_t *sp)
968{
969        int             flags;
970
971        flags = fcntl(sp->sock, F_GETFL) | O_NONBLOCK;
972        if (fcntl(sp->sock, F_SETFL, flags) < 0) {
973                return -1;
974    }
975        return 0;
976}
977
978/******************************************************************************/
979/*
980 *      Duplicate stdin and stdout
981 */
982
983int DuplicateStdFile (int sid){
984  int i;
985 
986  if (0 != dup2(socketList[sid]->sock, 0)  || 1 != dup2(socketList[sid]->sock, 1))
987    return -1;
988 
989  return 0;
990
991}
Note: See TracBrowser for help on using the repository browser.