ncbi_socket.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:153k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbi_socket.c,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 18:45:25  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.145
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbi_socket.c,v 1000.4 2004/06/01 18:45:25 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Denis Vakatov
  35.  *
  36.  * File Description:
  37.  *   Plain portable TCP/IP socket API for:  UNIX, MS-Win, MacOS
  38.  *     [UNIX ]   -DNCBI_OS_UNIX     -lresolv -lsocket -lnsl
  39.  *     [MSWIN]   -DNCBI_OS_MSWIN    wsock32.lib
  40.  *     [MacOS]   -DNCBI_OS_MAC      NCSASOCK -- BSD-style socket emulation lib
  41.  *
  42.  */
  43. /* NCBI core headers
  44.  */
  45. #include "ncbi_ansi_ext.h"
  46. #include "ncbi_priv.h"
  47. /* The next header implicitly includes <connect/ncbi_socket.h> */
  48. #include <connect/ncbi_connutil.h>
  49. /* OS must be specified in the command-line ("-D....") or in the conf. header
  50.  */
  51. #if !defined(NCBI_OS_UNIX) && !defined(NCBI_OS_MSWIN) && !defined(NCBI_OS_MAC)
  52. #  error "Unknown OS, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN, NCBI_OS_MAC!"
  53. #endif /*supported platforms*/
  54. /* Uncomment these(or specify "-DHAVE_GETADDRINFO -DHAVE_GETNAMEINFO") only if:
  55.  * 0) you are compiling this outside of the NCBI C or C++ Toolkits
  56.  *    (USE_NCBICONF is not #define'd), and
  57.  * 1) your platform has "getaddrinfo()" and "getnameinfo()", and
  58.  * 2) you are going to use this API code in multi-thread application, and
  59.  * 3) "gethostbyname()" gets called somewhere else in your code
  60.  */
  61. /* #define HAVE_GETADDRINFO 1 */
  62. /* #define HAVE_GETNAMEINFO 1 */
  63. /* Uncomment this (or specify "-DHAVE_GETHOSTBY***_R=") only if:
  64.  * 0) you are compiling this outside of the NCBI C or C++ Toolkits
  65.  *    (USE_NCBICONF is not #define'd), and
  66.  * 1) your platform has "gethostbyname_r()" but not "getnameinfo()", and
  67.  * 2) you are going to use this API code in multi-thread application, and
  68.  * 3) "gethostbyname()" gets called somewhere else in your code
  69.  */
  70. /*   Solaris: */
  71. /* #define HAVE_GETHOSTBYNAME_R 5 */
  72. /* #define HAVE_GETHOSTBYADDR_R 7 */
  73. /*   Linux, IRIX: */
  74. /* #define HAVE_GETHOSTBYNAME_R 6 */
  75. /* #define HAVE_GETHOSTBYADDR_R 8 */
  76. /* Uncomment this (or specify "-DHAVE_SIN_LEN") only if:
  77.  * 0) you are compiling this outside of the NCBI C or C++ Toolkits
  78.  *    (USE_NCBICONF is not #define'd), and
  79.  * 1) on your platform, struct sockaddr_in contains a field called "sin_len"
  80.  */
  81. /* #define HAVE_SIN_LEN 1 */
  82. /* Platform-specific system headers
  83.  */
  84. #if defined(NCBI_OS_UNIX)
  85. #  include <sys/time.h>
  86. #  include <unistd.h>
  87. #  ifdef NCBI_COMPILER_MW_MSL
  88. #    include <ncbi_mslextras.h>
  89. #  else
  90. #    include <netdb.h>
  91. #  endif
  92. #  include <fcntl.h>
  93. #  include <sys/socket.h>
  94. #  include <netinet/in.h>
  95. #  if !defined(NCBI_OS_BEOS) && !defined(NCBI_COMPILER_MW_MSL)
  96. #    include <arpa/inet.h>
  97. #  endif /*NCBI_OS_BEOS*/
  98. #  include <signal.h>
  99. #  include <sys/un.h>
  100. #elif defined(NCBI_OS_MSWIN)
  101. #  ifndef COMP_METRO
  102. #    include <winsock2.h>
  103. #  else
  104. #    define SD_RECEIVE      0x00
  105. #    define SD_SEND         0x01
  106. #    define SD_BOTH         0x02
  107. #  endif
  108. #elif defined(NCBI_OS_MAC)
  109. #  include <unistd.h>
  110. #  include <sock_ext.h>
  111. #  include <netdb.h>
  112. #  include <s_types.h>
  113. #  include <s_socket.h>
  114. #  include <neti_in.h>
  115. #  include <a_inet.h>
  116. #  include <neterrno.h> /* missing error numbers on Mac */
  117. #else
  118. #  error "Unsupported platform, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN, NCBI_OS_MAC !!!"
  119. #endif /* platform-specific headers (for UNIX, MSWIN, MAC) */
  120. /* Portable standard C headers
  121.  */
  122. #include <errno.h>
  123. #include <stdlib.h>
  124. /******************************************************************************
  125.  *  TYPEDEFS & MACROS
  126.  */
  127. /* Minimal size of the data buffer chunk in the socket internal buffer(s) */
  128. #define SOCK_BUF_CHUNK_SIZE 4096
  129. /* Macro #def for the platform-dependent constants, error codes and functions
  130.  */
  131. #if defined(NCBI_OS_MSWIN)
  132. typedef SOCKET TSOCK_Handle;
  133. #  define SOCK_INVALID        INVALID_SOCKET
  134. #  define SOCK_ERRNO          WSAGetLastError()
  135. #  define SOCK_EINTR          WSAEINTR
  136. #  define SOCK_EWOULDBLOCK    WSAEWOULDBLOCK
  137. #  define SOCK_EADDRINUSE     WSAEADDRINUSE
  138. #  define SOCK_ECONNRESET     WSAECONNRESET
  139. #  define SOCK_EPIPE          WSAESHUTDOWN
  140. #  define SOCK_EAGAIN         WSAEINPROGRESS
  141. #  define SOCK_EINPROGRESS    WSAEINPROGRESS
  142. #  define SOCK_EALREADY       WSAEALREADY
  143. #  define SOCK_ENOTCONN       WSAENOTCONN
  144. #  define SOCK_ECONNABORTED   WSAECONNABORTED
  145. #  define SOCK_ECONNREFUSED   WSAECONNREFUSED
  146. #  define SOCK_ENETRESET      WSAENETRESET
  147. #  define SOCK_NFDS(s)        0
  148. #  define SOCK_CLOSE(s)       closesocket(s)
  149. #  define SOCK_SHUTDOWN(s,h)  shutdown(s,h)
  150. #  define SOCK_SHUTDOWN_RD    SD_RECEIVE
  151. #  define SOCK_SHUTDOWN_WR    SD_SEND
  152. #  define SOCK_SHUTDOWN_RDWR  SD_BOTH
  153. #  define SOCK_STRERROR(err)  s_StrError(err)
  154. /* NCBI_OS_MSWIN */
  155. #elif defined(NCBI_OS_UNIX)
  156. typedef int TSOCK_Handle;
  157. #  define SOCK_INVALID        (-1)
  158. #  define SOCK_ERRNO          errno
  159. #  define SOCK_EINTR          EINTR
  160. #  define SOCK_EWOULDBLOCK    EWOULDBLOCK
  161. #  define SOCK_EADDRINUSE     EADDRINUSE
  162. #  define SOCK_ECONNRESET     ECONNRESET
  163. #  define SOCK_EPIPE          EPIPE
  164. #  define SOCK_EAGAIN         EAGAIN
  165. #  define SOCK_EINPROGRESS    EINPROGRESS
  166. #  define SOCK_EALREADY       EALREADY
  167. #  define SOCK_ENOTCONN       ENOTCONN
  168. #  define SOCK_ECONNABORTED   ECONNABORTED
  169. #  define SOCK_ECONNREFUSED   ECONNREFUSED
  170. #  define SOCK_ENETRESET      ENETRESET
  171. #  define SOCK_NFDS(s)        (s + 1)
  172. #  ifdef NCBI_OS_BEOS
  173. #    define SOCK_CLOSE(s)     closesocket(s)
  174. #  else
  175. #    define SOCK_CLOSE(s)     close(s)
  176. #  endif /*NCBI_OS_BEOS*/
  177. #  define SOCK_SHUTDOWN(s,h)  shutdown(s,h)
  178. #  ifndef SHUT_RD
  179. #    define SHUT_RD           0
  180. #  endif /*SHUT_RD*/
  181. #  define SOCK_SHUTDOWN_RD    SHUT_RD
  182. #  ifndef SHUT_WR
  183. #    define SHUT_WR           1
  184. #  endif /*SHUT_WR*/
  185. #  define SOCK_SHUTDOWN_WR    SHUT_WR
  186. #  ifndef SHUT_RDWR
  187. #    define SHUT_RDWR         2
  188. #  endif /*SHUT_RDWR*/
  189. #  define SOCK_SHUTDOWN_RDWR  SHUT_RDWR
  190. #  ifndef INADDR_NONE
  191. #    define INADDR_NONE       (unsigned int)(-1)
  192. #  endif /*INADDR_NONE*/
  193. #  define SOCK_STRERROR(err)  s_StrError(err)
  194. /* NCBI_OS_UNIX */
  195. #elif defined(NCBI_OS_MAC)
  196. #  if TARGET_API_MAC_CARBON
  197. #    define O_NONBLOCK kO_NONBLOCK
  198. #  endif /*TARGET_API_MAC_CARBON*/
  199. typedef int TSOCK_Handle;
  200. #  define SOCK_INVALID        (-1)
  201. #  ifndef SOCK_ERRNO
  202. #    define SOCK_ERRNO        errno
  203. #  endif /*SOCK_ERRNO*/
  204. #  define SOCK_EINTR          EINTR
  205. #  define SOCK_EWOULDBLOCK    EWOULDBLOCK
  206. #  define SOCK_EADDRINUSE     EADDRINUSE
  207. #  define SOCK_ECONNRESET     ECONNRESET
  208. #  define SOCK_EPIPE          EPIPE
  209. #  define SOCK_EAGAIN         EAGAIN
  210. #  define SOCK_EINPROGRESS    EINPROGRESS
  211. #  define SOCK_EALREADY       EALREADY
  212. #  define SOCK_ENOTCONN       ENOTCONN
  213. #  define SOCK_ECONNABORTED   ECONNABORTED
  214. #  define SOCK_ECONNREFUSED   ECONNREFUSED
  215. #  define SOCK_ENETRESET      ENETRESET
  216. #  define SOCK_NFDS(s)        (s + 1)
  217. #  define SOCK_CLOSE(s)       close(s)
  218. #  define SOCK_SHUTDOWN(s,h)  shutdown(s,h)
  219. #  define SOCK_SHUTDOWN_RD    0
  220. #  define SOCK_SHUTDOWN_WR    1
  221. #  define SOCK_SHUTDOWN_RDWR  2
  222. #  define SOCK_STRERROR(err)  s_StrError(err)
  223. #  ifdef NETDB_INTERNAL
  224. #    undef NETDB_INTERNAL
  225. #  endif /*NETDB_INTERNAL*/
  226. #endif /*NCBI_OS_MSWIN, NCBI_OS_UNIX, NCBI_OS_MAC*/
  227. #ifdef HAVE_SOCKLEN_T
  228. typedef socklen_t SOCK_socklen_t;
  229. #else
  230. typedef int       SOCK_socklen_t;
  231. #endif /*HAVE_SOCKLEN_T*/
  232. /* Type of connecting socket (except listening)
  233.  */
  234. typedef enum {
  235.     eSOCK_Datagram = 0,
  236.     eSOCK_ClientSide,
  237.     eSOCK_ServerSide,
  238.     eSOCK_ServerSideKeep
  239. } ESockType;
  240. #if 0/*defined(__GNUC__)*/
  241. typedef ESwitch    EBSwitch;
  242. typedef EIO_Status EBIO_Status;
  243. typedef ESockType  EBSockType;
  244. #else
  245. typedef unsigned   EBSwitch;
  246. typedef unsigned   EBIO_Status;
  247. typedef unsigned   EBSockType;
  248. #endif
  249. #define SET_LISTENING(s) ((s)->r_on_w  =   (unsigned) eDefault + 1)
  250. #define IS_LISTENING(s)  ((s)->r_on_w  ==  (unsigned) eDefault + 1)
  251. /* Listening socket
  252.  */
  253. struct LSOCK_tag {
  254.     TSOCK_Handle    sock;       /* OS-specific socket handle                 */
  255.     unsigned int    id;         /* the internal ID (see also "s_ID_Counter") */
  256.     unsigned int    n_accept;   /* total number of accepted clients          */
  257.     unsigned short  port;       /* port on which the socket is listening     */
  258.     /* type, status, EOF, log, read-on-write etc bit-field indicators */
  259.     EBSwitch             log:2; /* how to log events and data for this socket*/
  260.     EBSockType          type:2; /* MBZ (NB: eSOCK_Datagram)                  */
  261.     EBSwitch          r_on_w:2; /* 3 [=(int)eDefault + 1]                    */
  262.     EBSwitch        i_on_sig:2; /* eDefault                                  */
  263.     EBIO_Status     r_status:3; /* MBZ (NB: eIO_Success)                     */
  264.     unsigned/*bool*/     eof:1; /* 0                                         */
  265.     EBIO_Status     w_status:3; /* MBZ (NB: eIO_Success)                     */
  266.     unsigned/*bool*/ pending:1; /* 0                                         */
  267. };
  268. /* Socket [it must be in one-2-one correspondence with LSOCK above]
  269.  */
  270. struct SOCK_tag {
  271.     TSOCK_Handle    sock;       /* OS-specific socket handle                 */
  272.     unsigned int    id;         /* the internal ID (see also "s_ID_Counter") */
  273.     /* connection point */
  274.     unsigned int    host;       /* peer host (in the network byte order)     */
  275.     unsigned short  port;       /* peer port (in the network byte order)     */
  276.     /* type, status, EOF, log, read-on-write etc bit-field indicators */
  277.     EBSwitch             log:2; /* how to log events and data for this socket*/
  278.     EBSockType          type:2; /* socket type: client- or server-side, dgram*/
  279.     EBSwitch          r_on_w:2; /* enable/disable automatic read-on-write    */
  280.     EBSwitch        i_on_sig:2; /* enable/disable I/O restart on signals     */
  281.     EBIO_Status     r_status:3; /* read  status:  eIO_Closed if was shut down*/
  282.     unsigned/*bool*/     eof:1; /* Stream sockets: 'End of file' seen on read
  283.                                    Datagram socks: 'End of message' written  */
  284.     EBIO_Status     w_status:3; /* write status:  eIO_Closed if was shut down*/
  285.     unsigned/*bool*/ pending:1; /* != 0 if connection is still pending       */
  286.     /* timeouts */
  287.     const struct timeval* r_timeout;/* NULL if infinite, or points to "r_tv" */
  288.     struct timeval  r_tv;       /* finite read timeout value                 */
  289.     STimeout        r_to;       /* finite read timeout value (aux., temp.)   */
  290.     const struct timeval* w_timeout;/* NULL if infinite, or points to "w_tv" */
  291.     struct timeval  w_tv;       /* finite write timeout value                */
  292.     STimeout        w_to;       /* finite write timeout value (aux., temp.)  */
  293.     const struct timeval* c_timeout;/* NULL if infinite, or points to "c_tv" */
  294.     struct timeval  c_tv;       /* finite close timeout value                */
  295.     STimeout        c_to;       /* finite close timeout value (aux., temp.)  */
  296.     /* aux I/O data */
  297.     BUF             r_buf;      /* read  buffer                              */
  298.     BUF             w_buf;      /* write buffer                              */
  299.     size_t          w_len;      /* SOCK: how much data is pending for output */
  300.     /* statistics */
  301.     size_t          n_read;     /* DSOCK: total #; SOCK: last connect/ only  */
  302.     size_t          n_written;  /* DSOCK: total #; SOCK: last /session only  */
  303.     size_t          n_in;       /* DSOCK: msg #; SOCK: total # of bytes read */
  304.     size_t          n_out;      /* DSOCK: msg #; SOCK: total # of bytes sent */
  305. #ifdef NCBI_OS_UNIX
  306.     /* filename for UNIX socket */
  307.     char            file[1];    /* must go last                              */
  308. #endif /*NCBI_OS_UNIX*/
  309. };
  310. /*
  311.  * Please note the following implementation details:
  312.  *
  313.  * 1. w_buf is used for stream sockets to keep initial data segment
  314.  *    that has to be sent upon the connection establishment.
  315.  *
  316.  * 2. eof is used differently for stream and datagram sockets:
  317.  *    =1 for stream sockets means that read had hit EOF;
  318.  *    =1 for datagram sockets means that the message in w_buf is complete.
  319.  *
  320.  * 3. r_status keeps completion code of the last low-level read call;
  321.  *    however, eIO_Closed is there when the socket is shut down for reading;
  322.  *    see the table below for full details on stream sockets.
  323.  *
  324.  * 4. w_status keeps completion code of the last low-level write call;
  325.  *    however, eIO_Closed is there when the socket is shut down for writing.
  326.  *
  327.  * 5. The following table depicts r_status and eof combinations and their
  328.  *    meanings for stream sockets:
  329.  * -------------------------------+--------------------------------------------
  330.  *              Field             |
  331.  * ---------------+---------------+                  Meaning
  332.  * sock->r_status |   sock->eof   |           (stream sockets only)
  333.  * ---------------+---------------+--------------------------------------------
  334.  * eIO_Closed     |       0       |  Socket shut down for reading
  335.  * eIO_Closed     |       1       |  Read severely failed
  336.  * not eIO_Closed |       0       |  Read completed with r_status error
  337.  * not eIO_Closed |       1       |  Read hit EOF (and later r_status)
  338.  * ---------------+---------------+--------------------------------------------
  339.  */
  340. /* Globals:
  341.  */
  342. /* Flag to indicate whether the API has been initialized */
  343. static int/*bool*/ s_Initialized = 0/*false*/;
  344. /* SOCK counter */
  345. static unsigned int s_ID_Counter = 0;
  346. /* Read-while-writing switch */
  347. static ESwitch s_ReadOnWrite = eOff;        /* no read-on-write by default   */
  348. /* Reuse address flag for newly created stream sockets */
  349. static int/*bool*/ s_ReuseAddress = 0;      /* off by default                */
  350. /* I/O restart on signals */
  351. static ESwitch s_InterruptOnSignal = eOff;  /* restart I/O by default        */
  352. /* Data/event logging */
  353. static ESwitch s_Log = eOff;                /* no logging by default         */
  354. /* Select restart timeout */
  355. static const struct timeval* s_SelectTimeout = 0; /* =0 (disabled) by default*/
  356. /* Flag to indicate whether API should mask SIGPIPE (during initialization)  */
  357. #ifdef NCBI_OS_UNIX
  358. static int/*bool*/ s_AllowSigPipe = 0/*false - mask SIGPIPE out*/;
  359. #endif /*NCBI_OS_UNIX*/
  360. /******************************************************************************
  361.  *   Error reporting
  362.  */
  363. static const char* s_StrError(int error)
  364. {
  365.     static struct {
  366.         int         errnum;
  367.         const char* errtxt;
  368.     } errmap[] = {
  369. #ifdef NCBI_OS_MSWIN
  370.         {WSAEINTR,  "Interrupted system call"},
  371.         {WSAEBADF,  "Bad file number"},
  372.         {WSAEACCES, "Access denied"},
  373.         {WSAEFAULT, "Segmentation fault"},
  374.         {WSAEINVAL, "Invalid agrument"},
  375.         {WSAEMFILE, "Too many open files"},
  376.         /*
  377.          * Windows Sockets definitions of regular Berkeley error constants
  378.          */
  379.         {WSAEWOULDBLOCK,     "Resource temporarily unavailable"},
  380.         {WSAEINPROGRESS,     "Operation now in progress"},
  381.         {WSAEALREADY,        "Operation already in progress"},
  382.         {WSAENOTSOCK,        "Not a socket"},
  383.         {WSAEDESTADDRREQ,    "Destination address required"},
  384.         {WSAEMSGSIZE,        "Invalid message size"},
  385.         {WSAEPROTOTYPE,      "Wrong protocol type"},
  386.         {WSAENOPROTOOPT,     "Bad protocol option"},
  387.         {WSAEPROTONOSUPPORT, "Protocol not supported"},
  388.         {WSAESOCKTNOSUPPORT, "Socket type not supported"},
  389.         {WSAEOPNOTSUPP,      "Operation not supported"},
  390.         {WSAEPFNOSUPPORT,    "Protocol family not supported"},
  391.         {WSAEAFNOSUPPORT,    "Address family not supported"},
  392.         {WSAEADDRINUSE,      "Address already in use"},
  393.         {WSAEADDRNOTAVAIL,   "Cannot assign requested address"},
  394.         {WSAENETDOWN,        "Network is down"},
  395.         {WSAENETUNREACH,     "Network is unreachable"},
  396.         {WSAENETRESET,       "Connection dropped on network reset"},
  397.         {WSAECONNABORTED,    "Software caused connection abort"},
  398.         {WSAECONNRESET,      "Connection reset by peer"},
  399.         {WSAENOBUFS,         "No buffer space available"},
  400.         {WSAEISCONN,         "Socket is already connected"},
  401.         {WSAENOTCONN,        "Socket is not connected"},
  402.         {WSAESHUTDOWN,       "Cannot send after socket shutdown"},
  403.         {WSAETOOMANYREFS,    "Too many references"},
  404.         {WSAETIMEDOUT,       "Operation timed out"},
  405.         {WSAECONNREFUSED,    "Connection refused"},
  406.         {WSAELOOP,           "Infinite loop"},
  407.         {WSAENAMETOOLONG,    "Name too long"},
  408.         {WSAEHOSTDOWN,       "Host is down"},
  409.         {WSAEHOSTUNREACH,    "Host unreachable"},
  410.         {WSAENOTEMPTY,       "Not empty"},
  411.         {WSAEPROCLIM,        "Too many processes"},
  412.         {WSAEUSERS,          "Too many users"},
  413.         {WSAEDQUOT,          "Quota exceeded"},
  414.         {WSAESTALE,          "Stale descriptor"},
  415.         {WSAEREMOTE,         "Remote error"},
  416.         /*
  417.          * Extended Windows Sockets error constant definitions
  418.          */
  419.         {WSASYSNOTREADY,         "Network subsystem is unavailable"},
  420.         {WSAVERNOTSUPPORTED,     "Winsock.dll version out of range"},
  421.         {WSANOTINITIALISED,      "Not yet initialized"},
  422.         {WSAEDISCON,             "Graceful shutdown in progress"},
  423.         {WSAENOMORE,             "No more retries"},
  424.         {WSAECANCELLED,          "Cancelled"},
  425.         {WSAEINVALIDPROCTABLE,   "Invalid procedure table"},
  426.         {WSAEINVALIDPROVIDER,    "Invalid provider version number"},
  427.         {WSAEPROVIDERFAILEDINIT, "Cannot init provider"},
  428.         {WSASYSCALLFAILURE,      "System call failed"},
  429.         {WSASERVICE_NOT_FOUND,   "Service not found"},
  430.         {WSATYPE_NOT_FOUND,      "Class type not found"},
  431.         {WSA_E_NO_MORE,          "WSA_E_NO_MORE"},
  432.         {WSA_E_CANCELLED,        "WSA_E_CANCELLED"},
  433.         {WSAEREFUSED,            "Refused"},
  434. #endif /*NCBI_OS_MSWIN*/
  435. #ifdef NCBI_OS_MSWIN
  436. #  define EAI_BASE 0
  437. #else
  438. #  define EAI_BASE 100000
  439. #endif /*NCBI_OS_MSWIN*/
  440. #ifdef EAI_ADDRFAMILY
  441.         {EAI_ADDRFAMILY + EAI_BASE,
  442.                                  "Address family not supported"},
  443. #endif /*EAI_ADDRFAMILY*/
  444. #ifdef EAI_AGAIN
  445.         {EAI_AGAIN + EAI_BASE,
  446.                                  "Temporary failure in name resolution"},
  447. #endif /*EAI_AGAIN*/
  448. #ifdef EAI_BADFLAGS
  449.         {EAI_BADFLAGS + EAI_BASE,
  450.                                  "Invalid value for lookup flags"},
  451. #endif /*EAI_BADFLAGS*/
  452. #ifdef EAI_FAIL
  453.         {EAI_FAIL + EAI_BASE,
  454.                                  "Non-recoverable failure in name resolution"},
  455. #endif /*EAI_FAIL*/
  456. #ifdef EAI_FAMILY
  457.         {EAI_FAMILY + EAI_BASE,
  458.                                  "Address family not supported"},
  459. #endif /*EAI_FAMILY*/
  460. #ifdef EAI_MEMORY
  461.         {EAI_MEMORY + EAI_BASE,
  462.                                  "Memory allocation failure"},
  463. #endif /*EAI_MEMORY*/
  464. #ifdef EAI_NODATA
  465.         {EAI_NODATA + EAI_BASE,
  466.                                  "No address associated with nodename"},
  467. #endif /*EAI_NODATA*/
  468. #ifdef EAI_NONAME
  469.         {EAI_NONAME + EAI_BASE,
  470.                                  "Host/service name not known"},
  471. #endif /*EAI_NONAME*/
  472. #ifdef EAI_SERVICE
  473.         {EAI_SERVICE + EAI_BASE,
  474.                                  "Service name not supported for socket type"},
  475. #endif /*EAI_SERVICE*/
  476. #ifdef EAI_SOCKTYPE
  477.         {EAI_SOCKTYPE + EAI_BASE,
  478.                                  "Socket type not supported"},
  479. #endif /*EAI_SOCKTYPE*/
  480. #ifdef NCBI_OS_MSWIN
  481. #  define DNS_BASE 0
  482. #else
  483. #  define DNS_BASE 200000
  484. #endif /*NCBI_OS_MSWIN*/
  485. #ifdef HOST_NOT_FOUND
  486.         {HOST_NOT_FOUND + DNS_BASE,
  487.                                  "Host not found"},
  488. #endif /*HOST_NOT_FOUND*/
  489. #ifdef TRY_AGAIN
  490.         {TRY_AGAIN + DNS_BASE,
  491.                                  "DNS server failure"},
  492. #endif /*TRY_AGAIN*/
  493. #ifdef NO_RECOVERY
  494.         {NO_RECOVERY + DNS_BASE,
  495.                                  "Unrecoverable DNS error"},
  496. #endif /*NO_RECOVERY*/
  497. #ifdef NO_DATA
  498.         {NO_DATA + DNS_BASE,
  499.                                  "No DNS data of requested type"},
  500. #endif /*NO_DATA*/
  501. #ifdef NO_ADDRESS
  502.         {NO_ADDRESS + DNS_BASE,
  503.                                  "No address record found in DNS"},
  504. #endif /*NO_ADDRESS*/
  505.         /* Last dummy entry - must present */
  506.         {0, 0}
  507.     };
  508.     size_t i, n = sizeof(errmap)/sizeof(errmap[0]) - 1/*dummy entry*/;
  509.     /* always called on error, so get error number here if not having already*/
  510.     if ( !error )
  511.         error = errno;
  512.     for (i = 0; i < n; i++) {
  513.         if (errmap[i].errnum == error)
  514.             return errmap[i].errtxt;
  515.     }
  516.     return strerror(error);
  517. }
  518. /******************************************************************************
  519.  *   Data Logging
  520.  */
  521. static const char* s_ID(const SOCK sock, char* buf)
  522. {
  523.     const char* sname;
  524.     if ( !sock )
  525.         return "";
  526.     sname = IS_LISTENING(sock) ? "LSOCK" : "SOCK";
  527.     if (sock->sock == SOCK_INVALID)
  528.         sprintf(buf, "%s#%u[?]: ",  sname, sock->id);
  529.     else
  530.         sprintf(buf, "%s#%u[%u]: ", sname, sock->id, (unsigned int)sock->sock);
  531.     return buf;
  532. }
  533. /* Put socket description to the message, then log the transferred data
  534.  */
  535. static void s_DoLog
  536. (const SOCK  sock, EIO_Event event,
  537.  const void* data, size_t    size,  const struct sockaddr* sa)
  538. {
  539.     char head[128];
  540.     char tail[128];
  541.     char _id[32];
  542.     if ( !CORE_GetLOG() )
  543.         return;
  544.     assert(sock);
  545.     switch (event) {
  546.     case eIO_Open:
  547.         if (sock->type == eSOCK_Datagram) {
  548.             if ( !sa ) {
  549.                 strcpy(head, "Datagram socket created");
  550.                 *tail = 0;
  551.             } else {
  552.                 const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;
  553.                 if ( !data ) {
  554.                     strcpy(head, "Datagram socket bound to port :");
  555.                     sprintf(tail, "%hu", ntohs(sin->sin_port));
  556.                 } else {
  557.                     strcpy(head, "Datagram socket connected to ");
  558.                     HostPortToString(sin->sin_addr.s_addr,ntohs(sin->sin_port),
  559.                                      tail, sizeof(tail));
  560.                 }
  561.             }
  562.         } else {
  563.             if (sock->type == eSOCK_ClientSide)
  564.                 strcpy(head, "Connecting to ");
  565.             else if ( data )
  566.                 strcpy(head, "Connected to ");
  567.             else
  568.                 strcpy(head, "Accepted from ");
  569.             if (sa->sa_family == AF_INET) {
  570.                 const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;
  571.                 HostPortToString(sin->sin_addr.s_addr, ntohs(sin->sin_port),
  572.                                  tail, sizeof(tail));
  573.             }
  574. #ifdef NCBI_OS_UNIX
  575.             else if (sa->sa_family == AF_UNIX) {
  576.                 const struct sockaddr_un* un = (const struct sockaddr_un*) sa;
  577.                 strncpy0(tail, un->sun_path, sizeof(tail) - 1);
  578.             }
  579. #endif /*NCBI_OS_UNIX*/
  580.             else
  581.                 strcpy(tail, "???");
  582.         }
  583.         CORE_LOGF(eLOG_Trace, ("%s%s%s", s_ID(sock, _id), head, tail));
  584.         break;
  585.     case eIO_Read:
  586.     case eIO_Write:
  587.         if (sock->type == eSOCK_Datagram) {
  588.             const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;
  589.             assert(sa && sa->sa_family == AF_INET);
  590.             HostPortToString(sin->sin_addr.s_addr, ntohs(sin->sin_port),
  591.                              tail, sizeof(tail));
  592.             sprintf(tail + strlen(tail), ", msg# %u",
  593.                     (unsigned)(event == eIO_Read ? sock->n_in : sock->n_out));
  594.         } else {
  595.             assert(sa == 0);
  596.             *tail = 0;
  597.         }
  598.         sprintf(head, "%s%s%s at offset %lu%s%s", s_ID(sock, _id),
  599.                 event == eIO_Read
  600.                 ? (sock->type != eSOCK_Datagram  &&  !size
  601.                    ? (data ? "EOF hit" : SOCK_STRERROR(SOCK_ERRNO))
  602.                    : "Read")
  603.                 : (sock->type != eSOCK_Datagram  &&  !size
  604.                    ? SOCK_STRERROR(SOCK_ERRNO) : "Written"),
  605.                 sock->type == eSOCK_Datagram  ||  size ? "" :
  606.                 (event == eIO_Read ? " while reading" : " while writing"),
  607.                 (unsigned long) (event == eIO_Read
  608.                                  ? sock->n_read : sock->n_written),
  609.                 sa ? (event == eIO_Read ? " from " : " to ") : "", tail);
  610.         CORE_DATA(data, size, head);
  611.         break;
  612.     case eIO_Close:
  613.         {{
  614.             int n = sprintf(head, "%lu byte%s",
  615.                             (unsigned long) sock->n_written,
  616.                             sock->n_written == 1 ? "" : "s");
  617.             if (sock->type == eSOCK_Datagram  ||
  618.                 sock->n_out != sock->n_written) {
  619.                 sprintf(head + n, "/%lu %s%s",
  620.                         (unsigned long) sock->n_out,
  621.                         sock->type == eSOCK_Datagram ? "msg" : "total byte",
  622.                         sock->n_out == 1 ? "" : "s");
  623.             }
  624.         }}
  625.         {{
  626.             int n = sprintf(tail, "%lu byte%s",
  627.                             (unsigned long) sock->n_read,
  628.                             sock->n_read == 1 ? "" : "s");
  629.             if (sock->type == eSOCK_Datagram  ||
  630.                 sock->n_in != sock->n_read) {
  631.                 sprintf(tail + n, "/%lu %s%s",
  632.                         (unsigned long) sock->n_in,
  633.                         sock->type == eSOCK_Datagram ? "msg" : "total byte",
  634.                         sock->n_in == 1 ? "" : "s");
  635.             }
  636.         }}
  637.         CORE_LOGF(eLOG_Trace, ("%s%s (out: %s, in: %s)", s_ID(sock, _id),
  638.                                sock->type == eSOCK_ServerSideKeep
  639.                                ? "Leaving" : "Closing", head,tail));
  640.         break;
  641.     default:
  642.         CORE_LOGF(eLOG_Error, ("%s[SOCK::s_DoLog]  Invalid event %u",
  643.                                s_ID(sock, _id), (unsigned int) event));
  644.         assert(0);
  645.         break;
  646.     }
  647. }
  648. extern ESwitch SOCK_SetDataLoggingAPI(ESwitch log)
  649. {
  650.     ESwitch old = s_Log;
  651.     if (log == eDefault)
  652.         log = eOff;
  653.     s_Log = log;
  654.     return old;
  655. }
  656. extern ESwitch SOCK_SetDataLogging(SOCK sock, ESwitch log)
  657. {
  658.     ESwitch old = sock->log;
  659.     sock->log = log;
  660.     return old;
  661. }
  662. /******************************************************************************
  663.  *  API Initialization and Shutdown/Cleanup
  664.  */
  665. extern void SOCK_AllowSigPipeAPI(void)
  666. {
  667. #ifdef NCBI_OS_UNIX
  668.     s_AllowSigPipe = 1/*true - API will not mask SIGPIPE out at init*/;
  669. #endif /*NCBI_OS_UNIX*/
  670.     return;
  671. }
  672. #if 0/*defined(_DEBUG) && !defined(NDEBUG)*/
  673. #  if !defined(__GNUC__) && !defined(offsetof)
  674. #    define offsetof(T, F) ((size_t)((char*) &(((T*) 0)->F) - (char*) 0))
  675. #  endif
  676. static void s_ShowDataLayout(void)
  677. {
  678.     CORE_LOGF(eLOG_Note, ("SOCK data layout:n"
  679.                           "    Sizeof(SOCK_struct) = %u, offsets follown"
  680.                           "tsock:      %un"
  681.                           "tid:        %un"
  682.                           "thost:      %un"
  683.                           "tport:      %un"
  684.                           "tbitfield:  16 bitsn"
  685.                           "tr_timeout: %un"
  686.                           "tr_tv:      %un"
  687.                           "tr_to:      %un"
  688.                           "tw_timeout: %un"
  689.                           "tw_tv:      %un"
  690.                           "tw_to:      %un"
  691.                           "tc_timeout: %un"
  692.                           "tc_tv:      %un"
  693.                           "tc_to:      %un"
  694.                           "tr_buf:     %un"
  695.                           "tw_buf:     %un"
  696.                           "tw_len:     %un"
  697.                           "tn_read:    %un"
  698.                           "tn_written: %un"
  699.                           "tn_in:      %un"
  700.                           "tn_out:     %u"
  701. #  ifdef NCBI_OS_UNIX
  702.                           "ntfile:      %u"
  703. #  endif /*NCBI_OS_UNIX*/
  704.                           , (unsigned int) sizeof(SOCK_struct),
  705.                           (unsigned int) offsetof(SOCK_struct, sock),
  706.                           (unsigned int) offsetof(SOCK_struct, id),
  707.                           (unsigned int) offsetof(SOCK_struct, host),
  708.                           (unsigned int) offsetof(SOCK_struct, port),
  709.                           (unsigned int) offsetof(SOCK_struct, r_timeout),
  710.                           (unsigned int) offsetof(SOCK_struct, r_tv),
  711.                           (unsigned int) offsetof(SOCK_struct, r_to),
  712.                           (unsigned int) offsetof(SOCK_struct, w_timeout),
  713.                           (unsigned int) offsetof(SOCK_struct, w_tv),
  714.                           (unsigned int) offsetof(SOCK_struct, w_to),
  715.                           (unsigned int) offsetof(SOCK_struct, c_timeout),
  716.                           (unsigned int) offsetof(SOCK_struct, c_tv),
  717.                           (unsigned int) offsetof(SOCK_struct, c_to),
  718.                           (unsigned int) offsetof(SOCK_struct, r_buf),
  719.                           (unsigned int) offsetof(SOCK_struct, w_buf),
  720.                           (unsigned int) offsetof(SOCK_struct, w_len),
  721.                           (unsigned int) offsetof(SOCK_struct, n_read),
  722.                           (unsigned int) offsetof(SOCK_struct, n_written),
  723.                           (unsigned int) offsetof(SOCK_struct, n_in),
  724.                           (unsigned int) offsetof(SOCK_struct, n_out)
  725. #  ifdef NCBI_OS_UNIX
  726.                           , (unsigned int) offsetoff(SOCK_struct, file)
  727. #  endif /*NCBI_OS_UNIX*/
  728.                           ));
  729. }
  730. #endif
  731. extern EIO_Status SOCK_InitializeAPI(void)
  732. {
  733.     static int/*bool*/ s_AtExitSet = 0;
  734.     CORE_LOCK_WRITE;
  735.     if ( s_Initialized ) {
  736.         CORE_UNLOCK;
  737.         return eIO_Success;
  738.     }
  739. #if 0/*defined(_DEBUG) && !defined(NDEBUG)*/
  740.     s_ShowDataLayout();
  741. #endif
  742. #if defined(NCBI_OS_MSWIN)
  743.     {{
  744.         WSADATA wsadata;
  745.         int x_errno = WSAStartup(MAKEWORD(1,1), &wsadata);
  746.         if (x_errno != 0) {
  747.             CORE_UNLOCK;
  748.             CORE_LOG_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  749.                               "[SOCK::InitializeAPI]  Failed WSAStartup()");
  750.             return eIO_Unknown;
  751.         }
  752.     }}
  753. #elif defined(NCBI_OS_UNIX)
  754.     if ( !s_AllowSigPipe ) {
  755.         struct sigaction sa;
  756.         if (sigaction(SIGPIPE, 0, &sa) < 0  ||  sa.sa_handler == SIG_DFL) {
  757.             memset(&sa, 0, sizeof(sa));
  758.             sa.sa_handler = SIG_IGN;
  759.             sigaction(SIGPIPE, &sa, 0);
  760.         }
  761.     }
  762. #endif /*platform-specific init*/
  763.     s_Initialized = 1/*true*/;
  764.     if ( !s_AtExitSet ) {
  765.         atexit((void (*)(void)) SOCK_ShutdownAPI);
  766.         s_AtExitSet = 1;
  767.     }
  768.     CORE_UNLOCK;
  769.     return eIO_Success;
  770. }
  771. extern EIO_Status SOCK_ShutdownAPI(void)
  772. {
  773.     CORE_LOCK_WRITE;
  774.     if ( !s_Initialized ) {
  775.         CORE_UNLOCK;
  776.         return eIO_Success;
  777.     }
  778.     s_Initialized = 0/*false*/;
  779. #if defined(NCBI_OS_MSWIN)
  780.     {{
  781.         int x_errno = WSACleanup() ? SOCK_ERRNO : 0;
  782.         CORE_UNLOCK;
  783.         if ( x_errno ) {
  784.             CORE_LOG_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
  785.                               "[SOCK::ShutdownAPI]  Failed WSACleanup()");
  786.             return eIO_Unknown;
  787.         }
  788.     }}
  789. #else
  790.     CORE_UNLOCK;
  791. #endif /*NCBI_OS_MSWIN*/
  792.     return eIO_Success;
  793. }
  794. /******************************************************************************
  795.  *  LSOCK & SOCK AUXILIARIES
  796.  */
  797. /* STimeout <--> struct timeval  conversions
  798.  */
  799. static STimeout *s_tv2to(const struct timeval* tv, STimeout* to)
  800. {
  801.     if ( !tv )
  802.         return 0;
  803.     to->sec  = (unsigned int) tv->tv_sec;
  804.     to->usec = (unsigned int) tv->tv_usec;
  805.     return to;
  806. }
  807. static struct timeval* s_to2tv(const STimeout* to, struct timeval* tv)
  808. {
  809.     if ( !to )
  810.         return 0;
  811.     tv->tv_sec  = to->usec / 1000000 + to->sec;
  812.     tv->tv_usec = to->usec % 1000000;
  813.     return tv;
  814. }
  815. /* Switch the specified socket I/O between blocking and non-blocking mode
  816.  */
  817. static int/*bool*/ s_SetNonblock(TSOCK_Handle sock, int/*bool*/ nonblock)
  818. {
  819. #if defined(NCBI_OS_MSWIN)
  820.     unsigned long argp = nonblock ? 1 : 0;
  821.     return ioctlsocket(sock, FIONBIO, &argp) == 0;
  822. #elif defined(NCBI_OS_UNIX)  ||  defined(NCBI_OS_MAC)
  823.     return fcntl(sock, F_SETFL,
  824.                  nonblock ?
  825.                  fcntl(sock, F_GETFL, 0) | O_NONBLOCK :
  826.                  fcntl(sock, F_GETFL, 0) & (int) ~O_NONBLOCK) != -1;
  827. #else
  828. #   error "Unsupported platform"
  829. #endif /*platform-specific ioctl*/
  830. }
  831. static int/*bool*/ s_SetReuseAddress(TSOCK_Handle x_sock, int/*bool*/ on_off)
  832. {
  833. #if defined(NCBI_OS_UNIX)  ||  defined(NCBI_OS_MSWIN)
  834.     /* setsockopt() is not implemented for MAC (in MIT socket emulation lib) */
  835. #  ifdef NCBI_OS_MSWIN
  836.     BOOL reuse_addr = on_off ? TRUE : FALSE;
  837. #  else
  838.     int  reuse_addr = on_off ? 1 : 0;
  839. #  endif /*NCBI_OS_MSWIN*/
  840.     return !setsockopt(x_sock, SOL_SOCKET, SO_REUSEADDR, 
  841.                        (char*) &reuse_addr, sizeof(reuse_addr));
  842. #else
  843.     return 1;
  844. #endif /*NCBI_OS_UNIX || NCBI_OS_MSWIN*/
  845. }
  846. static EIO_Status s_Status(SOCK sock, EIO_Event direction)
  847. {
  848.     assert(sock  &&  sock->sock != SOCK_INVALID);
  849.     switch ( direction ) {
  850.     case eIO_Read:
  851.         return sock->type != eSOCK_Datagram  &&  sock->eof
  852.             ? eIO_Closed : sock->r_status;
  853.     case eIO_Write:
  854.         return sock->w_status;
  855.     default:
  856.         /*should never get here*/
  857.         assert(0);
  858.         break;
  859.     }
  860.     return eIO_InvalidArg;
  861. }
  862. /* compare 2 normialized timeval timeouts: "whether v1 is less than v2" */
  863. static int/*bool*/ s_Less(const struct timeval* v1, const struct timeval* v2)
  864. {
  865.     if (!v1)
  866.         return 0;
  867.     if (!v2)
  868.         return !!v1;
  869.     if (v1->tv_sec > v2->tv_sec)
  870.         return 0;
  871.     if (v1->tv_sec < v2->tv_sec)
  872.         return 1;
  873.     return v1->tv_usec < v2->tv_usec;
  874. }
  875. /* Select on the socket I/O (multiple sockets).
  876.  * "Event" field is not considered for entries, whose "sock" field is 0,
  877.  * "revent" for those entries is always "eIO_Open". For all other entries
  878.  * only those sockets will be considered, whose "revent" field does not
  879.  * contain "eIO_Open" value. If at least one non-"eIO_Open" status found
  880.  * in "revent", the call terminates with "eIO_Success" status (after,
  881.  * however checking all other entries for validity). No additional checks
  882.  * are made for the pre-ready entries. 
  883.  *
  884.  * This function does not check datagram sockets with the select() system call
  885.  * at all if the number of requested sockets is more than 1 (cf. SOCK_Poll()).
  886.  *
  887.  * If "eIO_Write" event is inquired on a stream socket, and the socket is
  888.  * marked for upread, then returned "revent" may also include "eIO_Read" to
  889.  * indicate that some input is available on that socket.
  890.  * If "eIO_Read" event is inquired on an array (n != 1) including stream
  891.  * socket(s) and some sockets still have connection/data pending, those
  892.  * "revent" field may then include "eIO_Write" to indicate that
  893.  * connection can be completed/data sent.
  894.  *
  895.  * Return eIO_Success when at least one socket is found either ready 
  896.  * (including "eIO_Read" event on "eIO_Write" for upreadable sockets
  897.  * and "eIO_Write" on "eIO_Read" for sockets in pending state)
  898.  * or failing ("revent" contains "eIO_Close").
  899.  * Return "eIO_Timeout", if timeout expired before any socket became available.
  900.  * Any other return code indicates some failure.
  901.  */
  902. static EIO_Status s_Select(size_t                n,
  903.                            SSOCK_Poll            polls[],
  904.                            const struct timeval* tv)
  905. {
  906.     int/*bool*/    write_only = 1;
  907.     int/*bool*/    read_only = 1;
  908.     int/*bool*/    ready = 0;
  909.     int/*bool*/    bad = 0;
  910.     fd_set         r_fds, w_fds, e_fds;
  911.     int            n_fds;
  912.     struct timeval x_tv;
  913.     size_t         i;
  914.     if ( tv )
  915.         x_tv = *tv;
  916.     for (;;) { /* (optionally) auto-resume if interrupted by a signal */
  917.         struct timeval xx_tv;
  918.         n_fds = 0;
  919.         FD_ZERO(&r_fds);
  920.         FD_ZERO(&w_fds);
  921.         FD_ZERO(&e_fds);
  922.         for (i = 0; i < n; i++) {
  923.             if ( !polls[i].sock ) {
  924.                 polls[i].revent = eIO_Open;
  925.                 continue;
  926.             }
  927.             if ( polls[i].revent ) {
  928.                 ready = 1;
  929.                 continue;
  930.             }
  931.             if (polls[i].event  &&
  932.                 (EIO_Event)(polls[i].event | eIO_ReadWrite) == eIO_ReadWrite) {
  933.                 TSOCK_Handle fd = polls[i].sock->sock;
  934.                 if (fd != SOCK_INVALID) {
  935.                     int/*bool*/ ls = IS_LISTENING(polls[i].sock);
  936.                     if (!ls && n != 1 && polls[i].sock->type == eSOCK_Datagram)
  937.                         continue;
  938.                     if (ready  ||  bad)
  939.                         continue;
  940.                     switch (polls[i].event) {
  941.                     case eIO_Write:
  942.                     case eIO_ReadWrite:
  943.                         if (!ls) {
  944.                             if (polls[i].sock->type == eSOCK_Datagram  ||
  945.                                 polls[i].sock->w_status != eIO_Closed) {
  946.                                 read_only = 0;
  947.                                 FD_SET(fd, &w_fds);
  948.                                 if (polls[i].sock->type == eSOCK_Datagram  ||
  949.                                     polls[i].sock->pending)
  950.                                     break;
  951.                                 if (polls[i].event == eIO_Write  &&
  952.                                     (polls[i].sock->r_on_w == eOff
  953.                                      ||  (polls[i].sock->r_on_w == eDefault
  954.                                           &&  s_ReadOnWrite != eOn)))
  955.                                     break;
  956.                             } else if (polls[i].event == eIO_Write)
  957.                                 break;
  958.                         } else if (polls[i].event == eIO_Write)
  959.                             break;
  960.                         /*FALLTHRU*/
  961.                     case eIO_Read:
  962.                         if (polls[i].sock->type != eSOCK_Datagram
  963.                             &&  (polls[i].sock->r_status == eIO_Closed  ||
  964.                                  polls[i].sock->eof))
  965.                             break;
  966.                         write_only = 0;
  967.                         FD_SET(fd, &r_fds);
  968.                         if (polls[i].sock->type == eSOCK_Datagram  ||
  969.                             polls[i].event != eIO_Read             ||
  970.                             polls[i].sock->w_status == eIO_Closed  ||
  971.                             n == 1  ||  (!polls[i].sock->pending  &&
  972.                                          !polls[i].sock->w_len))
  973.                             break;
  974.                         read_only = 0;
  975.                         FD_SET(fd, &w_fds);
  976.                         break;
  977.                     default:
  978.                         /* should never get here */
  979.                         assert(0);
  980.                         break;
  981.                     }
  982.                     FD_SET(fd, &e_fds);
  983.                     if (n_fds < (int) fd)
  984.                         n_fds = (int) fd;
  985.                 } else {
  986.                     polls[i].revent = eIO_Close;
  987.                     ready = 1;
  988.                 }
  989.             } else {
  990.                 polls[i].revent = eIO_Close;
  991.                 bad = 1;
  992.             }
  993.         }
  994.         if ( bad )
  995.             return eIO_InvalidArg;
  996.         if ( ready )
  997.             return eIO_Success;
  998.         if (!tv  ||  s_Less(s_SelectTimeout, &x_tv)) {
  999.             if ( s_SelectTimeout ) {
  1000.                 xx_tv = *s_SelectTimeout;
  1001.             }
  1002.         } else
  1003.             xx_tv = x_tv;
  1004.         n_fds = select(SOCK_NFDS((TSOCK_Handle) n_fds),
  1005.                        write_only ? 0 : &r_fds, read_only ? 0 : &w_fds,
  1006.                        &e_fds, tv || s_SelectTimeout ? &xx_tv : 0);
  1007.         /* timeout has expired */
  1008.         if (n_fds == 0) {
  1009.             if ( !tv )
  1010.                 continue;
  1011.             if ( s_Less(s_SelectTimeout, &x_tv) ) {
  1012.                 x_tv.tv_sec  -= s_SelectTimeout->tv_sec;
  1013.                 x_tv.tv_usec -= s_SelectTimeout->tv_usec;
  1014.                 continue;
  1015.             }
  1016.             return eIO_Timeout;
  1017.         }
  1018.         if (n_fds > 0)
  1019.             break;
  1020.         /* n_fds < 0 */
  1021.         if (SOCK_ERRNO != SOCK_EINTR) {
  1022.             int  x_errno = SOCK_ERRNO;
  1023.             char _id[32];
  1024.             CORE_LOGF_ERRNO_EX(eLOG_Trace, x_errno, SOCK_STRERROR(x_errno),
  1025.                                ("%s[SOCK::s_Select]  Failed select()",
  1026.                                 n == 1 ? s_ID(polls[0].sock, _id) : ""));
  1027.             return eIO_Unknown;
  1028.         }
  1029.         if ((n != 1  &&  s_InterruptOnSignal == eOn)  ||
  1030.             (n == 1  &&  (polls[0].sock->i_on_sig == eOn
  1031.                           ||  (polls[0].sock->i_on_sig == eDefault
  1032.                                &&  s_InterruptOnSignal == eOn)))) {
  1033.             return eIO_Interrupt;
  1034.         }
  1035.     }
  1036.     n_fds = 0;
  1037.     for (i = 0; i < n; i++) {
  1038.         if ( polls[i].sock ) {
  1039.             TSOCK_Handle fd = polls[i].sock->sock;
  1040.             assert(polls[i].revent == eIO_Open);
  1041.             if (fd != SOCK_INVALID) {
  1042.                 if (!write_only  &&  FD_ISSET(fd, &r_fds))
  1043.                     polls[i].revent = eIO_Read;
  1044.                 if (!read_only   &&   FD_ISSET(fd, &w_fds))
  1045.                     polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Write);
  1046.                 if (!polls[i].revent  &&  FD_ISSET(fd, &e_fds))
  1047.                     polls[i].revent = eIO_Close;
  1048.             } else
  1049.                 polls[i].revent = eIO_Close;
  1050.             if (polls[i].revent != eIO_Open)
  1051.                 n_fds++;
  1052.         }
  1053.     }
  1054.     assert(n_fds != 0);
  1055.     /* success; can do I/O now */
  1056.     return eIO_Success;
  1057. }
  1058. /******************************************************************************
  1059.  *  UTILITY
  1060.  */
  1061. extern const STimeout* SOCK_SetSelectInternalRestartTimeout(const STimeout* t)
  1062. {
  1063.     static struct timeval  s_NewTmo;
  1064.     static STimeout        s_OldTmo;
  1065.     const  STimeout* retval = s_tv2to(s_SelectTimeout, &s_OldTmo);
  1066.     s_SelectTimeout         = s_to2tv(t,               &s_NewTmo);
  1067.     return retval;
  1068. }
  1069. /******************************************************************************
  1070.  *  LISTENING SOCKET
  1071.  */
  1072. extern EIO_Status LSOCK_Create(unsigned short port,
  1073.                                unsigned short backlog,
  1074.                                LSOCK*         lsock)
  1075. {
  1076.     return LSOCK_CreateEx(port, backlog, lsock, eDefault);
  1077. }
  1078. extern EIO_Status LSOCK_CreateEx(unsigned short port,
  1079.                                  unsigned short backlog,
  1080.                                  LSOCK*         lsock,
  1081.                                  ESwitch        log)
  1082. {
  1083.     unsigned int       x_id = ++s_ID_Counter;
  1084.     TSOCK_Handle       x_lsock;
  1085.     struct sockaddr_in addr;
  1086.     *lsock = 0;
  1087.     /* initialize internals */
  1088.     verify(s_Initialized  ||  SOCK_InitializeAPI() == eIO_Success);
  1089.     /* create new(listening) socket */
  1090.     if ((x_lsock = socket(AF_INET, SOCK_STREAM, 0)) == SOCK_INVALID) {
  1091.         int x_errno = SOCK_ERRNO;
  1092.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1093.                            ("LSOCK#%u[?]: [LSOCK::Create] "
  1094.                             " Cannot create socket", x_id));
  1095.         return eIO_Unknown;
  1096.     }
  1097.     /*
  1098.      * It was confirmed(?) that at least under Solaris 2.5 this precaution:
  1099.      * 1) makes the address released immediately after the process
  1100.      *    termination;
  1101.      * 2) still issue EADDINUSE error on the attempt to bind() to the
  1102.      *    same address being in-use by a living process (if SOCK_STREAM).
  1103.      */
  1104.     if ( !s_SetReuseAddress(x_lsock, 1/*true*/) ) {
  1105.         int x_errno = SOCK_ERRNO;
  1106.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1107.                            ("LSOCK#%u[%u]: [LSOCK::Create] "
  1108.                             " Failed setsockopt(REUSEADDR)",
  1109.                             x_id, (unsigned int) x_lsock));
  1110.         SOCK_CLOSE(x_lsock);
  1111.         return eIO_Unknown;
  1112.     }
  1113.     /* bind */
  1114.     memset(&addr, 0, sizeof(addr));
  1115.     addr.sin_family      = AF_INET;
  1116.     addr.sin_addr.s_addr = htonl(INADDR_ANY);
  1117.     addr.sin_port        = htons(port);
  1118. #ifdef HAVE_SIN_LEN
  1119.     addr.sin_len         = sizeof(addr);
  1120. #endif /*HAVE_SIN_LEN*/
  1121.     if (bind(x_lsock, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
  1122.         int x_errno = SOCK_ERRNO;
  1123.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1124.                            ("LSOCK#%u[%u]: [LSOCK::Create]  Failed bind(:%hu)",
  1125.                             x_id, (unsigned int) x_lsock, port));
  1126.         SOCK_CLOSE(x_lsock);
  1127.         return x_errno == SOCK_EADDRINUSE ? eIO_Closed : eIO_Unknown;
  1128.     }
  1129.     /* listen */
  1130.     if (listen(x_lsock, backlog) != 0) {
  1131.         int x_errno = SOCK_ERRNO;
  1132.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1133.                            ("LSOCK#%u[%u]: [LSOCK::Create]  Failed listen(%hu)"
  1134.                             , x_id, (unsigned int) x_lsock, backlog));
  1135.         SOCK_CLOSE(x_lsock);
  1136.         return eIO_Unknown;
  1137.     }
  1138.     /* set to non-blocking mode */
  1139.     if ( !s_SetNonblock(x_lsock, 1/*true*/) ) {
  1140.         CORE_LOGF(eLOG_Error, ("LSOCK#%u[%u]: [LSOCK::Create] "
  1141.                                " Cannot set socket to non-blocking mode",
  1142.                                x_id, (unsigned int) x_lsock));
  1143.         SOCK_CLOSE(x_lsock);
  1144.         return eIO_Unknown;
  1145.     }
  1146.     /* allocate memory for the internal socket structure */
  1147.     if ( !(*lsock = (LSOCK) calloc(1, sizeof(**lsock))) )
  1148.         return eIO_Unknown;
  1149.     (*lsock)->sock     = x_lsock;
  1150.     (*lsock)->id       = x_id;
  1151.     (*lsock)->log      = log;
  1152.     (*lsock)->i_on_sig = eDefault;
  1153.     SET_LISTENING(*lsock);
  1154.     /* statistics & logging */
  1155.     if (log == eOn  ||  (log == eDefault  &&  s_Log == eOn)) {
  1156.         CORE_LOGF(eLOG_Trace, ("LSOCK#%u[%u]: Listening at port :%hu",
  1157.                                x_id, (unsigned int) x_lsock, port));
  1158.     }
  1159.     return eIO_Success;
  1160. }
  1161. extern EIO_Status LSOCK_Accept(LSOCK           lsock,
  1162.                                const STimeout* timeout,
  1163.                                SOCK*           sock)
  1164. {
  1165.     struct sockaddr_in addr;
  1166.     unsigned int       x_id;
  1167.     TSOCK_Handle       x_sock;
  1168.     if (lsock->sock == SOCK_INVALID) {
  1169.         CORE_LOGF(eLOG_Error, ("LSOCK#%u[?]: [LSOCK::Accept] "
  1170.                                " Invalid socket", lsock->id));
  1171.         assert(0);
  1172.         return eIO_Unknown;
  1173.     }
  1174.     {{ /* wait for the connection request to come (up to timeout) */
  1175.         EIO_Status     status;
  1176.         SSOCK_Poll     poll;
  1177.         struct timeval tv;
  1178.         poll.sock   = (SOCK) lsock;
  1179.         poll.event  = eIO_Read;
  1180.         poll.revent = eIO_Open;
  1181.         if ((status = s_Select(1, &poll, s_to2tv(timeout,&tv))) != eIO_Success)
  1182.             return status;
  1183.         if (poll.revent == eIO_Close)
  1184.             return eIO_Unknown;
  1185.         assert(poll.event == eIO_Read  &&  poll.revent == eIO_Read);
  1186.     }}
  1187.     x_id = (lsock->id * 1000 + ++s_ID_Counter) * 1000;
  1188.     {{ /* accept next connection */
  1189.         SOCK_socklen_t addrlen = (SOCK_socklen_t) sizeof(addr);
  1190.         memset(&addr, 0, sizeof(addr));
  1191. #ifdef HAVE_SIN_LEN
  1192.         addr.sin_len = sizeof(addr);
  1193. #endif
  1194.         if ((x_sock = accept(lsock->sock, (struct sockaddr*) &addr, &addrlen))
  1195.             == SOCK_INVALID) {
  1196.             int x_errno = SOCK_ERRNO;
  1197.             CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1198.                                ("LSOCK#%u[%u]: [LSOCK::Accept] "
  1199.                                 " Failed accept()", lsock->id,
  1200.                                 (unsigned int) lsock->sock));
  1201.             return eIO_Unknown;
  1202.         }
  1203.         lsock->n_accept++;
  1204.         assert(addr.sin_family == AF_INET);
  1205.         /* man accept(2) notes that non-blocking state may not be inherited */
  1206.         if ( !s_SetNonblock(x_sock, 1/*true*/) ) {
  1207.             CORE_LOGF(eLOG_Error, ("SOCK#%u[%u]: [LSOCK::Accept]  Cannot"
  1208.                                    " set accepted socket to non-blocking mode",
  1209.                                    x_id, (unsigned int) x_sock));
  1210.             SOCK_CLOSE(x_sock);
  1211.             return eIO_Unknown;
  1212.         }
  1213.         if (s_ReuseAddress  &&  !s_SetReuseAddress(x_sock, 1/*true*/)) {
  1214.             int x_errno = SOCK_ERRNO;
  1215.             CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
  1216.                                ("SOCK#%u[%u]: [LSOCK::Accept] "
  1217.                                 " Failed setsockopt(REUSEADDR)",
  1218.                                 x_id, (unsigned int) x_sock));
  1219.         }
  1220.     }}
  1221.     /* create new SOCK structure */
  1222.     if ( !(*sock = (SOCK) calloc(1, sizeof(**sock))) ) {
  1223.         SOCK_CLOSE(x_sock);
  1224.         return eIO_Unknown;
  1225.     }
  1226.     /* success */
  1227.     (*sock)->sock     = x_sock;
  1228.     (*sock)->id       = x_id;
  1229.     (*sock)->host     = addr.sin_addr.s_addr;
  1230.     (*sock)->port     = addr.sin_port;
  1231.     (*sock)->log      = lsock->log;
  1232.     (*sock)->type     = eSOCK_ServerSide;
  1233.     (*sock)->r_on_w   = eDefault;
  1234.     (*sock)->i_on_sig = eDefault;
  1235.     (*sock)->r_status = eIO_Success;
  1236.     (*sock)->eof      = 0/*false*/;
  1237.     (*sock)->w_status = eIO_Success;
  1238.     (*sock)->pending  = 0/*connected*/;
  1239.     /* all timeouts zeroed - infinite */
  1240.     BUF_SetChunkSize(&(*sock)->r_buf, SOCK_BUF_CHUNK_SIZE);
  1241.     /* w_buf is unused for accepted sockets */
  1242.     /* statistics & logging */
  1243.     if (lsock->log == eOn  ||  (lsock->log == eDefault  &&  s_Log == eOn))
  1244.         s_DoLog(*sock, eIO_Open, 0, 0, (struct sockaddr*) &addr);
  1245.     return eIO_Success;
  1246. }
  1247. extern EIO_Status LSOCK_Close(LSOCK lsock)
  1248. {
  1249.     EIO_Status status;
  1250.     if (lsock->sock == SOCK_INVALID) {
  1251.         CORE_LOGF(eLOG_Error, ("LSOCK#%u[?]: [LSOCK::Close] "
  1252.                                " Invalid socket", lsock->id));
  1253.         assert(0);
  1254.         return eIO_Unknown;
  1255.     }
  1256.     /* set the socket back to blocking mode */
  1257.     if ( !s_SetNonblock(lsock->sock, 0/*false*/) ) {
  1258.         CORE_LOGF(eLOG_Warning, ("LSOCK#%u[%u]: [LSOCK::Close] "
  1259.                                  " Cannot set socket back to blocking mode",
  1260.                                  lsock->id, (unsigned int) lsock->sock));
  1261.     }
  1262.     /* statistics & logging */
  1263.     if (lsock->log == eOn  ||  (lsock->log == eDefault  &&  s_Log == eOn)) {
  1264.         CORE_LOGF(eLOG_Trace, ("LSOCK#%u[%u]: Closing at port :%hu "
  1265.                                "(%u accept%s total)", lsock->id,
  1266.                                (unsigned int) lsock->sock, lsock->port,
  1267.                                lsock->n_accept, lsock->n_accept == 1? "":"s"));
  1268.     }
  1269.     status = eIO_Success;
  1270.     for (;;) { /* close persistently - retry if interrupted by a signal */
  1271.         /* success */
  1272.         if (SOCK_CLOSE(lsock->sock) == 0)
  1273.             break;
  1274.         /* error */
  1275.         if (SOCK_ERRNO != SOCK_EINTR) {
  1276.             int x_errno = SOCK_ERRNO;
  1277.             CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1278.                                ("LSOCK#%u[%u]: [LSOCK::Close]  Failed close()",
  1279.                                 lsock->id, (unsigned int) lsock->sock));
  1280.             status = eIO_Unknown;
  1281.             break;
  1282.         }
  1283.     }
  1284.     /* cleanup & return */
  1285.     lsock->sock = SOCK_INVALID;
  1286.     free(lsock);
  1287.     return status;
  1288. }
  1289. extern EIO_Status LSOCK_GetOSHandle(LSOCK  lsock,
  1290.                                     void*  handle,
  1291.                                     size_t handle_size)
  1292. {
  1293.     if (!handle  ||  handle_size != sizeof(lsock->sock)) {
  1294.         CORE_LOGF(eLOG_Error, ("LSOCK#%u[%u]: [LSOCK::GetOSHandle] "
  1295.                                " Invalid handle %s%lu", lsock->id,
  1296.                                (unsigned int) lsock->sock, handle? "size ": "",
  1297.                                handle ? (unsigned long) handle_size : 0));
  1298.         assert(0);
  1299.         return eIO_InvalidArg;
  1300.     }
  1301.     memcpy(handle, &lsock->sock, handle_size);
  1302.     return lsock->sock == SOCK_INVALID ? eIO_Closed : eIO_Success;
  1303. }
  1304. /******************************************************************************
  1305.  *  SOCKET
  1306.  */
  1307. /* connect() could be async/interrupted by a signal or just cannot be
  1308.  * established immediately;  yet, it must have been in progress
  1309.  * (asynchronous), so wait here for it to succeed (become writable).
  1310.  */
  1311. static EIO_Status s_IsConnected(SOCK                  sock,
  1312.                                 const struct timeval* tv,
  1313.                                 int*                  x_errno,
  1314.                                 int/*bool*/           writeable)
  1315. {
  1316.     EIO_Status     status;
  1317. #if defined(NCBI_OS_UNIX) || defined(NCBI_OS_MSWIN)
  1318.     SOCK_socklen_t x_len = (SOCK_socklen_t) sizeof(*x_errno);
  1319. #endif /*NCBI_OS_UNIX || NCBI_OS_MSWIN*/
  1320.     SSOCK_Poll     poll;
  1321.     *x_errno = 0;
  1322.     if (sock->w_status == eIO_Closed)
  1323.         return eIO_Closed;
  1324.     if ( !writeable ) {
  1325.         poll.sock   = sock;
  1326.         poll.event  = eIO_Write;
  1327.         poll.revent = eIO_Open;
  1328.         status      = s_Select(1, &poll, tv);
  1329.         if (status == eIO_Timeout)
  1330.             return status;
  1331.     } else {
  1332.         status      = eIO_Success;
  1333.         poll.revent = eIO_Write;
  1334.     }
  1335. #if defined(NCBI_OS_UNIX) || defined(NCBI_OS_MSWIN)
  1336.     if (status == eIO_Success  &&
  1337.         (getsockopt(sock->sock, SOL_SOCKET, SO_ERROR, (void*) x_errno, &x_len)
  1338.          ||  *x_errno != 0)) {
  1339.         status = eIO_Unknown;
  1340.     }
  1341. #endif /*NCBI_OS_UNIX || NCBI_OS_MSWIN*/
  1342.     if (status != eIO_Success  ||  poll.revent != eIO_Write) {
  1343.         if ( !*x_errno )
  1344.             *x_errno = SOCK_ERRNO;
  1345.         if (*x_errno == SOCK_ECONNREFUSED)
  1346.             sock->r_status = sock->w_status = status = eIO_Closed;
  1347.         else if (status == eIO_Success)
  1348.             status = eIO_Unknown;
  1349.     } else if (s_ReuseAddress  &&  !s_SetReuseAddress(sock->sock, 1/*true*/)) {
  1350.         int x_errno = SOCK_ERRNO;
  1351.         char _id[32];
  1352.         CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
  1353.                            ("%s[SOCK::s_IsConnected]  Failed "
  1354.                             "setsockopt(REUSEADDR)", s_ID(sock, _id)));
  1355.     }
  1356.     return status;
  1357. }
  1358. /* Connect the (pre-allocated) socket to the specified "host:port" peer.
  1359.  * HINT: if "host" is NULL then assume(!) that the "sock" already exists,
  1360.  *       and connect to the same host;  the same is for zero "port".
  1361.  * NOTE: Client-side stream sockets only.
  1362.  */
  1363. static EIO_Status s_Connect(SOCK            sock,
  1364.                             const char*     host,
  1365.                             unsigned short  port,
  1366.                             const STimeout* timeout)
  1367. {
  1368.     char               _id[32];
  1369.     int                x_errno;
  1370.     TSOCK_Handle       x_sock;
  1371.     unsigned int       x_host;
  1372.     unsigned short     x_port;
  1373.     struct sockaddr_in peer;
  1374.     int                n;
  1375.     assert(sock->type == eSOCK_ClientSide);
  1376. #ifdef NCBI_OS_UNIX
  1377.     assert(!sock->file[0]);
  1378. #endif /*NCBI_OS_UNIX*/
  1379.     /* initialize internals */
  1380.     verify(s_Initialized  ||  SOCK_InitializeAPI() == eIO_Success);
  1381.     /* get address of the remote host (assume the same host if it is NULL) */
  1382.     x_host = host  &&  *host ? SOCK_gethostbyname(host) : sock->host;
  1383.     if ( !x_host ) {
  1384.         CORE_LOGF(eLOG_Error, ("%s[SOCK::s_Connect]  Failed "
  1385.                                "SOCK_gethostbyname("%.64s")",
  1386.                                s_ID(sock, _id), host));
  1387.         return eIO_Unknown;
  1388.     }
  1389.     /* set the port to connect to (assume the same port if "port" is zero) */
  1390.     x_port = (unsigned short) (port ? htons(port) : sock->port);
  1391.     /* create new socket */
  1392.     if ((x_sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCK_INVALID) {
  1393.         int x_errno = SOCK_ERRNO;
  1394.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1395.                            ("%s[SOCK::s_Connect]  Cannot create socket",
  1396.                             s_ID(sock, _id)));
  1397.         return eIO_Unknown;
  1398.     }
  1399.     sock->sock = x_sock;
  1400.     /* set the socket I/O to non-blocking mode */
  1401.     if ( !s_SetNonblock(x_sock, 1/*true*/) ) {
  1402.         CORE_LOGF(eLOG_Error, ("%s[SOCK::s_Connect]  Cannot set socket to "
  1403.                                "non-blocking mode", s_ID(sock, _id)));
  1404.         sock->sock = SOCK_INVALID;
  1405.         SOCK_CLOSE(x_sock);
  1406.         return eIO_Unknown;
  1407.     }
  1408.     /* fill in the server "addr" to connect to */
  1409.     memset(&peer, 0, sizeof(peer));
  1410.     peer.sin_family      = AF_INET;
  1411.     peer.sin_addr.s_addr = x_host;
  1412.     peer.sin_port        = x_port;
  1413. #ifdef HAVE_SIN_LEN
  1414.     peer.sin_len         = sizeof(peer);
  1415. #endif /*HAVE_SIN_LEN*/
  1416.     /* statistics & logging */
  1417.     if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
  1418.         s_DoLog(sock, eIO_Open, 0, 0, (struct sockaddr*) &peer);
  1419.     /* establish connection to the peer */
  1420.     sock->r_status  = eIO_Success;
  1421.     sock->eof       = 0/*false*/;
  1422.     sock->w_status  = eIO_Success;
  1423.     assert(sock->w_len == 0);
  1424.     for (n = 0; ; n = 1) {
  1425.         if (connect(x_sock, (struct sockaddr*) &peer, sizeof(peer)) == 0) {
  1426.             x_errno = 0;
  1427.             break;
  1428.         }
  1429.         x_errno = SOCK_ERRNO;
  1430.         if (x_errno != SOCK_EINTR  ||  sock->i_on_sig == eOn  ||
  1431.             (sock->i_on_sig == eDefault  &&  s_InterruptOnSignal))
  1432.             break;
  1433.     }
  1434.     if (x_errno) {
  1435.         if ((n != 0 || x_errno != SOCK_EINPROGRESS)  &&
  1436.             (n == 0 || x_errno != SOCK_EALREADY)     &&
  1437.             x_errno != SOCK_EWOULDBLOCK) {
  1438.             if (x_errno != SOCK_EINTR) {
  1439.                 char addr[80];
  1440.                 HostPortToString(x_host, ntohs(x_port), addr, sizeof(addr));
  1441.                 CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1442.                                    ("%s[SOCK::s_Connect]  Failed connect() "
  1443.                                     "to %s", s_ID(sock, _id), addr));
  1444.             }
  1445.             sock->sock = SOCK_INVALID;
  1446.             SOCK_CLOSE(x_sock);
  1447.             /* unrecoverable error */
  1448.             return x_errno == SOCK_EINTR ? eIO_Interrupt : eIO_Unknown;
  1449.         }
  1450.         if (!timeout  ||  timeout->sec  ||  timeout->usec) {
  1451.             EIO_Status     status;
  1452.             struct timeval tv;
  1453.             status = s_IsConnected(sock, s_to2tv(timeout, &tv), &x_errno, 0);
  1454.             if (status != eIO_Success) {
  1455.                 char addr[80];
  1456.                 HostPortToString(x_host, ntohs(x_port), addr, sizeof(addr));
  1457.                 CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1458.                                    ("%s[SOCK::s_Connect]  Failed pending "
  1459.                                     "connect() to %s (%s)", s_ID(sock, _id),
  1460.                                     addr, IO_StatusStr(status)));
  1461.                 sock->sock = SOCK_INVALID;
  1462.                 SOCK_CLOSE(x_sock);
  1463.                 return status;
  1464.             }
  1465.             sock->pending = 0/*connected*/;
  1466.         } else
  1467.             sock->pending = 1/*not yet connected*/;
  1468.     } else
  1469.         sock->pending = 0/*connected*/;
  1470.     /* success: do not change any timeouts */
  1471.     sock->host  = x_host;
  1472.     sock->port  = x_port;
  1473.     sock->w_len = BUF_Size(sock->w_buf);
  1474.     return eIO_Success;
  1475. }
  1476. /* To allow emulating "peek" using the NCBI data buffering.
  1477.  * (MSG_PEEK is not implemented on Mac, and it is poorly implemented
  1478.  * on Win32, so we had to implement this feature by ourselves.)
  1479.  * NOTE: This call is for stream sockets only.
  1480.  */
  1481. static int s_Recv(SOCK        sock,
  1482.                   void*       buffer,
  1483.                   size_t      size,
  1484.                   int/*bool*/ peek)
  1485. {
  1486.     char*  x_buffer = (char*) buffer;
  1487.     char   xx_buffer[4096];
  1488.     size_t n_read;
  1489.     assert(sock->type != eSOCK_Datagram  &&  !sock->pending);
  1490.     if ( !size ) {
  1491.         /* internal upread use only */
  1492.         assert(sock->r_status != eIO_Closed && !sock->eof && peek && !buffer);
  1493.         n_read = 0;
  1494.     } else {
  1495.         /* read (or peek) from the internal buffer */
  1496.         n_read = peek ?
  1497.             BUF_Peek(sock->r_buf, x_buffer, size) :
  1498.             BUF_Read(sock->r_buf, x_buffer, size);
  1499.         if ((n_read  &&  (n_read == size  ||  !peek))  ||
  1500.             sock->r_status == eIO_Closed  ||  sock->eof) {
  1501.             return (int) n_read;
  1502.         }
  1503.     }
  1504.     /* read (not just peek) from the socket */
  1505.     do {
  1506.         size_t n_todo;
  1507.         int    x_read;
  1508.         if ( !size ) {
  1509.             /* internal upread call -- read out as much as possible */
  1510.             n_todo    = sizeof(xx_buffer);
  1511.             x_buffer  = xx_buffer;
  1512.         } else if ( !buffer ) {
  1513.             /* read to the temporary buffer (to store or discard later) */
  1514.             n_todo    = size - n_read;
  1515.             if (n_todo > sizeof(xx_buffer))
  1516.                 n_todo = sizeof(xx_buffer);
  1517.             x_buffer  = xx_buffer;
  1518.         } else {
  1519.             /* read to the data buffer provided by user */
  1520.             n_todo    = size - n_read;
  1521.             x_buffer += n_read;
  1522.         }
  1523.         /* recv */
  1524.         x_read = recv(sock->sock, x_buffer, n_todo, 0);
  1525.         /* success */
  1526.         if (x_read >= 0  ||
  1527.             (x_read < 0  &&  (SOCK_ERRNO == SOCK_ENOTCONN      ||
  1528.                               SOCK_ERRNO == SOCK_ECONNRESET    ||
  1529.                               SOCK_ERRNO == SOCK_ECONNABORTED  ||
  1530.                               SOCK_ERRNO == SOCK_ENETRESET))) {
  1531.             /* statistics & logging */
  1532.             if (sock->log == eOn  ||  (sock->log == eDefault && s_Log == eOn)){
  1533.                 s_DoLog(sock, eIO_Read, x_read >= 0 ? x_buffer : 0,
  1534.                         (size_t)(x_read < 0 ? 0 : x_read), 0);
  1535.             }
  1536.             if (x_read <= 0) {
  1537.                 /* catch EOF/failure */
  1538.                 sock->eof = 1/*true*/;
  1539.                 if (x_read == 0)
  1540.                     sock->r_status = eIO_Success;
  1541.                 else
  1542.                     sock->r_status = sock->w_status = eIO_Closed;
  1543.                 break;
  1544.             }
  1545.         } else {
  1546.             /* some error */
  1547.             int x_errno = SOCK_ERRNO;
  1548.             if (x_errno != SOCK_EWOULDBLOCK  &&
  1549.                 x_errno != SOCK_EAGAIN       &&
  1550.                 x_errno != SOCK_EINTR) {
  1551.                 /* catch unknown ERROR */
  1552.                 sock->r_status = eIO_Unknown;
  1553.                 CORE_LOGF_ERRNO_EX(eLOG_Trace, x_errno, SOCK_STRERROR(x_errno),
  1554.                                    ("%s[SOCK::s_Recv] "
  1555.                                     " Failed recv()", s_ID(sock, xx_buffer)));
  1556.             }
  1557.             return n_read ? (int) n_read : -1;
  1558.         }
  1559.         assert(x_read > 0);
  1560.         /* if "peek" -- store the new read data in the internal input buffer */
  1561.         if (peek  &&  !BUF_Write(&sock->r_buf, x_buffer, (size_t) x_read)) {
  1562.             CORE_LOGF_ERRNO(eLOG_Error, errno,
  1563.                             ("%s[SOCK::s_Recv]  Cannot store data in "
  1564.                              "peek buffer", s_ID(sock, xx_buffer)));
  1565.             sock->eof      = 1/*failure*/;
  1566.             sock->r_status = eIO_Closed;
  1567.             break;
  1568.         }
  1569.         /* successful read */
  1570.         sock->r_status = eIO_Success;
  1571.         sock->n_read  += x_read;
  1572.         n_read        += x_read;
  1573.     } while (!size  ||  (!buffer  &&  n_read < size));
  1574.     return (int) n_read;
  1575. }
  1576. static EIO_Status s_WritePending(SOCK, const struct timeval*, int);
  1577. /* s_Select() with stall protection: try pull incoming data from sockets.
  1578.  * This method returns array of polls, "revent"s of which are always
  1579.  * compatible with requested "event"s. That is, it always strips additional
  1580.  * events that s_Select() may have set to indicate additional I/O events
  1581.  * some sockets are ready for. Return eIO_Timeout if no compatible events
  1582.  * were found (all sockets are not ready for inquired respective I/O) within
  1583.  * the specified timeout (and no other socket error was flagged).
  1584.  * Return eIO_Success if at least one socket is ready. Return the number
  1585.  * of sockets that are ready via pointer argument "n_ready" (may be NULL).
  1586.  * Return other error code to indicate error condition.
  1587.  */
  1588. static EIO_Status s_SelectStallsafe(size_t                n,
  1589.                                     SSOCK_Poll            polls[],
  1590.                                     const struct timeval* tv,
  1591.                                     size_t*               n_ready)
  1592. {
  1593.     int/*bool*/ pending;
  1594.     EIO_Status  status;
  1595.     size_t      i, j;
  1596.     if ((status = s_Select(n, polls, tv)) != eIO_Success) {
  1597.         if ( n_ready )
  1598.             *n_ready = 0;
  1599.         return status;
  1600.     }
  1601.     j = 0;
  1602.     pending = 0;
  1603.     for (i = 0; i < n; i++) {
  1604.         if (polls[i].revent == eIO_Close)
  1605.             break;
  1606.         if (polls[i].revent & polls[i].event)
  1607.             break;
  1608.         if (polls[i].revent != eIO_Open  &&  !pending) {
  1609.             pending = 1;
  1610.             j = i;
  1611.         }
  1612.     }
  1613.     if (i >= n  &&  pending) {
  1614.         /* all sockets are not ready for the requested events */
  1615.         for (i = j; i < n; i++) {
  1616.             /* try to push pending writes */
  1617.             if (polls[i].event == eIO_Read  &&  polls[i].revent == eIO_Write) {
  1618.                 assert(n != 1);
  1619.                 assert(polls[i].sock->pending  ||  polls[i].sock->w_len);
  1620.                 status = s_WritePending(polls[i].sock, tv, 1/*writeable*/);
  1621.                 if (status != eIO_Success  &&  status != eIO_Timeout) {
  1622.                     polls[i].revent = eIO_Close;
  1623.                     break;
  1624.                 }
  1625.                 continue;
  1626.             }
  1627.             /* try to find an immediately readable socket */
  1628.             if (polls[i].event != eIO_Write)
  1629.                 continue;
  1630.             while (polls[i].revent == eIO_Read) {
  1631.                 assert(polls[i].sock                          &&
  1632.                        polls[i].sock->sock != SOCK_INVALID    &&
  1633.                        polls[i].sock->type != eSOCK_Datagram  &&
  1634.                        polls[i].sock->w_status != eIO_Closed  &&
  1635.                        polls[i].sock->r_status != eIO_Closed  &&
  1636.                        !polls[i].sock->eof                    &&
  1637.                        !polls[i].sock->pending                &&
  1638.                        (polls[i].sock->r_on_w == eOn
  1639.                         ||  (polls[i].sock->r_on_w == eDefault
  1640.                              &&  s_ReadOnWrite == eOn)));
  1641.                 /* try upread as much as possible data into internal buffer */
  1642.                 s_Recv(polls[i].sock, 0, 0/*infinite*/, 1/*peek*/);
  1643.                 /* then poll if writeable */
  1644.                 polls[i].revent = eIO_Open;
  1645.                 if ((status = s_Select(1, &polls[i], tv)) != eIO_Success)
  1646.                     break;
  1647.             }
  1648.             if (status != eIO_Success  ||  polls[i].revent == eIO_Write)
  1649.                 break; /*error or can write now!*/
  1650.         }
  1651.     }
  1652.     j = 0;
  1653.     for (i = 0; i < n; i++) {
  1654.         if (polls[i].revent != eIO_Close) {
  1655.             polls[i].revent = (EIO_Event)(polls[i].revent & polls[i].event);
  1656.             if (polls[i].revent != eIO_Open)
  1657.                 j++;
  1658.         } else
  1659.             j++;
  1660.     }
  1661.     if ( n_ready )
  1662.         *n_ready = j;
  1663.     return j ? eIO_Success : (status == eIO_Success ? eIO_Timeout : status);
  1664. }
  1665. static EIO_Status s_WipeRBuf(SOCK sock)
  1666. {
  1667.     EIO_Status status;
  1668.     size_t     size = BUF_Size(sock->r_buf);
  1669.     if (size  &&  BUF_Read(sock->r_buf, 0, size) != size) {
  1670.         char _id[32];
  1671.         CORE_LOGF(eLOG_Error, ("%s[SOCK::s_WipeRBuf] "
  1672.                                " Cannot drop aux. data buf", s_ID(sock, _id)));
  1673.         assert(0);
  1674.         status = eIO_Unknown;
  1675.     } else
  1676.         status = eIO_Success;
  1677.     return status;
  1678. }
  1679. /* For datagram sockets only! */
  1680. static EIO_Status s_WipeWBuf(SOCK sock)
  1681. {
  1682.     EIO_Status status;
  1683.     size_t     size = BUF_Size(sock->w_buf);
  1684.     assert(sock->type == eSOCK_Datagram);
  1685.     if (size  &&  BUF_Read(sock->w_buf, 0, size) != size) {
  1686.         char _id[32];
  1687.         CORE_LOGF(eLOG_Error, ("%s[SOCK::s_WipeWBuf] "
  1688.                                " Cannot drop aux. data buf", s_ID(sock, _id)));
  1689.         assert(0);
  1690.         status = eIO_Unknown;
  1691.     } else
  1692.         status = eIO_Success;
  1693.     sock->eof = 0;
  1694.     return status;
  1695. }
  1696. /* Write data to the socket "as is" (as many bytes at once as possible).
  1697.  * Return eIO_Success if at least some bytes were written successfully.
  1698.  * Otherwise (no bytes written) return an error code to indicate the problem.
  1699.  * NOTE: This call is for stream sockets only.
  1700.  */
  1701. static EIO_Status s_Send(SOCK        sock,
  1702.                          const void* buf,
  1703.                          size_t      size,
  1704.                          size_t*     n_written)
  1705. {
  1706.     char _id[32];
  1707.     assert(size > 0  &&  sock->type != eSOCK_Datagram  &&  *n_written == 0);
  1708.     for (;;) { /* optionally retry if interrupted by a signal */
  1709.         /* try to write */
  1710.         int x_written = send(sock->sock, (void*) buf, size, 0);
  1711.         int x_errno;
  1712.         if (x_written > 0) {
  1713.             /* statistics & logging */
  1714.             if (sock->log == eOn  ||  (sock->log == eDefault && s_Log == eOn))
  1715.                 s_DoLog(sock, eIO_Write, buf, (size_t) x_written, 0);
  1716.             sock->n_written += x_written;
  1717.             *n_written = x_written;
  1718.             sock->w_status = eIO_Success;
  1719.             break/*done*/;
  1720.         }
  1721.         x_errno = SOCK_ERRNO;
  1722.         /* don't want to handle all possible errors... let them be "unknown" */
  1723.         sock->w_status = eIO_Unknown;
  1724.         /* blocked -- retry if unblocked before the timeout expires */
  1725.         /* (use stall protection if specified) */
  1726.         if (x_errno == SOCK_EWOULDBLOCK  ||  x_errno == SOCK_EAGAIN) {
  1727.             EIO_Status status;
  1728.             SSOCK_Poll poll;
  1729.             poll.sock   = sock;
  1730.             poll.event  = eIO_Write;
  1731.             poll.revent = eIO_Open;
  1732.             /* stall protection:  try pull incoming data from the socket */
  1733.             status = s_SelectStallsafe(1, &poll, sock->w_timeout, 0);
  1734.             if (status != eIO_Success)
  1735.                 return status;
  1736.             if (poll.revent == eIO_Close)
  1737.                 return eIO_Unknown;
  1738.             assert(poll.revent == eIO_Write);
  1739.             continue;
  1740.         }
  1741.         if (x_errno != SOCK_EINTR) {
  1742.             /* forcibly closed by peer or shut down? */
  1743.             if (x_errno != SOCK_EPIPE      &&  x_errno != SOCK_ENOTCONN     &&
  1744.                 x_errno != SOCK_ECONNRESET &&  x_errno != SOCK_ECONNABORTED &&
  1745.                 x_errno != SOCK_ENETRESET) {
  1746.                 CORE_LOGF_ERRNO_EX(eLOG_Trace, x_errno, SOCK_STRERROR(x_errno),
  1747.                                    ("%s[SOCK::s_Send] "
  1748.                                     " Failed send()", s_ID(sock, _id)));
  1749.                 break;
  1750.             }
  1751.             sock->w_status = eIO_Closed;
  1752.             if (x_errno != SOCK_EPIPE)
  1753.                 sock->r_status = eIO_Closed;
  1754.             if (sock->log == eOn  ||  (sock->log == eDefault && s_Log == eOn))
  1755.                 s_DoLog(sock, eIO_Write, 0, 0, 0);
  1756.             break;
  1757.         }
  1758.         if (sock->i_on_sig == eOn  ||
  1759.             (sock->i_on_sig == eDefault  &&  s_InterruptOnSignal == eOn)) {
  1760.             sock->w_status = eIO_Interrupt;
  1761.             break;
  1762.         }
  1763.     }
  1764.     return sock->w_status;
  1765. }
  1766. /* Wrapper for s_Send() that slices the output buffer for some brain-dead
  1767.  * systems (e.g. old Macs) that cannot handle large data chunks in "send()".
  1768.  * Return eIO_Success if some data were successfully sent; other
  1769.  * error code if no data were sent at all.
  1770.  */
  1771. #ifdef SOCK_WRITE_SLICE
  1772. static EIO_Status s_WriteSliced(SOCK        sock,
  1773.                                 const void* buf,
  1774.                                 size_t      size,
  1775.                                 size_t*     n_written)
  1776. {
  1777.     /* split output buffer by slices (of size <= SOCK_WRITE_SLICE)
  1778.      * before writing to the socket
  1779.      */
  1780.     EIO_Status status;
  1781.     assert(size > 0  &&  *n_written == 0);
  1782.     do {
  1783.         size_t n_io = size > SOCK_WRITE_SLICE ? SOCK_WRITE_SLICE : size;
  1784.         size_t n_io_done = 0;
  1785.         status = s_Send(sock, (char*) buf + *n_written, n_io, &n_io_done);
  1786.         if (status != eIO_Success)
  1787.             break;
  1788.         *n_written += n_io_done;
  1789.         if (n_io != n_io_done)
  1790.             break;
  1791.         size       -= n_io_done;
  1792.     } while ( size );
  1793.     return status;
  1794. }
  1795. #else
  1796. #  define s_WriteSliced s_Send
  1797. #endif /*SOCK_WRITE_SLICE*/
  1798. static EIO_Status s_WritePending(SOCK                  sock,
  1799.                                  const struct timeval* tv,
  1800.                                  int/*bool*/           writeable)
  1801. {
  1802.     const struct timeval* x_tv;
  1803.     EIO_Status status;
  1804.     int x_errno;
  1805.     size_t off;
  1806.     assert(sock->type != eSOCK_Datagram  &&  sock->sock != SOCK_INVALID);
  1807.     if ( sock->pending ) {
  1808.         status = s_IsConnected(sock, tv, &x_errno, writeable);
  1809.         if (status != eIO_Success) {
  1810.             if (status != eIO_Timeout) {
  1811.                 char addr[80];
  1812.                 char  _id[32];
  1813. #ifdef NCBI_OS_UNIX
  1814.                 if ( sock->file[0] ) {
  1815.                     size_t      len = strlen(sock->file);
  1816.                     int/*bool*/ trunc = len > sizeof(addr) - 3 ? 1 : 0;
  1817.                     sprintf(addr, ""%s%.*s"", trunc ? "..." : "", 
  1818.                             (int)(trunc ? sizeof(addr) - 6 : len),
  1819.                             &sock->file[trunc ? len - sizeof(addr) + 6 : 0]);
  1820.                 } else
  1821. #endif /*NCBI_OS_UNIX*/
  1822.                     HostPortToString(sock->host, ntohs(sock->port),
  1823.                                      addr, sizeof(addr));
  1824.                 CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1825.                                    ("%s[SOCK::s_WritePending]  Failed pending "
  1826.                                     "connect() to %s", s_ID(sock, _id), addr));
  1827.                 sock->w_status = status;
  1828.             }
  1829.             return status;
  1830.         }
  1831.         sock->pending = 0/*connected*/;
  1832.     }
  1833.     if (sock->w_len == 0  ||  sock->w_status == eIO_Closed)
  1834.         return eIO_Success;
  1835.     x_tv = sock->w_timeout;
  1836.     sock->w_timeout = tv;
  1837.     off = BUF_Size(sock->w_buf) - sock->w_len;
  1838.     do {
  1839.         char   buf[4096];
  1840.         size_t n_written = 0;
  1841.         size_t n_write = BUF_PeekAt(sock->w_buf, off, buf, sizeof(buf));
  1842.         status = s_WriteSliced(sock, buf, n_write, &n_written);
  1843.         if (status != eIO_Success)
  1844.             break;
  1845.         sock->w_len -= n_written;
  1846.         off         += n_written;
  1847.     } while ( sock->w_len );
  1848.     sock->w_timeout = x_tv;
  1849.     assert((sock->w_len != 0)  ==  (status != eIO_Success));
  1850.     return status;
  1851. }
  1852. /* Read/Peek data from the socket. Always return eIO_Success if some data
  1853.  * were read (regardless of socket conditions that may include EOF/error).
  1854.  * Return other (error) code only if no data at all could be obtained.
  1855.  */
  1856. static EIO_Status s_Read(SOCK        sock,
  1857.                          void*       buf,
  1858.                          size_t      size,
  1859.                          size_t*     n_read,
  1860.                          int/*bool*/ peek)
  1861. {
  1862.     EIO_Status status;
  1863.     *n_read = 0;
  1864.     if (sock->type == eSOCK_Datagram) {
  1865.         *n_read = peek ?
  1866.             BUF_Peek(sock->r_buf, buf, size) :
  1867.             BUF_Read(sock->r_buf, buf, size);
  1868.         sock->r_status = *n_read || !size ? eIO_Success : eIO_Closed;
  1869.         return sock->r_status;
  1870.     }
  1871.     status = s_WritePending(sock, sock->r_timeout, 0);
  1872.     if (sock->pending || !size)
  1873.         return sock->pending ? status : s_Status(sock, eIO_Read);
  1874.     for (;;) { /* retry if either blocked or interrupted (optional) */
  1875.         /* try to read */
  1876.         int x_read = s_Recv(sock, buf, size, peek);
  1877.         int x_errno;
  1878.         if (x_read > 0) {
  1879.             assert((size_t) x_read <= size);
  1880.             *n_read = x_read;
  1881.             return eIO_Success;
  1882.         }
  1883.         if (sock->r_status == eIO_Unknown)
  1884.             break;
  1885.         if (sock->r_status == eIO_Closed  ||  sock->eof) {
  1886.             if ( !sock->eof ) {
  1887.                 char _id[32];
  1888.                 CORE_LOGF(eLOG_Trace, ("%s[SOCK::s_Read]  Socket has already "
  1889.                                        "been shut down for reading",
  1890.                                        s_ID(sock, _id)));
  1891.             }
  1892.             return eIO_Closed;
  1893.         }
  1894.         x_errno = SOCK_ERRNO;
  1895.         /* blocked -- wait for data to come;  exit if timeout/error */
  1896.         if (x_errno == SOCK_EWOULDBLOCK  ||  x_errno == SOCK_EAGAIN) {
  1897.             const struct timeval* tv = sock->r_timeout;
  1898.             SSOCK_Poll poll;
  1899.             if (tv  &&  !tv->tv_sec  &&  !tv->tv_usec)
  1900.                 return eIO_Timeout;
  1901.             poll.sock   = sock;
  1902.             poll.event  = eIO_Read;
  1903.             poll.revent = eIO_Open;
  1904.             if ((status = s_Select(1, &poll, tv)) != eIO_Success)
  1905.                 return status;
  1906.             if (poll.revent == eIO_Close)
  1907.                 break;
  1908.             assert(poll.event == eIO_Read  &&  poll.revent == eIO_Read);
  1909.             continue;
  1910.         }
  1911.         if (x_errno != SOCK_EINTR)
  1912.             break;
  1913.         if (sock->i_on_sig == eOn  ||
  1914.             (sock->i_on_sig == eDefault  &&  s_InterruptOnSignal == eOn)) {
  1915.             sock->r_status = eIO_Interrupt;
  1916.             break;
  1917.         }
  1918.     }
  1919.     /* don't want to handle all possible errors... let them be "unknown" */
  1920.     return eIO_Unknown;
  1921. }
  1922. /* Write to the socket. Return eIO_Success if some data were written.
  1923.  * Return other (error) code only if no data at all could be written.
  1924.  */
  1925. static EIO_Status s_Write(SOCK        sock,
  1926.                           const void* buf,
  1927.                           size_t      size,
  1928.                           size_t*     n_written)
  1929. {
  1930.     EIO_Status status;
  1931.     *n_written = 0;
  1932.     if (sock->type == eSOCK_Datagram) {
  1933.         if ( sock->eof )
  1934.             s_WipeWBuf(sock);
  1935.         if ( BUF_Write(&sock->w_buf, buf, size) ) {
  1936.             sock->w_status = eIO_Success;
  1937.             *n_written = size;
  1938.         } else
  1939.             sock->w_status = eIO_Unknown;
  1940.         return sock->w_status;
  1941.     }
  1942.     if (sock->w_status == eIO_Closed) {
  1943.         if (size != 0) {
  1944.             char _id[32];
  1945.             CORE_LOGF(eLOG_Trace, ("%s[SOCK::s_Write]  Socket has already "
  1946.                                    "been shut down for writing",
  1947.                                    s_ID(sock, _id)));
  1948.         }
  1949.         return eIO_Closed;
  1950.     }
  1951.     if ((status = s_WritePending(sock, sock->w_timeout, 0)) != eIO_Success) {
  1952.         if (status == eIO_Timeout  ||  status == eIO_Closed)
  1953.             return status;
  1954.         return size ? status : eIO_Success;
  1955.     }
  1956.     assert(sock->w_len == 0);
  1957.     return size ? s_WriteSliced(sock, buf, size, n_written) : eIO_Success;
  1958. }
  1959. /* For non-datagram sockets only */
  1960. static EIO_Status s_Shutdown(SOCK                  sock,
  1961.                              EIO_Event             how,
  1962.                              const struct timeval* tv)
  1963. {
  1964.     EIO_Status status;
  1965.     char      _id[32];
  1966.     int        x_how;
  1967.     assert(sock->type != eSOCK_Datagram);
  1968.     switch ( how ) {
  1969.     case eIO_Read:
  1970.         if ( sock->eof ) {
  1971.             /* hit EOF (and may be not yet shut down) -- so, flag it as been
  1972.              * shut down, but do not call the actual system shutdown(),
  1973.              * as it can cause smart OS'es like Linux to complain
  1974.              */
  1975.             sock->eof = 0/*false*/;
  1976.             sock->r_status = eIO_Closed;
  1977.         }
  1978.         if (sock->r_status == eIO_Closed)
  1979.             return eIO_Success;  /* has been shut down already */
  1980.         x_how = SOCK_SHUTDOWN_RD;
  1981.         sock->r_status = eIO_Closed;
  1982. #ifdef NCBI_OS_MSWIN
  1983.         /* see comments at the end of eIO_Write case */
  1984.         return eIO_Success;
  1985. #endif /*NCBI_OS_MSWIN*/
  1986.         break;
  1987.     case eIO_Write:
  1988.         if (sock->w_status == eIO_Closed)
  1989.             return eIO_Success;  /* has been shut down already */
  1990.         if ((status = s_WritePending(sock, tv, 0)) != eIO_Success
  1991.             &&  (!tv  ||  tv->tv_sec  ||  tv->tv_usec)) {
  1992.             CORE_LOGF(eLOG_Warning, ("%s[SOCK::s_Shutdown]  Shutting down for "
  1993.                                      "write with some output pending (%s)",
  1994.                                      s_ID(sock, _id), IO_StatusStr(status)));
  1995.         }
  1996.         x_how = SOCK_SHUTDOWN_WR;
  1997.         sock->w_status = eIO_Closed;
  1998. #ifdef NCBI_OS_MSWIN
  1999.         /*  on MS-Win, socket shutdown on writing apparently messes up (?!)  *
  2000.          *  with the later reading, esp. when reading a lot of data...       */
  2001.         return eIO_Success;
  2002. #endif /*NCBI_OS_MSWIN*/
  2003.         break;
  2004.     case eIO_ReadWrite:
  2005. #ifdef NCBI_OS_MSWIN
  2006.         if (sock->r_status == eIO_Closed  &&  sock->w_status == eIO_Closed)
  2007.             return eIO_Success;
  2008.         if (sock->w_status != eIO_Closed  &&
  2009.             (status = s_WritePending(sock, tv, 0)) != eIO_Success
  2010.             &&  (!tv ||  tv->tv_sec  ||  tv->tv_usec)) {
  2011.             CORE_LOGF(eLOG_Warning, ("%s[SOCK::s_Shutdown]  Shutting down for "
  2012.                                      "R/W with some output pending (%s)",
  2013.                                      s_ID(sock, _id), IO_StatusStr(status)));