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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [rtems_webserver/] [socket.c] - Diff between revs 30 and 173

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 30 Rev 173
/*
/*
 * socket.c -- Socket support module for UNIX
 * socket.c -- Socket support module for UNIX
 *
 *
 * Copyright (c) Go Ahead, 1995-1999
 * Copyright (c) Go Ahead, 1995-1999
 */
 */
 
 
/******************************** Description *********************************/
/******************************** Description *********************************/
 
 
/*
/*
 *      SCO Unix Socket Module.  This supports non-blocking buffered socket I/O.
 *      SCO Unix Socket Module.  This supports non-blocking buffered socket I/O.
 */
 */
 
 
/********************************** Includes **********************************/
/********************************** Includes **********************************/
 
 
#include        <errno.h>
#include        <errno.h>
#include        <fcntl.h>
#include        <fcntl.h>
#include        <string.h>
#include        <string.h>
#include        <stdlib.h>
#include        <stdlib.h>
#include        <unistd.h>
#include        <unistd.h>
 
 
#if __rtems__
#if __rtems__
#include        <sys/select.h>
#include        <sys/select.h>
#endif
#endif
 
 
#include        "uemf.h"
#include        "uemf.h"
 
 
/*********************************** Defines **********************************/
/*********************************** Defines **********************************/
 
 
typedef struct {
typedef struct {
        char                    host[64];                               /* Host name */
        char                    host[64];                               /* Host name */
        ringq_t                 inBuf;                                  /* Input ring queue */
        ringq_t                 inBuf;                                  /* Input ring queue */
        ringq_t                 outBuf;                                 /* Output ring queue */
        ringq_t                 outBuf;                                 /* Output ring queue */
        ringq_t                 lineBuf;                                /* Line ring queue */
        ringq_t                 lineBuf;                                /* Line ring queue */
        socketAccept_t  accept;                                 /* Accept handler */
        socketAccept_t  accept;                                 /* Accept handler */
        socketHandler_t handler;                                /* User I/O handler */
        socketHandler_t handler;                                /* User I/O handler */
        int                             handler_data;                   /* User handler data */
        int                             handler_data;                   /* User handler data */
        int                             sid;                                    /* Index into socket[] */
        int                             sid;                                    /* Index into socket[] */
        int                             port;                                   /* Port to listen on */
        int                             port;                                   /* Port to listen on */
        int                             flags;                                  /* Current state flags */
        int                             flags;                                  /* Current state flags */
        int                             readyMask;                              /* Events now ready */
        int                             readyMask;                              /* Events now ready */
        int                             interestMask;                   /* Events interest */
        int                             interestMask;                   /* Events interest */
        int                             error;                                  /* Last error */
        int                             error;                                  /* Last error */
        int                             sock;                                   /* Actual socket handle */
        int                             sock;                                   /* Actual socket handle */
} socket_t;
} socket_t;
 
 
/************************************ Locals **********************************/
/************************************ Locals **********************************/
 
 
static socket_t**       socketList;                             /* List of open sockets */
static socket_t**       socketList;                             /* List of open sockets */
static int                      socketMax;                              /* Maximum size of socket */
static int                      socketMax;                              /* Maximum size of socket */
static int                      socketHighestFd = -1;   /* Highest socket fd opened */
static int                      socketHighestFd = -1;   /* Highest socket fd opened */
 
 
/***************************** Forward Declarations ***************************/
/***************************** Forward Declarations ***************************/
 
 
static int      socketAlloc(char* host, int port, socketAccept_t accept, int flags);
static int      socketAlloc(char* host, int port, socketAccept_t accept, int flags);
static void socketFree(int sid);
static void socketFree(int sid);
static void socketAccept(socket_t* sp);
static void socketAccept(socket_t* sp);
static int      socketGetInput(int sid, char* buf, int toRead, int* errCode);
static int      socketGetInput(int sid, char* buf, int toRead, int* errCode);
static int      socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode);
static int      socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode);
static int      socketDoEvent(socket_t *sp);
static int      socketDoEvent(socket_t *sp);
static int      socketGetError();
static int      socketGetError();
static int      socketWaitForEvent(socket_t* sp, int events, int* errCode);
static int      socketWaitForEvent(socket_t* sp, int events, int* errCode);
static int      socketNonBlock(socket_t *sp);
static int      socketNonBlock(socket_t *sp);
static socket_t* socketPtr(int sid);
static socket_t* socketPtr(int sid);
 
 
/*********************************** Code *************************************/
/*********************************** Code *************************************/
/*
/*
 *      Open socket module
 *      Open socket module
 */
 */
 
 
