source: rtems/cpukit/httpd/socket.c @ 4bf1801

4.104.114.84.95
Last change on this file since 4bf1801 was b8d9f41, checked in by Joel Sherrill <joel.sherrill@…>, on 10/28/99 at 14:59:35

Added include of <sys/select.h> in attempt to remove compilation warning.

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