ncbi_socket.c

来自「ncbi源码」· C语言 代码 · 共 1,815 行 · 第 1/5 页

C
1,815
字号
/* * Please note the following implementation details: * * 1. w_buf is used for stream sockets to keep initial data segment *    that has to be sent upon the connection establishment. * * 2. eof is used differently for stream and datagram sockets: *    =1 for stream sockets means that read had hit EOF; *    =1 for datagram sockets means that the message in w_buf is complete. * * 3. r_status keeps completion code of the last low-level read call; *    however, eIO_Closed is there when the socket is shut down for reading; *    see the table below for full details on stream sockets. * * 4. w_status keeps completion code of the last low-level write call; *    however, eIO_Closed is there when the socket is shut down for writing. * * 5. The following table depicts r_status and eof combinations and their *    meanings for stream sockets: * -------------------------------+-------------------------------------------- *              Field             | * ---------------+---------------+                  Meaning * sock->r_status |   sock->eof   |           (stream sockets only) * ---------------+---------------+-------------------------------------------- * eIO_Closed     |       0       |  Socket shut down for reading * eIO_Closed     |       1       |  Read severely failed * not eIO_Closed |       0       |  Read completed with r_status error * not eIO_Closed |       1       |  Read hit EOF (and later r_status) * ---------------+---------------+-------------------------------------------- *//* Globals: *//* Flag to indicate whether the API has been initialized */static int/*bool*/ s_Initialized = 0/*false*/;/* SOCK counter */static unsigned int s_ID_Counter = 0;/* Read-while-writing switch */static ESwitch s_ReadOnWrite = eOff;        /* no read-on-write by default   *//* Reuse address flag for newly created stream sockets */static int/*bool*/ s_ReuseAddress = 0;      /* off by default                *//* I/O restart on signals */static ESwitch s_InterruptOnSignal = eOff;  /* restart I/O by default        *//* Data/event logging */static ESwitch s_Log = eOff;                /* no logging by default         *//* Select restart timeout */static const struct timeval* s_SelectTimeout = 0; /* =0 (disabled) by default*//* Flag to indicate whether API should mask SIGPIPE (during initialization)  */#ifdef NCBI_OS_UNIXstatic int/*bool*/ s_AllowSigPipe = 0/*false - mask SIGPIPE out*/;#endif /*NCBI_OS_UNIX*//****************************************************************************** *   Error reporting */static const char* s_StrError(int error){    static struct {        int         errnum;        const char* errtxt;    } errmap[] = {#ifdef NCBI_OS_MSWIN        {WSAEINTR,  "Interrupted system call"},        {WSAEBADF,  "Bad file number"},        {WSAEACCES, "Access denied"},        {WSAEFAULT, "Segmentation fault"},        {WSAEINVAL, "Invalid agrument"},        {WSAEMFILE, "Too many open files"},        /*         * Windows Sockets definitions of regular Berkeley error constants         */        {WSAEWOULDBLOCK,     "Resource temporarily unavailable"},        {WSAEINPROGRESS,     "Operation now in progress"},        {WSAEALREADY,        "Operation already in progress"},        {WSAENOTSOCK,        "Not a socket"},        {WSAEDESTADDRREQ,    "Destination address required"},        {WSAEMSGSIZE,        "Invalid message size"},        {WSAEPROTOTYPE,      "Wrong protocol type"},        {WSAENOPROTOOPT,     "Bad protocol option"},        {WSAEPROTONOSUPPORT, "Protocol not supported"},        {WSAESOCKTNOSUPPORT, "Socket type not supported"},        {WSAEOPNOTSUPP,      "Operation not supported"},        {WSAEPFNOSUPPORT,    "Protocol family not supported"},        {WSAEAFNOSUPPORT,    "Address family not supported"},        {WSAEADDRINUSE,      "Address already in use"},        {WSAEADDRNOTAVAIL,   "Cannot assign requested address"},        {WSAENETDOWN,        "Network is down"},        {WSAENETUNREACH,     "Network is unreachable"},        {WSAENETRESET,       "Connection dropped on network reset"},        {WSAECONNABORTED,    "Software caused connection abort"},        {WSAECONNRESET,      "Connection reset by peer"},        {WSAENOBUFS,         "No buffer space available"},        {WSAEISCONN,         "Socket is already connected"},        {WSAENOTCONN,        "Socket is not connected"},        {WSAESHUTDOWN,       "Cannot send after socket shutdown"},        {WSAETOOMANYREFS,    "Too many references"},        {WSAETIMEDOUT,       "Operation timed out"},        {WSAECONNREFUSED,    "Connection refused"},        {WSAELOOP,           "Infinite loop"},        {WSAENAMETOOLONG,    "Name too long"},        {WSAEHOSTDOWN,       "Host is down"},        {WSAEHOSTUNREACH,    "Host unreachable"},        {WSAENOTEMPTY,       "Not empty"},        {WSAEPROCLIM,        "Too many processes"},        {WSAEUSERS,          "Too many users"},        {WSAEDQUOT,          "Quota exceeded"},        {WSAESTALE,          "Stale descriptor"},        {WSAEREMOTE,         "Remote error"},        /*         * Extended Windows Sockets error constant definitions         */        {WSASYSNOTREADY,         "Network subsystem is unavailable"},        {WSAVERNOTSUPPORTED,     "Winsock.dll version out of range"},        {WSANOTINITIALISED,      "Not yet initialized"},        {WSAEDISCON,             "Graceful shutdown in progress"},        {WSAENOMORE,             "No more retries"},        {WSAECANCELLED,          "Cancelled"},        {WSAEINVALIDPROCTABLE,   "Invalid procedure table"},        {WSAEINVALIDPROVIDER,    "Invalid provider version number"},        {WSAEPROVIDERFAILEDINIT, "Cannot init provider"},        {WSASYSCALLFAILURE,      "System call failed"},        {WSASERVICE_NOT_FOUND,   "Service not found"},        {WSATYPE_NOT_FOUND,      "Class type not found"},        {WSA_E_NO_MORE,          "WSA_E_NO_MORE"},        {WSA_E_CANCELLED,        "WSA_E_CANCELLED"},        {WSAEREFUSED,            "Refused"},#endif /*NCBI_OS_MSWIN*/#ifdef NCBI_OS_MSWIN#  define EAI_BASE 0#else#  define EAI_BASE 100000#endif /*NCBI_OS_MSWIN*/#ifdef EAI_ADDRFAMILY        {EAI_ADDRFAMILY + EAI_BASE,                                 "Address family not supported"},#endif /*EAI_ADDRFAMILY*/#ifdef EAI_AGAIN        {EAI_AGAIN + EAI_BASE,                                 "Temporary failure in name resolution"},#endif /*EAI_AGAIN*/#ifdef EAI_BADFLAGS        {EAI_BADFLAGS + EAI_BASE,                                 "Invalid value for lookup flags"},#endif /*EAI_BADFLAGS*/#ifdef EAI_FAIL        {EAI_FAIL + EAI_BASE,                                 "Non-recoverable failure in name resolution"},#endif /*EAI_FAIL*/#ifdef EAI_FAMILY        {EAI_FAMILY + EAI_BASE,                                 "Address family not supported"},#endif /*EAI_FAMILY*/#ifdef EAI_MEMORY        {EAI_MEMORY + EAI_BASE,                                 "Memory allocation failure"},#endif /*EAI_MEMORY*/#ifdef EAI_NODATA        {EAI_NODATA + EAI_BASE,                                 "No address associated with nodename"},#endif /*EAI_NODATA*/#ifdef EAI_NONAME        {EAI_NONAME + EAI_BASE,                                 "Host/service name not known"},#endif /*EAI_NONAME*/#ifdef EAI_SERVICE        {EAI_SERVICE + EAI_BASE,                                 "Service name not supported for socket type"},#endif /*EAI_SERVICE*/#ifdef EAI_SOCKTYPE        {EAI_SOCKTYPE + EAI_BASE,                                 "Socket type not supported"},#endif /*EAI_SOCKTYPE*/#ifdef NCBI_OS_MSWIN#  define DNS_BASE 0#else#  define DNS_BASE 200000#endif /*NCBI_OS_MSWIN*/#ifdef HOST_NOT_FOUND        {HOST_NOT_FOUND + DNS_BASE,                                 "Host not found"},#endif /*HOST_NOT_FOUND*/#ifdef TRY_AGAIN        {TRY_AGAIN + DNS_BASE,                                 "DNS server failure"},#endif /*TRY_AGAIN*/#ifdef NO_RECOVERY        {NO_RECOVERY + DNS_BASE,                                 "Unrecoverable DNS error"},#endif /*NO_RECOVERY*/#ifdef NO_DATA        {NO_DATA + DNS_BASE,                                 "No DNS data of requested type"},#endif /*NO_DATA*/#ifdef NO_ADDRESS        {NO_ADDRESS + DNS_BASE,                                 "No address record found in DNS"},#endif /*NO_ADDRESS*/        /* Last dummy entry - must present */        {0, 0}    };    size_t i, n = sizeof(errmap)/sizeof(errmap[0]) - 1/*dummy entry*/;    /* always called on error, so get error number here if not having already*/    if ( !error )        error = errno;    for (i = 0; i < n; i++) {        if (errmap[i].errnum == error)            return errmap[i].errtxt;    }    return strerror(error);}/****************************************************************************** *   Data Logging */static const char* s_ID(const SOCK sock, char* buf){    const char* sname;    if ( !sock )        return "";    sname = IS_LISTENING(sock) ? "LSOCK" : "SOCK";    if (sock->sock == SOCK_INVALID)        sprintf(buf, "%s#%u[?]: ",  sname, sock->id);    else        sprintf(buf, "%s#%u[%u]: ", sname, sock->id, (unsigned int)sock->sock);    return buf;}/* Put socket description to the message, then log the transferred data */static void s_DoLog(const SOCK  sock, EIO_Event event, const void* data, size_t    size,  const struct sockaddr* sa){    char head[128];    char tail[128];    char _id[32];    if ( !CORE_GetLOG() )        return;    assert(sock);    switch (event) {    case eIO_Open:        if (sock->type == eSOCK_Datagram) {            if ( !sa ) {                strcpy(head, "Datagram socket created");                *tail = 0;            } else {                const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;                if ( !data ) {                    strcpy(head, "Datagram socket bound to port :");                    sprintf(tail, "%hu", ntohs(sin->sin_port));                } else {                    strcpy(head, "Datagram socket connected to ");                    HostPortToString(sin->sin_addr.s_addr,ntohs(sin->sin_port),                                     tail, sizeof(tail));                }            }        } else {            if (sock->type == eSOCK_ClientSide)                strcpy(head, "Connecting to ");            else if ( data )                strcpy(head, "Connected to ");            else                strcpy(head, "Accepted from ");            if (sa->sa_family == AF_INET) {                const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;                HostPortToString(sin->sin_addr.s_addr, ntohs(sin->sin_port),                                 tail, sizeof(tail));            }#ifdef NCBI_OS_UNIX            else if (sa->sa_family == AF_UNIX) {                const struct sockaddr_un* un = (const struct sockaddr_un*) sa;                strncpy0(tail, un->sun_path, sizeof(tail) - 1);            }#endif /*NCBI_OS_UNIX*/            else                strcpy(tail, "???");        }        CORE_LOGF(eLOG_Trace, ("%s%s%s", s_ID(sock, _id), head, tail));        break;    case eIO_Read:    case eIO_Write:        if (sock->type == eSOCK_Datagram) {            const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;            assert(sa && sa->sa_family == AF_INET);            HostPortToString(sin->sin_addr.s_addr, ntohs(sin->sin_port),                             tail, sizeof(tail));            sprintf(tail + strlen(tail), ", msg# %u",                    (unsigned)(event == eIO_Read ? sock->n_in : sock->n_out));        } else {            assert(sa == 0);            *tail = 0;        }        sprintf(head, "%s%s%s at offset %lu%s%s", s_ID(sock, _id),                event == eIO_Read                ? (sock->type != eSOCK_Datagram  &&  !size                   ? (data ? "EOF hit" : SOCK_STRERROR(SOCK_ERRNO))                   : "Read")                : (sock->type != eSOCK_Datagram  &&  !size                   ? SOCK_STRERROR(SOCK_ERRNO) : "Written"),                sock->type == eSOCK_Datagram  ||  size ? "" :                (event == eIO_Read ? " while reading" : " while writing"),                (unsigned long) (event == eIO_Read                                 ? sock->n_read : sock->n_written),                sa ? (event == eIO_Read ? " from " : " to ") : "", tail);        CORE_DATA(data, size, head);        break;    case eIO_Close:        {{            int n = sprintf(head, "%lu byte%s",                            (unsigned long) sock->n_written,                            sock->n_written == 1 ? "" : "s");            if (sock->type == eSOCK_Datagram  ||                sock->n_out != sock->n_written) {                sprintf(head + n, "/%lu %s%s",                        (unsigned long) sock->n_out,                        sock->type == eSOCK_Datagram ? "msg" : "total byte",                        sock->n_out == 1 ? "" : "s");            }        }}        {{            int n = sprintf(tail, "%lu byte%s",                            (unsigned long) sock->n_read,                            sock->n_read == 1 ? "" : "s");            if (sock->type == eSOCK_Datagram  ||                sock->n_in != sock->n_read) {                sprintf(tail + n, "/%lu %s%s",                        (unsigned long) sock->n_in,                        sock->type == eSOCK_Datagram ? "msg" : "total byte",                        sock->n_in == 1 ? "" : "s");            }        }}        CORE_LOGF(eLOG_Trace, ("%s%s (out: %s, in: %s)", s_ID(sock, _id),                               sock->type == eSOCK_ServerSideKeep                               ? "Leaving" : "Closing", head,tail));        break;    default:        CORE_LOGF(eLOG_Error, ("%s[SOCK::s_DoLog]  Invalid event %u",                               s_ID(sock, _id), (unsigned int) event));

⌨️ 快捷键说明

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