int socketOpen()
int socketOpen()
{
{
        return 0;
        return 0;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Close the socket module, by closing all open connections
 *      Close the socket module, by closing all open connections
 */
 */
 
 
void socketClose()
void socketClose()
{
{
        int             i;
        int             i;
 
 
        for (i = socketMax; i >= 0; i--) {
        for (i = socketMax; i >= 0; i--) {
                if (socketList && socketList[i]) {
                if (socketList && socketList[i]) {
                        socketCloseConnection(i);
                        socketCloseConnection(i);
                }
                }
        }
        }
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Open a client or server socket. Host is NULL if we want server capability.
 *      Open a client or server socket. Host is NULL if we want server capability.
 */
 */
 
 
int socketOpenConnection(char* host, int port, socketAccept_t accept, int flags)
int socketOpenConnection(char* host, int port, socketAccept_t accept, int flags)
{
{
        socket_t                        *sp;
        socket_t                        *sp;
        struct sockaddr_in      sockaddr;
        struct sockaddr_in      sockaddr;
        struct hostent          *hostent;               /* Host database entry */
        struct hostent          *hostent;               /* Host database entry */
        int                                     sid, rc;
        int                                     sid, rc;
 
 
/*
/*
 *      Allocate a socket structure
 *      Allocate a socket structure
 */
 */
        if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
        if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
                return -1;
                return -1;
        }
        }
        sp = socketList[sid];
        sp = socketList[sid];
        a_assert(sp);
        a_assert(sp);
 
 
/*
/*
 *      Create the socket address structure
 *      Create the socket address structure
 */
 */
        memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
        memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
        sockaddr.sin_family = AF_INET;
        sockaddr.sin_family = AF_INET;
        sockaddr.sin_port = htons((short) (port & 0xFFFF));
        sockaddr.sin_port = htons((short) (port & 0xFFFF));
 
 
        if (host == NULL) {
        if (host == NULL) {
                sockaddr.sin_addr.s_addr = INADDR_ANY;
                sockaddr.sin_addr.s_addr = INADDR_ANY;
        } else {
        } else {
                sockaddr.sin_addr.s_addr = inet_addr(host);
                sockaddr.sin_addr.s_addr = inet_addr(host);
                if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
                if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
                        hostent = gethostbyname(host);
                        hostent = gethostbyname(host);
                        if (hostent != NULL) {
                        if (hostent != NULL) {
                                memcpy((char *) &sockaddr.sin_addr,
                                memcpy((char *) &sockaddr.sin_addr,
                                        (char *) hostent->h_addr_list[0],
                                        (char *) hostent->h_addr_list[0],
                                        (size_t) hostent->h_length);
                                        (size_t) hostent->h_length);
                        } else {
                        } else {
                                errno = ENXIO;
                                errno = ENXIO;
                                socketFree(sid);
                                socketFree(sid);
                                return -1;
                                return -1;
                        }
                        }
                }
                }
        }
        }
 
 
/*
/*
 *      Create the socket. Set the close on exec flag so children don't
 *      Create the socket. Set the close on exec flag so children don't
 *      inherit the socket.
 *      inherit the socket.
 */
 */
        sp->sock = socket(AF_INET, SOCK_STREAM, 0);
        sp->sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sp->sock < 0) {
        if (sp->sock < 0) {
                socketFree(sid);
                socketFree(sid);
                return -1;
                return -1;
        }
        }
        fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
        fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
        socketHighestFd = max(socketHighestFd, sp->sock);
        socketHighestFd = max(socketHighestFd, sp->sock);
 
 
/*
/*
 *      Host is set if we are the client
 *      Host is set if we are the client
 */
 */
        if (host) {
        if (host) {
/*
/*
 *              Connect to the remote server
 *              Connect to the remote server
 */
 */
                if (connect(sp->sock, (struct sockaddr *) &sockaddr,
                if (connect(sp->sock, (struct sockaddr *) &sockaddr,
                                sizeof(sockaddr)) < 0) {
                                sizeof(sockaddr)) < 0) {
                        socketFree(sid);
                        socketFree(sid);
                        return -1;
                        return -1;
                }
                }
                socketNonBlock(sp);
                socketNonBlock(sp);
 
 
        } else {
        } else {
/*
/*
 *              Bind to the socket endpoint with resule and the call listen()
 *              Bind to the socket endpoint with resule and the call listen()
 **             to start listening
 **             to start listening
 */
 */
                rc = 1;
                rc = 1;
                setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
                setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
                if (bind(sp->sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr))
                if (bind(sp->sock, (struct sockaddr *) &sockaddr, sizeof(sockaddr))
                                < 0) {
                                < 0) {
                        socketFree(sid);
                        socketFree(sid);
                        return -1;
                        return -1;
                }
                }
                sp->flags |= SOCKET_LISTENING;
                sp->flags |= SOCKET_LISTENING;
 
 
                if (listen(sp->sock, SOMAXCONN) < 0) {
                if (listen(sp->sock, SOMAXCONN) < 0) {
                        socketFree(sid);
                        socketFree(sid);
                        return -1;
                        return -1;
                }
                }
                sp->interestMask = SOCKET_READABLE;
                sp->interestMask = SOCKET_READABLE;
        }
        }
        return sid;
        return sid;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Close a socket
 *      Close a socket
 */
 */
 
 
void socketCloseConnection(int sid)
void socketCloseConnection(int sid)
{
{
        socket_t*       sp;
        socket_t*       sp;
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return;
                return;
        }
        }
 
 
/*
/*
 *      We always flush all output before closing. Unlink from the emf event
 *      We always flush all output before closing. Unlink from the emf event
 *      mechanism and then free (and close) the connection
 *      mechanism and then free (and close) the connection
 */
 */
        socketFlush(sid, 1);
        socketFlush(sid, 1);
        socketFree(sid);
        socketFree(sid);
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Accept a connection. Called by socketDoEvent
 *      Accept a connection. Called by socketDoEvent
 */
 */
 
 
static void socketAccept(socket_t* sp)
static void socketAccept(socket_t* sp)
{
{
        struct sockaddr_in      addr;
        struct sockaddr_in      addr;
        socket_t                        *nsp;
        socket_t                        *nsp;
        int                             len;
        int                             len;
        int                             newSock, nid;
        int                             newSock, nid;
 
 
        a_assert(sp);
        a_assert(sp);
 
 
/*
/*
 *      Accept the connection and prevent inheriting by children (F_SETFD)
 *      Accept the connection and prevent inheriting by children (F_SETFD)
 */
 */
        len = sizeof(struct sockaddr_in);
        len = sizeof(struct sockaddr_in);
        if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, &len)) < 0) {
        if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, &len)) < 0) {
                return;
                return;
        }
        }
        fcntl(newSock, F_SETFD, FD_CLOEXEC);
        fcntl(newSock, F_SETFD, FD_CLOEXEC);
        socketHighestFd = max(socketHighestFd, newSock);
        socketHighestFd = max(socketHighestFd, newSock);
 
 
