⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket_unix.c

📁 一个很好用的解析
💻 C
字号:
/*=============================================================================                                 socket_unix.c===============================================================================  This is the implementation of TSocket for a standard Unix (POSIX)  stream socket -- what you create with a socket() C library call.=============================================================================*/#include "xmlrpc_config.h"#include <stdlib.h>#include <assert.h>#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <netdb.h>#include <arpa/inet.h>#include <errno.h>#if HAVE_SYS_FILIO_H  #include <sys/filio.h>#endif#if HAVE_SYS_IOCTL_H  #include <sys/ioctl.h>#endif#include "xmlrpc-c/util_int.h"#include "mallocvar.h"#include "trace.h"#include "socket.h"#include "xmlrpc-c/abyss.h"#include "socket_unix.h"struct socketUnix {/*----------------------------------------------------------------------------   The properties/state of a TSocket unique to a Unix TSocket.-----------------------------------------------------------------------------*/    int fd;        /* File descriptor of the POSIX socket (such as is created by           socket() in the C library) on which the TSocket is based.        */    abyss_bool userSuppliedFd;        /* The file descriptor and associated POSIX socket belong to the           user; we did not create it.        */};voidSocketUnixInit(abyss_bool * const succeededP) {    *succeededP = TRUE;}voidSocketUnixTerm(void) {}static SocketDestroyImpl            socketDestroy;static SocketWriteImpl              socketWrite;static SocketReadImpl               socketRead;static SocketConnectImpl            socketConnect;static SocketBindImpl               socketBind;static SocketListenImpl             socketListen;static SocketAcceptImpl             socketAccept;static SocketErrorImpl              socketError;static SocketWaitImpl               socketWait;static SocketAvailableReadBytesImpl socketAvailableReadBytes;static SocketGetPeerNameImpl        socketGetPeerName;static struct TSocketVtbl const vtbl = {    &socketDestroy,    &socketWrite,    &socketRead,    &socketConnect,    &socketBind,    &socketListen,    &socketAccept,    &socketError,    &socketWait,    &socketAvailableReadBytes,    &socketGetPeerName};voidSocketUnixCreate(TSocket ** const socketPP) {    struct socketUnix * socketUnixP;    MALLOCVAR(socketUnixP);    if (socketUnixP) {        int rc;        rc = socket(AF_INET, SOCK_STREAM, 0);        if (rc < 0)            *socketPP = NULL;        else {            socketUnixP->fd = rc;            socketUnixP->userSuppliedFd = FALSE;                        {                int32_t n = 1;                int rc;                rc = setsockopt(socketUnixP->fd, SOL_SOCKET, SO_REUSEADDR,                                (char*)&n, sizeof(n));                if (rc < 0)                    *socketPP = NULL;                else                    SocketCreate(&vtbl, socketUnixP, socketPP);            }            if (!*socketPP)                close(socketUnixP->fd);        }        if (!*socketPP)            free(socketUnixP);    } else        *socketPP = NULL;}voidSocketUnixCreateFd(int        const fd,                   TSocket ** const socketPP) {    struct socketUnix * socketUnixP;    MALLOCVAR(socketUnixP);    if (socketUnixP) {        socketUnixP->fd = fd;        socketUnixP->userSuppliedFd = TRUE;        SocketCreate(&vtbl, socketUnixP, socketPP);        if (!*socketPP)            free(socketUnixP);    } else        *socketPP = NULL;}static voidsocketDestroy(TSocket * const socketP) {    struct socketUnix * const socketUnixP = socketP->implP;    if (!socketUnixP->userSuppliedFd)        close(socketUnixP->fd);    free(socketUnixP);}static voidsocketWrite(TSocket *             const socketP,            const unsigned char * const buffer,            uint32_t              const len,            abyss_bool *          const failedP) {    struct socketUnix * const socketUnixP = socketP->implP;    size_t bytesLeft;    abyss_bool error;    assert(sizeof(size_t) >= sizeof(len));    for (bytesLeft = len, error = FALSE;         bytesLeft > 0 && !error;        ) {        size_t const maxSend = (size_t)(-1) >> 1;        ssize_t rc;                rc = send(socketUnixP->fd, &buffer[len-bytesLeft],                  MIN(maxSend, bytesLeft), 0);        if (SocketTraceIsActive) {            if (rc < 0)                fprintf(stderr, "Abyss socket: send() failed.  errno=%d (%s)",                        errno, strerror(errno));            else if (rc == 0)                fprintf(stderr, "Abyss socket: send() failed.  "                        "Socket closed.\n");            else                fprintf(stderr, "Abyss socket: sent %u bytes: '%.*s'\n",                        -rc, -rc, &buffer[len-bytesLeft]);        }        if (rc <= 0)            /* 0 means connection closed; < 0 means severe error */            error = TRUE;        else            bytesLeft -= rc;    }    *failedP = error;}static uint32_tsocketRead(TSocket * const socketP,            char *    const buffer,            uint32_t  const len) {    struct socketUnix * const socketUnixP = socketP->implP;    int rc;    rc = recv(socketUnixP->fd, buffer, len, 0);    if (SocketTraceIsActive) {        if (rc < 0)            fprintf(stderr, "Abyss socket: recv() failed.  errno=%d (%s)",                    errno, strerror(errno));        else             fprintf(stderr, "Abyss socket: read %u bytes: '%.*s'\n",                    len, (int)len, buffer);    }    return rc;}abyss_boolsocketConnect(TSocket * const socketP,              TIPAddr * const addrP,              uint16_t  const portNumber) {    struct socketUnix * const socketUnixP = socketP->implP;    struct sockaddr_in name;    int rc;    name.sin_family = AF_INET;    name.sin_port = htons(portNumber);    name.sin_addr = *addrP;    rc = connect(socketUnixP->fd, (struct sockaddr *)&name, sizeof(name));    return rc != -1;}abyss_boolsocketBind(TSocket * const socketP,           TIPAddr * const addrP,           uint16_t  const portNumber) {    struct socketUnix * const socketUnixP = socketP->implP;    struct sockaddr_in name;    int rc;    name.sin_family = AF_INET;    name.sin_port   = htons(portNumber);    if (addrP)        name.sin_addr = *addrP;    else        name.sin_addr.s_addr = INADDR_ANY;    rc = bind(socketUnixP->fd, (struct sockaddr *)&name, sizeof(name));    return (rc != -1);}abyss_boolsocketListen(TSocket * const socketP,             uint32_t  const backlog) {    struct socketUnix * const socketUnixP = socketP->implP;    int32_t const minus1 = -1;    int rc;    /* Disable the Nagle algorithm to make persistant connections faster */    setsockopt(socketUnixP->fd, IPPROTO_TCP,TCP_NODELAY,               &minus1, sizeof(minus1));    rc = listen(socketUnixP->fd, backlog);    return (rc != -1);}static voidsocketAccept(TSocket *    const listenSocketP,             abyss_bool * const connectedP,             abyss_bool * const failedP,             TSocket **   const acceptedSocketPP,             TIPAddr *    const ipAddrP) {/*----------------------------------------------------------------------------   Accept a connection on the listening socket 'listenSocketP'.  Return as   *acceptedSocketPP the socket for the accepted connection.   If no connection is waiting on 'listenSocketP', wait until one is.   If we receive a signal while waiting, return immediately.   Return *connectedP true iff we accepted a connection.  Return   *failedP true iff we were unable to accept a connection for some   reason other than that we were interrupted.  Return both false if   our wait for a connection was interrupted by a signal.-----------------------------------------------------------------------------*/    struct socketUnix * const listenSocketUnixP = listenSocketP->implP;    abyss_bool connected, failed, interrupted;    connected  = FALSE;    failed      = FALSE;    interrupted = FALSE;    while (!connected && !failed && !interrupted) {        struct sockaddr_in sa;        socklen_t size = sizeof(sa);        int rc;        rc = accept(listenSocketUnixP->fd, (struct sockaddr *)&sa, &size);        if (rc >= 0) {            int const acceptedFd = rc;            struct socketUnix * acceptedSocketUnixP;            MALLOCVAR(acceptedSocketUnixP);            if (acceptedSocketUnixP) {                acceptedSocketUnixP->fd = acceptedFd;                acceptedSocketUnixP->userSuppliedFd = FALSE;                                SocketCreate(&vtbl, acceptedSocketUnixP, acceptedSocketPP);                if (!*acceptedSocketPP)                    failed = TRUE;                else {                    connected = TRUE;                    *ipAddrP = sa.sin_addr;                }                if (failed)                    free(acceptedSocketUnixP);            } else                failed = TRUE;            if (failed)                close(acceptedFd);        } else if (errno == EINTR)            interrupted = TRUE;        else            failed = TRUE;    }       *failedP    = failed;    *connectedP = connected;}static uint32_tsocketWait(TSocket *  const socketP,           abyss_bool const rd,           abyss_bool const wr,           uint32_t   const timems) {    struct socketUnix * const socketUnixP = socketP->implP;    fd_set rfds, wfds;    struct timeval tv;    FD_ZERO(&rfds);    FD_ZERO(&wfds);    if (rd)        FD_SET(socketUnixP->fd, &rfds);    if (wr)        FD_SET(socketUnixP->fd, &wfds);    tv.tv_sec  = timems / 1000;    tv.tv_usec = timems % 1000;    for (;;) {        int rc;        rc = select(socketUnixP->fd + 1, &rfds, &wfds, NULL,                    (timems == TIME_INFINITE ? NULL : &tv));        switch(rc) {           case 0: /* time out */            return 0;        case -1:  /* socket error */            if (errno == EINTR)                break;                        return 0;                    default:            if (FD_ISSET(socketUnixP->fd, &rfds))                return 1;            if (FD_ISSET(socketUnixP->fd, &wfds))                return 2;            return 0;        }    }}static uint32_tsocketAvailableReadBytes(TSocket * const socketP) {    struct socketUnix * const socketUnixP = socketP->implP;    uint32_t x;    int rc;    rc = ioctl(socketUnixP->fd, FIONREAD, &x);    return rc == 0 ? x : 0;}static voidsocketGetPeerName(TSocket *    const socketP,                  TIPAddr *    const ipAddrP,                  uint16_t *   const portNumberP,                  abyss_bool * const successP) {    struct socketUnix * const socketUnixP = socketP->implP;    socklen_t addrlen;    int rc;    struct sockaddr sockAddr;    addrlen = sizeof(sockAddr);        rc = getpeername(socketUnixP->fd, &sockAddr, &addrlen);    if (rc < 0) {        TraceMsg("getpeername() failed.  errno=%d (%s)",                 errno, strerror(errno));        *successP = FALSE;    } else {        if (addrlen != sizeof(sockAddr)) {            TraceMsg("getpeername() returned a socket address of the wrong "                     "size: %u.  Expected %u", addrlen, sizeof(sockAddr));            *successP = FALSE;        } else {            if (sockAddr.sa_family != AF_INET) {                TraceMsg("Socket does not use the Inet (IP) address "                         "family.  Instead it uses family %d",                         sockAddr.sa_family);                *successP = FALSE;            } else {                struct sockaddr_in * const sockAddrInP = (struct sockaddr_in *)                    &sockAddr;                *ipAddrP     = sockAddrInP->sin_addr;                *portNumberP = sockAddrInP->sin_port;                *successP = TRUE;            }        }    }}static uint32_tsocketError(TSocket * const socketP) {    if (socketP){} /* defeat compiler warning */    return errno;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -