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 + -
显示快捷键?