/*
/*
 *      Create a socket structure and insert into the socket list
 *      Create a socket structure and insert into the socket list
 */
 */
        nid = socketAlloc(sp->host, sp->port, sp->accept, 0);
        nid = socketAlloc(sp->host, sp->port, sp->accept, 0);
        nsp = socketList[nid];
        nsp = socketList[nid];
        a_assert(nsp);
        a_assert(nsp);
        nsp->sock = newSock;
        nsp->sock = newSock;
 
 
        if (nsp == NULL) {
        if (nsp == NULL) {
                return;
                return;
        }
        }
/*
/*
 *      Call the user accept callback, the user must call socketCreateHandler
 *      Call the user accept callback, the user must call socketCreateHandler
 *      to register for further events of interest.
 *      to register for further events of interest.
 */
 */
        if (sp->accept != NULL) {
        if (sp->accept != NULL) {
                if ((sp->accept)(nid, inet_ntoa(addr.sin_addr),
                if ((sp->accept)(nid, inet_ntoa(addr.sin_addr),
                                ntohs(addr.sin_port)) < 0) {
                                ntohs(addr.sin_port)) < 0) {
                        socketFree(nid);
                        socketFree(nid);
                        return;
                        return;
                }
                }
        }
        }
        socketNonBlock(nsp);
        socketNonBlock(nsp);
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Write to a socket. This may block if the underlying socket cannot
 *      Write to a socket. This may block if the underlying socket cannot
 *      absorb the data. Returns -1 on error, otherwise the number of bytes
 *      absorb the data. Returns -1 on error, otherwise the number of bytes
 *      written.
 *      written.
 */
 */
 
 
int     socketWrite(int sid, char* buf, int bufsize)
int     socketWrite(int sid, char* buf, int bufsize)
{
{
        socket_t*       sp;
        socket_t*       sp;
        ringq_t*        rq;
        ringq_t*        rq;
        int                     len, bytesWritten, room;
        int                     len, bytesWritten, room;
 
 
        a_assert(buf);
        a_assert(buf);
        a_assert(bufsize >= 0);
        a_assert(bufsize >= 0);
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return -1;
                return -1;
        }
        }
 
 
/*
/*
 *      Loop adding as much data to the output ringq as we can absorb
 *      Loop adding as much data to the output ringq as we can absorb
 *      Flush when the ringq is too full and continue.
 *      Flush when the ringq is too full and continue.
 */
 */
        rq = &sp->outBuf;
        rq = &sp->outBuf;
        for (bytesWritten = 0; bufsize > 0; ) {
        for (bytesWritten = 0; bufsize > 0; ) {
                if ((room = ringqPutBlkMax(rq)) == 0) {
                if ((room = ringqPutBlkMax(rq)) == 0) {
                        if (socketFlush(sid, 0) < 0) {
                        if (socketFlush(sid, 0) < 0) {
                                return -1;
                                return -1;
                        }
                        }
                        if ((room = ringqPutBlkMax(rq)) == 0) {
                        if ((room = ringqPutBlkMax(rq)) == 0) {
                                break;
                                break;
                        }
                        }
                        continue;
                        continue;
                }
                }
                len = min(room, bufsize);
                len = min(room, bufsize);
                ringqPutBlk(rq, (unsigned char*) buf, len);
                ringqPutBlk(rq, (unsigned char*) buf, len);
                bytesWritten += len;
                bytesWritten += len;
                bufsize -= len;
                bufsize -= len;
                buf += len;
                buf += len;
        }
        }
        return bytesWritten;
        return bytesWritten;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Read from a socket. Return the number of bytes read if successful. This
 *      Read from a socket. Return the number of bytes read if successful. This
 *      may be less than the requested "bufsize" and may be zero. Return -1 for
 *      may be less than the requested "bufsize" and may be zero. Return -1 for
 *      errors. Return 0 for EOF. Otherwise return the number of bytes read. Since
 *      errors. Return 0 for EOF. Otherwise return the number of bytes read. Since
 *      this may be zero, callers should use socketEof() to distinguish between
 *      this may be zero, callers should use socketEof() to distinguish between
 *      this and EOF. Note: this ignores the line buffer, so a previous socketGets
 *      this and EOF. Note: this ignores the line buffer, so a previous socketGets
 *      which read a partial line may cause a subsequent socketRead to miss
 *      which read a partial line may cause a subsequent socketRead to miss
 *      some data.
 *      some data.
 */
 */
 
 
int     socketRead(int sid, char* buf, int bufsize)
int     socketRead(int sid, char* buf, int bufsize)
{
{
        socket_t*       sp;
        socket_t*       sp;
        ringq_t*        rq;
        ringq_t*        rq;
        int                     len, room, errCode, bytesRead;
        int                     len, room, errCode, bytesRead;
 
 
        a_assert(buf);
        a_assert(buf);
        a_assert(bufsize > 0);
        a_assert(bufsize > 0);
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return -1;
                return -1;
        }
        }
 
 
        if (sp->flags & SOCKET_EOF) {
        if (sp->flags & SOCKET_EOF) {
                return 0;
                return 0;
        }
        }
 
 
        rq = &sp->inBuf;
        rq = &sp->inBuf;
        for (bytesRead = 0; bufsize > 0; ) {
        for (bytesRead = 0; bufsize > 0; ) {
                len = min(ringqLen(rq), bufsize);
                len = min(ringqLen(rq), bufsize);
                if (len <= 0) {
                if (len <= 0) {
                        room = ringqPutBlkMax(rq);
                        room = ringqPutBlkMax(rq);
                        len = socketGetInput(sid, (char*) rq->endp, room, &errCode);
                        len = socketGetInput(sid, (char*) rq->endp, room, &errCode);
                        if (len < 0) {
                        if (len < 0) {
                                if (errCode == EWOULDBLOCK) {
                                if (errCode == EWOULDBLOCK) {
                                        if (bytesRead >= 0) {
                                        if (bytesRead >= 0) {
                                                return bytesRead;
                                                return bytesRead;
                                        }
                                        }
                                }
                                }
                                return -1;
                                return -1;
 
 
                        } else if (len == 0) {
                        } else if (len == 0) {
/*
/*
 *                              This is EOF, but we may have already read some data so pass that
 *                              This is EOF, but we may have already read some data so pass that
 *                              back first before notifying EOF. The next read will return 0
 *                              back first before notifying EOF. The next read will return 0
 *                              to indicate EOF.
 *                              to indicate EOF.
 */
 */
                                return bytesRead;
                                return bytesRead;
                        }
                        }
                        ringqPutBlkAdj(rq, len);
                        ringqPutBlkAdj(rq, len);
                        len = min(len, bufsize);
                        len = min(len, bufsize);
                }
                }
                memcpy(&buf[bytesRead], rq->servp, len);
                memcpy(&buf[bytesRead], rq->servp, len);
                ringqGetBlkAdj(rq, len);
                ringqGetBlkAdj(rq, len);
                bufsize -= len;
                bufsize -= len;
                bytesRead += len;
                bytesRead += len;
        }
        }
        return bytesRead;
        return bytesRead;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Get a string from a socket. This returns data in *buf in a malloced string
 *      Get a string from a socket. This returns data in *buf in a malloced string
 *      after trimming the '\n'. If there is zero bytes returned, *buf will be set
 *      after trimming the '\n'. If there is zero bytes returned, *buf will be set
 *      to NULL. It returns -1 for error, EOF or when no complete line yet read.
 *      to NULL. It returns -1 for error, EOF or when no complete line yet read.
 *      Otherwise the length of the line is returned. If a partial line is read
 *      Otherwise the length of the line is returned. If a partial line is read
 *      socketInputBuffered or socketEof can be used to distinguish between EOF
 *      socketInputBuffered or socketEof can be used to distinguish between EOF
 *      and partial line still buffered. This routine eats and ignores carriage
 *      and partial line still buffered. This routine eats and ignores carriage
 *  returns.
 *  returns.
 */
 */
 
 
int     socketGets(int sid, char** buf)
int     socketGets(int sid, char** buf)
{
{
        socket_t*       sp;
        socket_t*       sp;
        ringq_t*        lq;
        ringq_t*        lq;
        char            c;
        char            c;
        int                     rc, len;
        int                     rc, len;
 
 
        a_assert(buf);
        a_assert(buf);
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return -1;
                return -1;
        }
        }
        lq = &sp->lineBuf;
        lq = &sp->lineBuf;
 
 
        while (1) {
        while (1) {
 
 
                if ((rc = socketRead(sid, &c, 1)) < 0) {
                if ((rc = socketRead(sid, &c, 1)) < 0) {
                        return rc;
                        return rc;
 
 
                } else if (rc == 0) {
                } else if (rc == 0) {
/*
/*
 *                      If there is a partial line and we are at EOF, pretend we saw a '\n'
 *                      If there is a partial line and we are at EOF, pretend we saw a '\n'
 */
 */
                        if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
                        if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
                                c = '\n';
                                c = '\n';
                        } else {
                        } else {
                                return -1;
                                return -1;
                        }
                        }
                }
                }
/*
/*
 *              If a newline is seen, return the data excluding the new line to the
 *              If a newline is seen, return the data excluding the new line to the
 *              caller. If carriage return is seen, just eat it.
 *              caller. If carriage return is seen, just eat it.
 */
 */
                if (c == '\n') {
                if (c == '\n') {
                        len = ringqLen(lq);
                        len = ringqLen(lq);
                        if (len > 0) {
                        if (len > 0) {
                                if ((*buf = balloc(B_L, len + 1)) == NULL) {
                                if ((*buf = balloc(B_L, len + 1)) == NULL) {
                                        return -1;
                                        return -1;
                                }
                                }
                                memset(*buf, 0, len + 1);
                                memset(*buf, 0, len + 1);
                                ringqGetBlk(lq, (unsigned char*) *buf, len);
                                ringqGetBlk(lq, (unsigned char*) *buf, len);
                        } else {
                        } else {
                                *buf = NULL;
                                *buf = NULL;
                        }
                        }
                        return len;
                        return len;
 
 
                } else if (c == '\r') {
                } else if (c == '\r') {
                        continue;
                        continue;
                }
                }
                ringqPutc(lq, c);
                ringqPutc(lq, c);
        }
        }
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Flush a socket. Do not wait, just initiate output and return.
 *      Flush a socket. Do not wait, just initiate output and return.
 *      This will return -1 on errors and 0 if successful.
 *      This will return -1 on errors and 0 if successful.
 */
 */
 
 
int socketFlush(int sid, int block)
int socketFlush(int sid, int block)
{
{
        socket_t*       sp;
        socket_t*       sp;
        ringq_t*        rq;
        ringq_t*        rq;
        int                     len, bytesWritten, errCode;
        int                     len, bytesWritten, errCode;
 
 
        a_assert(block == 0 || block == 1);
        a_assert(block == 0 || block == 1);
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return -1;
                return -1;
        }
        }
        rq = &sp->outBuf;
        rq = &sp->outBuf;
 
 
/*
/*
 *      Set the background flushing flag which socketDoEvent will check to
 *      Set the background flushing flag which socketDoEvent will check to
 *      continue the flush.
 *      continue the flush.
 */
 */
        if (!block) {
        if (!block) {
                sp->flags |= SOCKET_FLUSHING;
                sp->flags |= SOCKET_FLUSHING;
        }
        }
 
 
/*
/*
 *      Break from loop if not blocking after initiating output. If we are blocking
 *      Break from loop if not blocking after initiating output. If we are blocking
 *      we wait for a write event.
 *      we wait for a write event.
 */
 */
        while (ringqLen(rq) > 0) {
        while (ringqLen(rq) > 0) {
                len = ringqGetBlkMax(&sp->outBuf);
                len = ringqGetBlkMax(&sp->outBuf);
                bytesWritten = socketDoOutput(sp, (char*) rq->servp, len, &errCode);
                bytesWritten = socketDoOutput(sp, (char*) rq->servp, len, &errCode);
                if (bytesWritten < 0) {
                if (bytesWritten < 0) {
                        if (errCode == EINTR) {
                        if (errCode == EINTR) {
                                continue;
                                continue;
                        } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) {
                        } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) {
                                if (! block) {
                                if (! block) {
                                        return 0;
                                        return 0;
                                }
                                }
                                if (socketWaitForEvent(sp, SOCKET_WRITABLE | SOCKET_EXCEPTION,
                                if (socketWaitForEvent(sp, SOCKET_WRITABLE | SOCKET_EXCEPTION,
                                                &errCode)) {
                                                &errCode)) {
                                        continue;
                                        continue;
                                }
                                }
                        }
                        }
                        return -1;
                        return -1;
                }
                }
                ringqGetBlkAdj(rq, bytesWritten);
                ringqGetBlkAdj(rq, bytesWritten);
                if (! block) {
                if (! block) {
                        break;
                        break;
                }
                }
        }
        }
        return 0;
        return 0;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Return the count of input characters buffered. We look at both the line
 *      Return the count of input characters buffered. We look at both the line
 *      buffer and the input (raw) buffer. Return -1 on error or EOF.
 *      buffer and the input (raw) buffer. Return -1 on error or EOF.
 */
 */
 
 
int socketInputBuffered(int sid)
int socketInputBuffered(int sid)
{
{
        socket_t*       sp;
        socket_t*       sp;
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return -1;
                return -1;
        }
        }
        if (socketEof(sid)) {
        if (socketEof(sid)) {
                return -1;
                return -1;
        }
        }
        return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
        return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Return true if EOF
 *      Return true if EOF
 */
 */
 
 
int socketEof(int sid)
int socketEof(int sid)
{
{
        socket_t*       sp;
        socket_t*       sp;
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return -1;
                return -1;
        }
        }
        return sp->flags & SOCKET_EOF;
        return sp->flags & SOCKET_EOF;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Create a user handler for this socket. The handler called whenever there
 *      Create a user handler for this socket. The handler called whenever there
 *      is an event of interest as defined by interestMask (SOCKET_READABLE, ...)
 *      is an event of interest as defined by interestMask (SOCKET_READABLE, ...)
 */
 */
 
 
void socketCreateHandler(int sid, int interestMask, socketHandler_t handler,
void socketCreateHandler(int sid, int interestMask, socketHandler_t handler,
        int data)
        int data)
{
{
        socket_t*       sp;
        socket_t*       sp;
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return;
                return;
        }
        }
        sp->handler = handler;
        sp->handler = handler;
        sp->handler_data = data;
        sp->handler_data = data;
        sp->interestMask = interestMask;
        sp->interestMask = interestMask;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Delete a handler
 *      Delete a handler
 */
 */
 
 
void socketDeleteHandler(int sid)
void socketDeleteHandler(int sid)
{
{
        socket_t*       sp;
        socket_t*       sp;
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return;
                return;
        }
        }
        sp->handler = NULL;
        sp->handler = NULL;
        sp->interestMask = 0;
        sp->interestMask = 0;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Get more input from the socket and return in buf.
 *      Get more input from the socket and return in buf.
 *      Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
 *      Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
 */
 */
 
 
static int socketGetInput(int sid, char* buf, int toRead, int* errCode)
static int socketGetInput(int sid, char* buf, int toRead, int* errCode)
{
{
        struct sockaddr_in      server;
        struct sockaddr_in      server;
        socket_t*                       sp;
        socket_t*                       sp;
        int                             len, bytesRead;
        int                             len, bytesRead;
 
 
        a_assert(buf);
        a_assert(buf);
        a_assert(errCode);
        a_assert(errCode);
 
 
        *errCode = 0;
        *errCode = 0;
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return -1;
                return -1;
        }
        }
 
 
/*
/*
 *      If we have previously seen an EOF condition, then just return
 *      If we have previously seen an EOF condition, then just return
 */
 */
        if (sp->flags & SOCKET_EOF) {
        if (sp->flags & SOCKET_EOF) {
                return 0;
                return 0;
        }
        }
 
 
/*
/*
 *      Read the data
 *      Read the data
 */
 */
        if (sp->flags & SOCKET_BROADCAST) {
        if (sp->flags & SOCKET_BROADCAST) {
                server.sin_family = AF_INET;
                server.sin_family = AF_INET;
                server.sin_addr.s_addr = INADDR_BROADCAST;
                server.sin_addr.s_addr = INADDR_BROADCAST;
                server.sin_port = htons((short)(sp->port & 0xFFFF));
                server.sin_port = htons((short)(sp->port & 0xFFFF));
                len = sizeof(server);
                len = sizeof(server);
                bytesRead = recvfrom(sp->sock, buf, toRead, 0,
                bytesRead = recvfrom(sp->sock, buf, toRead, 0,
                        (struct sockaddr*) &server, &len);
                        (struct sockaddr*) &server, &len);
        } else {
        } else {
                bytesRead = recv(sp->sock, buf, toRead, 0);
                bytesRead = recv(sp->sock, buf, toRead, 0);
        }
        }
 
 
        if (bytesRead < 0) {
        if (bytesRead < 0) {
                if (errno == ECONNRESET) {
                if (errno == ECONNRESET) {
                        return 0;
                        return 0;
                }
                }
                *errCode = socketGetError();
                *errCode = socketGetError();
                return -1;
                return -1;
 
 
        } else if (bytesRead == 0) {
        } else if (bytesRead == 0) {
                sp->flags |= SOCKET_EOF;
                sp->flags |= SOCKET_EOF;
        }
        }
        return bytesRead;
        return bytesRead;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Socket output procedure. Return -1 on errors otherwise return the number
 *      Socket output procedure. Return -1 on errors otherwise return the number
 *      of bytes written.
 *      of bytes written.
 */
 */
 
 
static int socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode)
static int socketDoOutput(socket_t* sp, char* buf, int toWrite, int* errCode)
{
{
        struct sockaddr_in      server;
        struct sockaddr_in      server;
        int                             bytes;
        int                             bytes;
 
 
        a_assert(sp);
        a_assert(sp);
        a_assert(buf);
        a_assert(buf);
        a_assert(toWrite > 0);
        a_assert(toWrite > 0);
        a_assert(errCode);
        a_assert(errCode);
 
 
        *errCode = 0;
        *errCode = 0;
 
 
/*
/*
 *      Write the data
 *      Write the data
 */
 */
        if (sp->flags & SOCKET_BROADCAST) {
        if (sp->flags & SOCKET_BROADCAST) {
                server.sin_family = AF_INET;
                server.sin_family = AF_INET;
                server.sin_addr.s_addr = INADDR_BROADCAST;
                server.sin_addr.s_addr = INADDR_BROADCAST;
                server.sin_port = htons((short)(sp->port & 0xFFFF));
                server.sin_port = htons((short)(sp->port & 0xFFFF));
                bytes = sendto(sp->sock, buf, toWrite, 0,
                bytes = sendto(sp->sock, buf, toWrite, 0,
                        (struct sockaddr*) &server, sizeof(server));
                        (struct sockaddr*) &server, sizeof(server));
        } else {
        } else {
                bytes = send(sp->sock, buf, toWrite, 0);
                bytes = send(sp->sock, buf, toWrite, 0);
        }
        }
 
 
        if (bytes == 0 && bytes != toWrite) {
        if (bytes == 0 && bytes != toWrite) {
                *errCode = EWOULDBLOCK;
                *errCode = EWOULDBLOCK;
                return -1;
                return -1;
        }
        }
 
 
        if (bytes < 0) {
        if (bytes < 0) {
                *errCode = socketGetError();
                *errCode = socketGetError();
        }
        }
        return bytes;
        return bytes;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Return TRUE if there is a socket with an event ready to process,
 *      Return TRUE if there is a socket with an event ready to process,
 */
 */
 
 
int socketReady()
int socketReady()
{
{
        socket_t        *sp;
        socket_t        *sp;
        int                     i;
        int                     i;
 
 
        for (i = 0; i < socketMax; i++) {
        for (i = 0; i < socketMax; i++) {
                if ((sp = socketList[i]) == NULL) {
                if ((sp = socketList[i]) == NULL) {
                        continue;
                        continue;
                }
                }
                if (sp->readyMask & sp->interestMask) {
                if (sp->readyMask & sp->interestMask) {
                        return 1;
                        return 1;
                }
                }
        }
        }
        return 0;
        return 0;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Wait for a handle to become readable or writable and return a number of
 *      Wait for a handle to become readable or writable and return a number of
 *      noticed events.
 *      noticed events.
 */
 */
 
 
int socketSelect()
int socketSelect()
{
{
        socket_t        *sp;
        socket_t        *sp;
        fd_mask         *readFds, *writeFds, *exceptFds;
        fd_mask         *readFds, *writeFds, *exceptFds;
        int             sid, len, nwords, index, bit, nEvents;
        int             sid, len, nwords, index, bit, nEvents;
 
 
/*
/*
 *      Allocate and zero the select masks
 *      Allocate and zero the select masks
 */
 */
        nwords = (socketHighestFd + NFDBITS - 1) / NFDBITS;
        nwords = (socketHighestFd + NFDBITS - 1) / NFDBITS;
        len = nwords * sizeof(int);
        len = nwords * sizeof(int);
 
 
        readFds = balloc(B_L, len);
        readFds = balloc(B_L, len);
        memset(readFds, 0, len);
        memset(readFds, 0, len);
        writeFds = balloc(B_L, len);
        writeFds = balloc(B_L, len);
        memset(writeFds, 0, len);
        memset(writeFds, 0, len);
        exceptFds = balloc(B_L, len);
        exceptFds = balloc(B_L, len);
        memset(exceptFds, 0, len);
        memset(exceptFds, 0, len);
 
 
/*
/*
 *      Set the select event masks for events to watch
 *      Set the select event masks for events to watch
 */
 */
        for (sid = 0; sid < socketMax; sid++) {
        for (sid = 0; sid < socketMax; sid++) {
                if ((sp = socketList[sid]) == NULL) {
                if ((sp = socketList[sid]) == NULL) {
                        continue;
                        continue;
                }
                }
                a_assert(sp);
                a_assert(sp);
 
 
/*
/*
 *              Initialize the ready masks and compute the mask offsets.
 *              Initialize the ready masks and compute the mask offsets.
 */
 */
                index = sp->sock / (NBBY * sizeof(fd_mask));
                index = sp->sock / (NBBY * sizeof(fd_mask));
                bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
                bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
 
 
/*
/*
 *              Set the appropriate bit in the ready masks for the sp->sock.
 *              Set the appropriate bit in the ready masks for the sp->sock.
 */
 */
                if (sp->interestMask & SOCKET_READABLE) {
                if (sp->interestMask & SOCKET_READABLE) {
                        readFds[index] |= bit;
                        readFds[index] |= bit;
                }
                }
                if (sp->interestMask & SOCKET_WRITABLE) {
                if (sp->interestMask & SOCKET_WRITABLE) {
                        writeFds[index] |= bit;
                        writeFds[index] |= bit;
                }
                }
                if (sp->interestMask & SOCKET_EXCEPTION) {
                if (sp->interestMask & SOCKET_EXCEPTION) {
                        exceptFds[index] |= bit;
                        exceptFds[index] |= bit;
                }
                }
        }
        }
 
 
/*
/*
 *      Wait for the event or a timeout.
 *      Wait for the event or a timeout.
 */
 */
        nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
        nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
                (fd_set *) writeFds, (fd_set *) exceptFds, NULL);
                (fd_set *) writeFds, (fd_set *) exceptFds, NULL);
        if (nEvents > 0) {
        if (nEvents > 0) {
                for (sid = 0; sid < socketMax; sid++) {
                for (sid = 0; sid < socketMax; sid++) {
                        if ((sp = socketList[sid]) == NULL) {
                        if ((sp = socketList[sid]) == NULL) {
                                continue;
                                continue;
                        }
                        }
 
 
                        index = sp->sock / (NBBY * sizeof(fd_mask));
                        index = sp->sock / (NBBY * sizeof(fd_mask));
                        bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
                        bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
 
 
                        if (readFds[index] & bit) {
                        if (readFds[index] & bit) {
                                sp->readyMask |= SOCKET_READABLE;
                                sp->readyMask |= SOCKET_READABLE;
                        }
                        }
                        if (writeFds[index] & bit) {
                        if (writeFds[index] & bit) {
                                sp->readyMask |= SOCKET_WRITABLE;
                                sp->readyMask |= SOCKET_WRITABLE;
                        }
                        }
                        if (exceptFds[index] & bit) {
                        if (exceptFds[index] & bit) {
                                sp->readyMask |= SOCKET_EXCEPTION;
                                sp->readyMask |= SOCKET_EXCEPTION;
                        }
                        }
                }
                }
        }
        }
 
 
        bfree(B_L, readFds);
        bfree(B_L, readFds);
        bfree(B_L, writeFds);
        bfree(B_L, writeFds);
        bfree(B_L, exceptFds);
        bfree(B_L, exceptFds);
 
 
        return nEvents;
        return nEvents;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Process socket events
 *      Process socket events
 */
 */
 
 
void socketProcess()
void socketProcess()
{
{
        socket_t        *sp;
        socket_t        *sp;
        int                     sid;
        int                     sid;
 
 
/*
/*
 *      Process each socket
 *      Process each socket
 */
 */
        for (sid = 0; sid < socketMax; sid++) {
        for (sid = 0; sid < socketMax; sid++) {
                if ((sp = socketList[sid]) == NULL) {
                if ((sp = socketList[sid]) == NULL) {
                        continue;
                        continue;
                }
                }
                if ((sp->readyMask & sp->interestMask) ||
                if ((sp->readyMask & sp->interestMask) ||
                                ((sp->interestMask & SOCKET_READABLE) &&
                                ((sp->interestMask & SOCKET_READABLE) &&
                                socketInputBuffered(sid))) {
                                socketInputBuffered(sid))) {
                        socketDoEvent(sp);
                        socketDoEvent(sp);
                }
                }
        }
        }
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Process and event on the event queue
 *      Process and event on the event queue
 */
 */
 
 
static int socketDoEvent(socket_t *sp)
static int socketDoEvent(socket_t *sp)
{
{
        ringq_t*                rq;
        ringq_t*                rq;
        int                     sid;
        int                     sid;
 
 
        a_assert(sp);
        a_assert(sp);
 
 
    sid = sp->sid;
    sid = sp->sid;
        if (sp->readyMask & SOCKET_READABLE) {
        if (sp->readyMask & SOCKET_READABLE) {
                if (sp->flags & SOCKET_LISTENING) {
                if (sp->flags & SOCKET_LISTENING) {
                        socketAccept(sp);
                        socketAccept(sp);
                        sp->readyMask = 0;
                        sp->readyMask = 0;
                        return 1;
                        return 1;
                }
                }
        } else {
        } else {
/*
/*
 *              If there is still read data in the buffers, trigger the read handler
 *              If there is still read data in the buffers, trigger the read handler
 *              NOTE: this may busy spin if the read handler doesn't read the data
 *              NOTE: this may busy spin if the read handler doesn't read the data
 */
 */
                if (sp->interestMask & SOCKET_READABLE && socketInputBuffered(sid)) {
                if (sp->interestMask & SOCKET_READABLE && socketInputBuffered(sid)) {
                        sp->readyMask |= SOCKET_READABLE;
                        sp->readyMask |= SOCKET_READABLE;
                }
                }
        }
        }
 
 
 
 
/*
/*
 *      If now writable and flushing in the background, continue flushing
 *      If now writable and flushing in the background, continue flushing
 */
 */
        if (sp->readyMask & SOCKET_WRITABLE) {
        if (sp->readyMask & SOCKET_WRITABLE) {
                if (sp->flags & SOCKET_FLUSHING) {
                if (sp->flags & SOCKET_FLUSHING) {
                        rq = &sp->outBuf;
                        rq = &sp->outBuf;
                        if (ringqLen(rq) > 0) {
                        if (ringqLen(rq) > 0) {
                                socketFlush(sp->sid, 0);
                                socketFlush(sp->sid, 0);
                        } else {
                        } else {
                                sp->flags &= ~SOCKET_FLUSHING;
                                sp->flags &= ~SOCKET_FLUSHING;
                        }
                        }
                }
                }
        }
        }
 
 
/*
/*
 *      Now invoke the users socket handler. NOTE: the handler may delete the
 *      Now invoke the users socket handler. NOTE: the handler may delete the
 *      socket, so we must be very careful after calling the handler.
 *      socket, so we must be very careful after calling the handler.
 */
 */
        if (sp->handler && (sp->interestMask & sp->readyMask)) {
        if (sp->handler && (sp->interestMask & sp->readyMask)) {
                (sp->handler)(sid, sp->interestMask & sp->readyMask,
                (sp->handler)(sid, sp->interestMask & sp->readyMask,
                        sp->handler_data);
                        sp->handler_data);
/*
/*
 *              Make sure socket pointer is still valid, then set the readyMask
 *              Make sure socket pointer is still valid, then set the readyMask
 *              to 0.
 *              to 0.
 */
 */
                if (socketPtr(sid)) {
                if (socketPtr(sid)) {
                        sp->readyMask = 0;
                        sp->readyMask = 0;
                }
                }
        }
        }
        return 1;
        return 1;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Allocate a new socket structure
 *      Allocate a new socket structure
 */
 */
 
 
static int socketAlloc(char* host, int port, socketAccept_t accept, int flags)
static int socketAlloc(char* host, int port, socketAccept_t accept, int flags)
{
{
        socket_t        *sp;
        socket_t        *sp;
        int                     sid;
        int                     sid;
 
 
        if ((sid = hAlloc((void***) &socketList)) < 0) {
        if ((sid = hAlloc((void***) &socketList)) < 0) {
                return -1;
                return -1;
        }
        }
        if ((sp = (socket_t*) balloc(B_L, sizeof(socket_t))) == NULL) {
        if ((sp = (socket_t*) balloc(B_L, sizeof(socket_t))) == NULL) {
                hFree((void***) &socket, sid);
                hFree((void***) &socket, sid);
                return -1;
                return -1;
        }
        }
        memset(sp, 0, sizeof(socket_t));
        memset(sp, 0, sizeof(socket_t));
        socketList[sid] = sp;
        socketList[sid] = sp;
        if (sid >= socketMax)
        if (sid >= socketMax)
                socketMax = sid + 1;
                socketMax = sid + 1;
 
 
        sp->sid = sid;
        sp->sid = sid;
        sp->accept = accept;
        sp->accept = accept;
        sp->port = port;
        sp->port = port;
        sp->flags = flags;
        sp->flags = flags;
 
 
        if (host) {
        if (host) {
                strncpy(sp->host, host, sizeof(sp->host));
                strncpy(sp->host, host, sizeof(sp->host));
        }
        }
 
 
        ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
        ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
        ringqOpen(&sp->outBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
        ringqOpen(&sp->outBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
        ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1);
        ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1);
 
 
        return sid;
        return sid;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Free a socket structure
 *      Free a socket structure
 */
 */
 
 
static void socketFree(int sid)
static void socketFree(int sid)
{
{
        socket_t*       sp;
        socket_t*       sp;
        int                     i;
        int                     i;
 
 
        if ((sp = socketPtr(sid)) == NULL) {
        if ((sp = socketPtr(sid)) == NULL) {
                return;
                return;
        }
        }
        if (sp->sock >= 0) {
        if (sp->sock >= 0) {
                close(sp->sock);
                close(sp->sock);
        }
        }
 
 
        ringqClose(&sp->inBuf);
        ringqClose(&sp->inBuf);
        ringqClose(&sp->outBuf);
        ringqClose(&sp->outBuf);
        ringqClose(&sp->lineBuf);
        ringqClose(&sp->lineBuf);
 
 
        bfree(B_L, sp);
        bfree(B_L, sp);
        socketMax = hFree((void***) &socketList, sid);
        socketMax = hFree((void***) &socketList, sid);
 
 
/*
/*
 *      Calculate the new highest socket number
 *      Calculate the new highest socket number
 */
 */
        socketHighestFd = -1;
        socketHighestFd = -1;
        for (i = 0; i < socketMax; i++) {
        for (i = 0; i < socketMax; i++) {
                if ((sp = socketList[i]) == NULL) {
                if ((sp = socketList[i]) == NULL) {
                        continue;
                        continue;
                }
                }
                socketHighestFd = max(socketHighestFd, sp->sock);
                socketHighestFd = max(socketHighestFd, sp->sock);
        }
        }
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Validate a socket handle
 *      Validate a socket handle
 */
 */
 
 
static socket_t* socketPtr(int sid)
static socket_t* socketPtr(int sid)
{
{
        if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
        if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
                a_assert(NULL);
                a_assert(NULL);
                return NULL;
                return NULL;
        }
        }
 
 
        a_assert(socketList[sid]);
        a_assert(socketList[sid]);
        return socketList[sid];
        return socketList[sid];
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Get the operating system error code
 *      Get the operating system error code
 */
 */
 
 
static int socketGetError()
static int socketGetError()
{
{
        return errno;
        return errno;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
 *      Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
 */
 */
 
 
static int socketWaitForEvent(socket_t* sp, int interestMask, int* errCode)
static int socketWaitForEvent(socket_t* sp, int interestMask, int* errCode)
{
{
        a_assert(sp);
        a_assert(sp);
 
 
        while (socketSelect()) {
        while (socketSelect()) {
                if (sp->readyMask & interestMask) {
                if (sp->readyMask & interestMask) {
                        break;
                        break;
                }
                }
        }
        }
        if (sp->readyMask & SOCKET_EXCEPTION) {
        if (sp->readyMask & SOCKET_EXCEPTION) {
                return -1;
                return -1;
        } else if (sp->readyMask & SOCKET_WRITABLE) {
        } else if (sp->readyMask & SOCKET_WRITABLE) {
                return 0;
                return 0;
        } else {
        } else {
                *errCode = errno = EWOULDBLOCK;
                *errCode = errno = EWOULDBLOCK;
                return -1;
                return -1;
        }
        }
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Put the socket into non-blocking mode
 *      Put the socket into non-blocking mode
 */
 */
 
 
static int socketNonBlock(socket_t *sp)
static int socketNonBlock(socket_t *sp)
{
{
        int             flags;
        int             flags;
 
 
        flags = fcntl(sp->sock, F_GETFL) | O_NONBLOCK;
        flags = fcntl(sp->sock, F_GETFL) | O_NONBLOCK;
        if (fcntl(sp->sock, F_SETFL, flags) < 0) {
        if (fcntl(sp->sock, F_SETFL, flags) < 0) {
                return -1;
                return -1;
    }
    }
        return 0;
        return 0;
}
}
 
 
/******************************************************************************/
/******************************************************************************/
/*
/*
 *      Duplicate stdin and stdout
 *      Duplicate stdin and stdout
 */
 */
 
 
int DuplicateStdFile (int sid)
int DuplicateStdFile (int sid)
{
{
  if (0 != dup2(socketList[sid]->sock, 0)  || 1 != dup2(socketList[sid]->sock, 1))
  if (0 != dup2(socketList[sid]->sock, 0)  || 1 != dup2(socketList[sid]->sock, 1))
    return -1;
    return -1;
 
 
  return 0;
  return 0;
 
 
}
}
 
 

powered by: WebSVN 2.1.0

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