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

生物技术

开发平台:

C/C++

  1.         }
  2.         x_how = SOCK_SHUTDOWN_RDWR;
  3.         sock->eof = 0/*false*/;
  4.         sock->r_status = sock->w_status = eIO_Closed;
  5.         break;
  6. #else
  7.         {{
  8.             EIO_Status sw = s_Shutdown(sock, eIO_Write, tv);
  9.             EIO_Status sr = s_Shutdown(sock, eIO_Read,  tv);
  10.             if (sw != eIO_Success  ||  sr != eIO_Success)
  11.                 return (sw == eIO_Success ? sr :
  12.                         sr == eIO_Success ? sw : eIO_Unknown);
  13.         }}
  14.         return eIO_Success;
  15. #endif /*NCBI_OS_MSWIN*/
  16.     default:
  17.         CORE_LOGF(eLOG_Error, ("%s[SOCK::s_Shutdown]  Invalid direction %u",
  18.                                s_ID(sock, _id), (unsigned int) how));
  19.         return eIO_InvalidArg;
  20.     }
  21.     if (SOCK_SHUTDOWN(sock->sock, x_how) != 0) {
  22.         int x_errno = SOCK_ERRNO;
  23.         if (
  24. #if defined(NCBI_OS_LINUX)/*bug in the Linux kernel to report*/  || 
  25.     defined(NCBI_OS_IRIX)                                        || 
  26.     defined(NCBI_OS_OSF1)
  27.             x_errno != SOCK_ENOTCONN
  28. #else
  29.             x_errno != SOCK_ENOTCONN  ||  sock->pending
  30. #endif /*UNIX flavors*/
  31.             )
  32.             CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
  33.                                ("%s[SOCK::s_Shutdown]  Failed shutdown(%s)",
  34.                                 s_ID(sock, _id), how == eIO_Read ? "READ" :
  35.                                 how == eIO_Write ? "WRITE" : "READ/WRITE"));
  36.     }
  37.     return eIO_Success;
  38. }
  39. /* Close the socket
  40.  */
  41. static EIO_Status s_Close(SOCK sock)
  42. {
  43.     EIO_Status status;
  44.     char      _id[32];
  45.     /* reset the auxiliary data buffers */
  46.     s_WipeRBuf(sock);
  47.     if (sock->type == eSOCK_Datagram) {
  48.         s_WipeWBuf(sock);
  49.     } else if (sock->type != eSOCK_ServerSideKeep) {
  50.         /* set the close()'s linger period be equal to the close timeout */
  51. #if (defined(NCBI_OS_UNIX) && !defined(NCBI_OS_BEOS)) || defined(NCBI_OS_MSWIN)
  52.         /* setsockopt() is not implemented for MAC (MIT socket emulation lib)*/
  53.         if (sock->w_status != eIO_Closed  &&  (!sock->c_timeout        ||
  54.                                                sock->c_timeout->tv_sec ||
  55.                                                sock->c_timeout->tv_usec)) {
  56.             const struct timeval* tv = sock->c_timeout;
  57.             unsigned int  tmo;
  58.             struct linger lgr;
  59.             if (!tv)
  60.                 tmo = 120; /*this is a standard TCP TTL, 2 minutes*/
  61.             else if (!(tmo = tv->tv_sec + (tv->tv_usec + 500000)/1000000))
  62.                 tmo = 1;
  63.             lgr.l_onoff  = 1;
  64.             lgr.l_linger = tmo;
  65.             if (setsockopt(sock->sock, SOL_SOCKET, SO_LINGER,
  66.                            (char*) &lgr, sizeof(lgr)) != 0) {
  67.                 int x_errno = SOCK_ERRNO;
  68.                 CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
  69.                                    ("%s[SOCK::s_Close]  Failed "
  70.                                     "setsockopt(SO_LINGER)", s_ID(sock, _id)));
  71.             }
  72.         }
  73. #endif /*(NCBI_OS_UNIX && !NCBI_OS_BEOS) || NCBI_OS_MSWIN*/
  74.         /* shutdown in both directions */
  75.         s_Shutdown(sock, eIO_ReadWrite, sock->c_timeout);
  76.         /* set the socket back to blocking mode */
  77.         if ( !s_SetNonblock(sock->sock, 0/*false*/) ) {
  78.             CORE_LOGF(eLOG_Warning,("%s[SOCK::s_Close]  Cannot set socket "
  79.                                     "back to blocking mode", s_ID(sock, _id)));
  80.         }
  81.     } else {
  82.         status = s_WritePending(sock, sock->c_timeout, 0);
  83.         if (status != eIO_Success) {
  84.             CORE_LOGF(eLOG_Warning, ("%s[SOCK::s_Close]  Leaving with some "
  85.                                      "output data pending (%s)",
  86.                                      s_ID(sock, _id), IO_StatusStr(status)));
  87.         }
  88.     }
  89.     sock->w_len = 0;
  90.     /* statistics & logging */
  91.     if (sock->type != eSOCK_Datagram) {
  92.         sock->n_in  += sock->n_read;
  93.         sock->n_out += sock->n_written;
  94.     }
  95.     if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
  96.         s_DoLog(sock, eIO_Close, 0, 0, 0);
  97.     status = eIO_Success;
  98.     if (sock->type != eSOCK_ServerSideKeep) {
  99.         for (;;) { /* close persistently - retry if interrupted by a signal */
  100.             if (SOCK_CLOSE(sock->sock) == 0)
  101.                 break;
  102.             /* error */
  103.             if (SOCK_ERRNO != SOCK_EINTR) {
  104.                 int x_errno = SOCK_ERRNO;
  105.                 CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
  106.                                    ("%s[SOCK::s_Close] "
  107.                                     " Failed close()", s_ID(sock, _id)));
  108.                 status = eIO_Unknown;
  109.                 break;
  110.             }
  111.         }
  112.     }
  113.     /* return */
  114.     sock->sock = SOCK_INVALID;
  115.     return status;
  116. }
  117. extern EIO_Status SOCK_Create(const char*     host,
  118.                               unsigned short  port, 
  119.                               const STimeout* timeout,
  120.                               SOCK*           sock)
  121. {
  122.     return SOCK_CreateEx(host, port, timeout, sock, 0, 0, eDefault);
  123. }
  124. extern EIO_Status SOCK_CreateEx(const char*     host,
  125.                                 unsigned short  port,
  126.                                 const STimeout* timeout,
  127.                                 SOCK*           sock,
  128.                                 const void*     data,
  129.                                 size_t          datalen,
  130.                                 ESwitch         log)
  131. {
  132.     unsigned int x_id = ++s_ID_Counter * 1000;
  133.     SOCK         x_sock;
  134.     *sock = 0;
  135.     /* allocate memory for the internal socket structure */
  136.     if (!(x_sock = (SOCK) calloc(1, sizeof(*x_sock))))
  137.         return eIO_Unknown;
  138.     x_sock->sock = SOCK_INVALID;
  139.     x_sock->id   = x_id;
  140.     x_sock->log  = log;
  141.     x_sock->type = eSOCK_ClientSide;
  142.     /* setup the I/O data buffer properties */
  143.     BUF_SetChunkSize(&x_sock->r_buf, SOCK_BUF_CHUNK_SIZE);
  144.     if (datalen) {
  145.         if (!BUF_SetChunkSize(&x_sock->w_buf, datalen) ||
  146.             !BUF_Write(&x_sock->w_buf, data, datalen)) {
  147.             char _id[32];
  148.             CORE_LOGF_ERRNO(eLOG_Error, errno,
  149.                             ("%s[SOCK::CreateEx] "
  150.                              " Cannot store initial data", s_ID(x_sock, _id)));
  151.             SOCK_Close(x_sock);
  152.             return eIO_Unknown;
  153.         }
  154.     }
  155.     /* connect */
  156.     {{
  157.         EIO_Status status;
  158.         if ((status = s_Connect(x_sock, host, port, timeout)) != eIO_Success) {
  159.             SOCK_Close(x_sock);
  160.             return status;
  161.         }
  162.     }}
  163.     /* success */
  164.     x_sock->r_on_w   = eDefault;
  165.     x_sock->i_on_sig = eDefault;
  166.     *sock = x_sock;
  167.     return eIO_Success;
  168. }
  169. extern EIO_Status SOCK_CreateOnTop(const void*   handle,
  170.                                    size_t        handle_size,
  171.                                    SOCK*         sock)
  172. {
  173.     return SOCK_CreateOnTopEx(handle, handle_size, sock, 0, 0,
  174.                               eDefault, eSCOT_CloseOnClose);
  175. }
  176. extern EIO_Status SOCK_CreateOnTopEx(const void*   handle,
  177.                                      size_t        handle_size,
  178.                                      SOCK*         sock,
  179.                                      const void*   data,
  180.                                      size_t        datalen,
  181.                                      ESwitch       log,
  182.                                      ESCOT_OnClose on_close)
  183. {
  184.     union {
  185.         struct sockaddr    sa;
  186.         struct sockaddr_in in;
  187. #ifdef NCBI_OS_UNIX
  188.         struct sockaddr_un un;
  189. #endif /*NCBI_OS_UNIX*/
  190.     } peer;
  191.     SOCK               x_sock;
  192.     TSOCK_Handle       xx_sock;
  193.     BUF                w_buf = 0;
  194.     unsigned int       x_id = ++s_ID_Counter * 1000;
  195.     SOCK_socklen_t     peerlen;
  196.     size_t             socklen;
  197.     *sock = 0;
  198.     assert(!datalen  ||  data);
  199.     if (!handle  ||  handle_size != sizeof(xx_sock)) {
  200.         CORE_LOGF(eLOG_Error, ("SOCK#%u[?]: [SOCK::CreateOnTopEx] "
  201.                                " Invalid handle %s%lu", x_id,
  202.                                handle ? "size " : "",
  203.                                handle ? (unsigned long) handle_size : 0));
  204.         assert(0);
  205.         return eIO_InvalidArg;
  206.     }
  207.     memcpy(&xx_sock, handle, sizeof(xx_sock));
  208.     /* initialize internals */
  209.     verify(s_Initialized  ||  SOCK_InitializeAPI() == eIO_Success);
  210.     /* get peer's address */
  211.     peerlen = (SOCK_socklen_t) sizeof(peer);
  212.     memset(&peer, 0, peerlen);
  213. #ifdef HAVE_SIN_LEN
  214.     peer.sa.sa_len = sizeof(peer);
  215. #endif
  216.     if (getpeername(xx_sock, &peer.sa, &peerlen) < 0)
  217.         return eIO_Closed;
  218. #ifdef NCBI_OS_UNIX
  219.     if (peer.sa.sa_family != AF_INET  &&  peer.sa.sa_family != AF_UNIX)
  220. #  if defined(NCBI_OS_BSD)     ||  
  221.       defined(NCBI_OS_DARWIN)  ||  
  222.       defined(NCBI_OS_IRIX)
  223.         if (peer.sa.sa_family != AF_UNSPEC/*0*/)
  224. #  endif /*NCBI_OS_???*/
  225.             return eIO_InvalidArg;
  226. #else
  227.     if (peer.sa.sa_family != AF_INET)
  228.         return eIO_InvalidArg;
  229. #endif /*NCBI_OS_UNIX*/
  230. #ifdef NCBI_OS_UNIX
  231.     if (
  232. #  if defined(NCBI_OS_BSD)     ||  
  233.       defined(NCBI_OS_DARWIN)  ||  
  234.       defined(NCBI_OS_IRIX)
  235.         peer.sa.sa_family == AF_UNSPEC/*0*/  ||
  236. #  endif /*NCBI_OS_???*/
  237.         peer.sa.sa_family == AF_UNIX) {
  238.         if (!peer.un.sun_path[0]) {
  239.             peerlen = (SOCK_socklen_t) sizeof(peer);
  240.             memset(&peer, 0, sizeof(peer));
  241. #  ifdef HAVE_SIN_LEN
  242.             peer.sa.sa_len = sizeof(peer);
  243. #  endif
  244.             if (getsockname(xx_sock, &peer.sa, &peerlen) < 0)
  245.                 return eIO_Closed;
  246.             assert(peer.sa.sa_family == AF_UNIX);
  247.             if (!peer.un.sun_path[0]) {
  248.                 CORE_LOGF(eLOG_Error, ("SOCK#%u[%u]: [SOCK::CreateOnTopEx] "
  249.                                        " Unbound UNIX socket",
  250.                                        x_id, (unsigned int) xx_sock));
  251.                 assert(0);
  252.                 return eIO_InvalidArg;
  253.             }
  254.         }
  255.         socklen = strlen(peer.un.sun_path);
  256.     } else
  257. #endif /*NCBI_OS_UNIX*/
  258.         socklen = 0;
  259.     
  260.     /* store initial data */
  261.     if (datalen  &&  (!BUF_SetChunkSize(&w_buf, datalen)  ||
  262.                       !BUF_Write(&w_buf, data, datalen))) {
  263.         CORE_LOGF_ERRNO(eLOG_Error, errno,
  264.                         ("SOCK#%u[%u]: [SOCK::CreateOnTopEx]  Cannot store "
  265.                          "initial data", x_id, (unsigned int) xx_sock));
  266.         BUF_Destroy(w_buf);
  267.         return eIO_Unknown;
  268.     }
  269.     
  270.     /* create and fill socket handle */
  271.     if (!(x_sock = (SOCK) calloc(1, sizeof(*x_sock) + socklen))) {
  272.         BUF_Destroy(w_buf);
  273.         return eIO_Unknown;
  274.     }
  275.     x_sock->sock     = xx_sock;
  276.     x_sock->id       = x_id;
  277. #ifdef NCBI_OS_UNIX
  278.     if (peer.sa.sa_family != AF_UNIX) {
  279.         x_sock->host = peer.in.sin_addr.s_addr;
  280.         x_sock->port = peer.in.sin_port;
  281.     } else
  282.         strcpy(x_sock->file, peer.un.sun_path);
  283. #else
  284.     x_sock->host     = peer.in.sin_addr.s_addr;
  285.     x_sock->port     = peer.in.sin_port;
  286. #endif /*NCBI_OS_UNIX*/
  287.     x_sock->log      = log;
  288.     x_sock->type     = (on_close != eSCOT_KeepOnClose
  289.                         ? eSOCK_ServerSide
  290.                         : eSOCK_ServerSideKeep);
  291.     x_sock->r_on_w   = eDefault;
  292.     x_sock->i_on_sig = eDefault;
  293.     x_sock->r_status = eIO_Success;
  294.     x_sock->eof      = 0/*false*/;
  295.     x_sock->w_status = eIO_Success;
  296.     x_sock->pending  = 1/*have to check at the nearest I/O*/;
  297.     /* all timeouts zeroed - infinite */
  298.     BUF_SetChunkSize(&x_sock->r_buf, SOCK_BUF_CHUNK_SIZE);
  299.     x_sock->w_buf    = w_buf;
  300.     x_sock->w_len    = datalen;
  301.     /* set to non-blocking mode */
  302.     if ( !s_SetNonblock(xx_sock, 1/*true*/) ) {
  303.         char _id[32];
  304.         CORE_LOGF(eLOG_Error, ("%s[SOCK::CreateOnTopEx]  Cannot set socket "
  305.                                "to non-blocking mode", s_ID(x_sock, _id)));
  306.         x_sock->sock = SOCK_INVALID;
  307.         SOCK_Close(x_sock);
  308.         return eIO_Unknown;
  309.     }
  310.     
  311.     /* statistics & logging */
  312.     if (log == eOn  ||  (log == eDefault  &&  s_Log == eOn))
  313.         s_DoLog(x_sock, eIO_Open, &peer, 0, &peer.sa);
  314.     /* success */
  315.     *sock = x_sock;
  316.     return eIO_Success;
  317. }
  318. extern EIO_Status SOCK_Reconnect(SOCK            sock,
  319.                                  const char*     host,
  320.                                  unsigned short  port,
  321.                                  const STimeout* timeout)
  322. {
  323.     char _id[32];
  324.     if (sock->sock == eSOCK_Datagram) {
  325.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] "
  326.                                " Datagram socket", s_ID(sock, _id)));
  327.         assert(0);
  328.         return eIO_InvalidArg;
  329.     }
  330. #ifdef NCBI_OS_UNIX
  331.     if (sock->file[0]) {
  332.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect]  UNIX socket "%s"",
  333.                                s_ID(sock, _id), sock->file));
  334.         assert(0);
  335.         return eIO_InvalidArg;
  336.     }
  337. #endif /*NCBI_OS_UNIX*/
  338.     /* close the socket if necessary */
  339.     if (sock->sock != SOCK_INVALID)
  340.         s_Close(sock);
  341.     /* special treatment for server-side socket */
  342.     if (sock->type & eSOCK_ServerSide) {
  343.         if (!host  ||  !*host  ||  !port) {
  344.             CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect]  Attempt to reconnect "
  345.                                    "server-side socket as the client one to "
  346.                                    "its peer address", s_ID(sock, _id)));
  347.             return eIO_InvalidArg;
  348.         }
  349.         sock->type = eSOCK_ClientSide;
  350.     }
  351.     /* connect */
  352.     sock->id++;
  353.     sock->n_read    = 0;
  354.     sock->n_written = 0;
  355.     return s_Connect(sock, host, port, timeout);
  356. }
  357. extern EIO_Status SOCK_Shutdown(SOCK      sock,
  358.                                 EIO_Event how)
  359. {
  360.     char _id[32];
  361.     if (sock->sock == SOCK_INVALID) {
  362.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Shutdown] "
  363.                                " Invalid socket", s_ID(sock, _id)));
  364.         return eIO_Closed;
  365.     }
  366.     if (sock->type == eSOCK_Datagram) {
  367.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Shutdown] "
  368.                                " Datagram socket", s_ID(sock, _id)));
  369.         assert(0);
  370.         return eIO_InvalidArg;
  371.     }
  372.     return s_Shutdown(sock, how, sock->w_timeout);
  373. }
  374. extern EIO_Status SOCK_CloseEx(SOCK sock, int/*bool*/ destroy)
  375. {
  376.     EIO_Status status = sock->sock==SOCK_INVALID ? eIO_Success : s_Close(sock);
  377.     assert(sock->sock == SOCK_INVALID);
  378.     if (destroy) {
  379.         BUF_Destroy(sock->r_buf);
  380.         BUF_Destroy(sock->w_buf);
  381.         free(sock);
  382.     }
  383.     return status;
  384. }
  385. extern EIO_Status SOCK_Close(SOCK sock)
  386. {
  387.     return SOCK_CloseEx(sock, 1/*destroy*/);
  388. }
  389. extern EIO_Status SOCK_Wait(SOCK            sock,
  390.                             EIO_Event       event,
  391.                             const STimeout* timeout)
  392. {
  393.     char _id[32];
  394.     if (sock->sock == SOCK_INVALID) {
  395.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Wait] "
  396.                                " Invalid socket", s_ID(sock, _id)));
  397.         return eIO_Closed;
  398.     }
  399.     /* check against already shutdown socket there */
  400.     switch ( event ) {
  401.     case eIO_Read:
  402.         if (BUF_Size(sock->r_buf) != 0)
  403.             return eIO_Success;
  404.         if (sock->type == eSOCK_Datagram)
  405.             return eIO_Closed;
  406.         if (sock->r_status == eIO_Closed) {
  407.             CORE_LOGF(eLOG_Warning, ("%s[SOCK::Wait(R)]  Socket has already "
  408.                                      "been %s", s_ID(sock, _id),
  409.                                      sock->eof ? "closed" : "shut down"));
  410.             return eIO_Closed;
  411.         }
  412.         if ( sock->eof )
  413.             return eIO_Closed;
  414.         break;
  415.     case eIO_Write:
  416.         if (sock->type == eSOCK_Datagram)
  417.             return eIO_Success;
  418.         if (sock->w_status == eIO_Closed) {
  419.             CORE_LOGF(eLOG_Warning, ("%s[SOCK::Wait(W)]  Socket has already "
  420.                                      "been shut down", s_ID(sock, _id)));
  421.             return eIO_Closed;
  422.         }
  423.         break;
  424.     case eIO_ReadWrite:
  425.         if (sock->type == eSOCK_Datagram  ||  BUF_Size(sock->r_buf) != 0)
  426.             return eIO_Success;
  427.         if ((sock->r_status == eIO_Closed  ||  sock->eof)  &&
  428.             (sock->w_status == eIO_Closed)) {
  429.             if (sock->r_status == eIO_Closed) {
  430.                 CORE_LOGF(eLOG_Warning, ("%s[SOCK::Wait(RW)]  Socket has "
  431.                                          "already been shut down",
  432.                                          s_ID(sock, _id)));
  433.             }
  434.             return eIO_Closed;
  435.         }
  436.         if (sock->r_status == eIO_Closed  ||  sock->eof) {
  437.             if (sock->r_status == eIO_Closed) {
  438.                 CORE_LOGF(eLOG_Note, ("%s[SOCK::Wait(RW)]  Socket has already "
  439.                                       "been %s", s_ID(sock, _id), sock->eof
  440.                                       ? "closed" : "shut down for reading"));
  441.             }
  442.             event = eIO_Write;
  443.             break;
  444.         }
  445.         if (sock->w_status == eIO_Closed) {
  446.             CORE_LOGF(eLOG_Note,("%s[SOCK::Wait(RW)]  Socket has already been "
  447.                                  "shut down for writing", s_ID(sock, _id)));
  448.             event = eIO_Read;
  449.             break;
  450.         }
  451.         break;
  452.     default:
  453.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Wait]  Invalid event %u",
  454.                                s_ID(sock, _id), (unsigned int) event));
  455.         return eIO_InvalidArg;
  456.     }
  457.     assert(sock->type != eSOCK_Datagram);
  458.     /* do wait */
  459.     {{
  460.         struct timeval        tv;
  461.         SSOCK_Poll            poll;
  462.         EIO_Status            status;
  463.         const struct timeval* x_tv = s_to2tv(timeout, &tv);
  464.         if ((status = s_WritePending(sock, x_tv, 0)) != eIO_Success) {
  465.             if (event == eIO_Write  ||  sock->pending)
  466.                 return status;
  467.         }
  468.         poll.sock   = sock;
  469.         poll.event  = event;
  470.         poll.revent = eIO_Open;
  471.         if ((status = s_SelectStallsafe(1, &poll, x_tv, 0)) != eIO_Success)
  472.             return status;
  473.         if (poll.revent == eIO_Close)
  474.             return eIO_Unknown;
  475.         assert(poll.event == poll.revent);
  476.         return status/*success*/;
  477.     }}
  478. }
  479. extern EIO_Status SOCK_Poll(size_t          n,
  480.                             SSOCK_Poll      polls[],
  481.                             const STimeout* timeout,
  482.                             size_t*         n_ready)
  483. {
  484.     SSOCK_Poll    xx_polls[2];
  485.     SSOCK_Poll*    x_polls;
  486.     EIO_Status     status;
  487.     size_t         x_n;
  488.     struct timeval tv;
  489.     if ((n == 0) != (polls == 0)) {
  490.         if ( n_ready )
  491.             *n_ready = 0;
  492.         return eIO_InvalidArg;
  493.     }
  494.     for (x_n = 0; x_n < n; x_n++) {
  495.         if (!IS_LISTENING(polls[x_n].sock)         &&
  496.             polls[x_n].sock                        &&
  497.             polls[x_n].sock->sock != SOCK_INVALID  &&
  498.             (polls[x_n].event == eIO_Read  ||
  499.              polls[x_n].event == eIO_ReadWrite)    &&
  500.             BUF_Size(polls[x_n].sock->r_buf) != 0) {
  501.             polls[x_n].revent = eIO_Read;
  502.         } else
  503.             polls[x_n].revent = eIO_Open;
  504.     }
  505.     if (n == 1) {
  506.         xx_polls[0] = polls[0];
  507.         xx_polls[1].sock = 0;
  508.         x_polls = xx_polls;
  509.         x_n = 2;
  510.     } else {
  511.         x_polls = polls;
  512.         x_n = n;
  513.     }
  514.     status = s_SelectStallsafe(x_n, x_polls, s_to2tv(timeout, &tv), n_ready);
  515.     if (n == 1)
  516.         polls[0].revent = xx_polls[0].revent;
  517.     return status;
  518. }
  519. extern EIO_Status POLLABLE_Poll(size_t          n,
  520.                                 SPOLLABLE_Poll  polls[],
  521.                                 const STimeout* timeout,
  522.                                 size_t*         n_ready)
  523. {
  524.     return SOCK_Poll(n, (SSOCK_Poll *const) polls, timeout, n_ready);
  525. }
  526. extern POLLABLE POLLABLE_FromSOCK(SOCK sock)
  527. {
  528.     assert(!sock  ||  !IS_LISTENING(sock));
  529.     return (POLLABLE) sock;
  530. }
  531. extern POLLABLE POLLABLE_FromLSOCK(LSOCK lsock)
  532. {
  533.     assert(!lsock  ||  IS_LISTENING(lsock));
  534.     return (POLLABLE) lsock;
  535. }
  536. extern SOCK  POLLABLE_ToSOCK(POLLABLE poll)
  537. {
  538.     SOCK sock = (SOCK) poll;
  539.     return !sock  ||  IS_LISTENING(sock) ? 0 : sock;
  540. }
  541. extern LSOCK POLLABLE_ToLSOCK(POLLABLE poll)
  542. {
  543.     LSOCK lsock = (LSOCK) poll;
  544.     return !lsock  ||  IS_LISTENING(lsock) ? lsock : 0;
  545. }
  546. extern EIO_Status SOCK_SetTimeout(SOCK            sock,
  547.                                   EIO_Event       event,
  548.                                   const STimeout* timeout)
  549. {
  550.     char _id[32];
  551.     switch ( event ) {
  552.     case eIO_Read:
  553.         sock->r_timeout = s_to2tv(timeout, &sock->r_tv);
  554.         break;
  555.     case eIO_Write:
  556.         sock->w_timeout = s_to2tv(timeout, &sock->w_tv);
  557.         break;
  558.     case eIO_ReadWrite:
  559.         sock->r_timeout = s_to2tv(timeout, &sock->r_tv);
  560.         sock->w_timeout = s_to2tv(timeout, &sock->w_tv);
  561.         break;
  562.     case eIO_Close:
  563.         sock->c_timeout = s_to2tv(timeout, &sock->c_tv);
  564.         break;
  565.     default:
  566.         CORE_LOGF(eLOG_Error, ("%s[SOCK::SetTimeout]  Invalid event %u",
  567.                                s_ID(sock, _id), (unsigned int) event));
  568.         assert(0);
  569.         return eIO_InvalidArg;
  570.     }
  571.     return eIO_Success;
  572. }
  573. extern const STimeout* SOCK_GetTimeout(SOCK      sock,
  574.                                        EIO_Event event)
  575. {
  576.     const STimeout *tr, *tw;
  577.     char _id[32];
  578.     switch ( event ) {
  579.     case eIO_Read:
  580.         return s_tv2to(sock->r_timeout, &sock->r_to);
  581.     case eIO_Write:
  582.         return s_tv2to(sock->w_timeout, &sock->w_to);
  583.     case eIO_ReadWrite:
  584.         /* both timeouts come out normalized */
  585.         tr = s_tv2to(sock->r_timeout, &sock->r_to);
  586.         tw = s_tv2to(sock->w_timeout, &sock->w_to);
  587.         if ( !tr )
  588.             return tw;
  589.         if ( !tw )
  590.             return tr;
  591.         if (tr->sec > tw->sec)
  592.             return tw;
  593.         if (tw->sec > tr->sec)
  594.             return tr;
  595.         assert(tr->sec == tw->sec);
  596.         return tr->usec > tw->usec ? tw : tr;
  597.     case eIO_Close:
  598.         return s_tv2to(sock->c_timeout, &sock->c_to);
  599.     default:
  600.         CORE_LOGF(eLOG_Error, ("%s[SOCK::GetTimeout]  Invalid event %u",
  601.                                s_ID(sock, _id), (unsigned int) event));
  602.         assert(0);
  603.     }
  604.     return 0;
  605. }
  606. extern EIO_Status SOCK_Read(SOCK           sock,
  607.                             void*          buf,
  608.                             size_t         size,
  609.                             size_t*        n_read,
  610.                             EIO_ReadMethod how)
  611. {
  612.     EIO_Status status;
  613.     size_t     x_read;
  614.     char       _id[32];
  615.     if (sock->sock != SOCK_INVALID) {
  616.         switch ( how ) {
  617.         case eIO_ReadPlain:
  618.             status = s_Read(sock, buf, size, &x_read, 0/*false, read*/);
  619.             break;
  620.         case eIO_ReadPeek:
  621.             status = s_Read(sock, buf, size, &x_read, 1/*true, peek*/);
  622.             break;
  623.         case eIO_ReadPersist:
  624.             x_read = 0;
  625.             do {
  626.                 size_t xx_read;
  627.                 status = SOCK_Read(sock, (char*) buf + (buf? x_read : 0), size,
  628.                                    &xx_read, eIO_ReadPlain);
  629.                 if (status != eIO_Success)
  630.                     break;
  631.                 x_read += xx_read;
  632.                 size   -= xx_read;
  633.             } while ( size );
  634.             break;
  635.         default:
  636.             CORE_LOGF(eLOG_Error, ("%s[SOCK::Read]  Invalid read method %u",
  637.                                    s_ID(sock, _id), (unsigned int) how));
  638.             assert(0);
  639.             x_read = 0;
  640.             status = eIO_InvalidArg;
  641.             break;
  642.         }
  643.     } else {
  644.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Read] "
  645.                                " Invalid socket", s_ID(sock, _id)));
  646.         x_read = 0;
  647.         status = eIO_Closed;
  648.     }
  649.     if ( n_read )
  650.         *n_read = x_read;
  651.     return status;
  652. }
  653. extern EIO_Status SOCK_PushBack(SOCK        sock,
  654.                                 const void* buf,
  655.                                 size_t      size)
  656. {
  657.     if (sock->sock == SOCK_INVALID) {
  658.         char _id[32];
  659.         CORE_LOGF(eLOG_Error, ("%s[SOCK::PushBack] "
  660.                                " Invalid socket", s_ID(sock, _id)));
  661.         return eIO_Closed;
  662.     }
  663.     return BUF_PushBack(&sock->r_buf, buf, size) ? eIO_Success : eIO_Unknown;
  664. }
  665. extern EIO_Status SOCK_Write(SOCK            sock,
  666.                              const void*     buf,
  667.                              size_t          size,
  668.                              size_t*         n_written,
  669.                              EIO_WriteMethod how)
  670. {
  671.     EIO_Status status;
  672.     char       _id[32];
  673.     size_t     x_written;
  674.     if (sock->sock != SOCK_INVALID) {
  675.         switch ( how ) {
  676.         case eIO_WritePlain:
  677.             status = s_Write(sock, buf, size, &x_written);
  678.             break;
  679.         case eIO_WritePersist:
  680.             x_written = 0;
  681.             do {
  682.                 size_t xx_written;
  683.                 status = SOCK_Write(sock, (char*) buf + x_written, size,
  684.                                     &xx_written, eIO_WritePlain);
  685.                 if (status != eIO_Success)
  686.                     break;
  687.                 x_written += xx_written;
  688.                 size      -= xx_written;
  689.             } while ( size );
  690.             break;
  691.         default:
  692.             CORE_LOGF(eLOG_Error, ("%s[SOCK::Write]  Invalid write method %u",
  693.                                    s_ID(sock, _id), (unsigned int) how));
  694.             assert(0);
  695.             x_written = 0;
  696.             status = eIO_InvalidArg;
  697.             break;
  698.         }
  699.     } else {
  700.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Write] "
  701.                                " Invalid socket", s_ID(sock, _id)));
  702.         x_written = 0;
  703.         status = eIO_Closed;
  704.     }
  705.     if ( n_written )
  706.         *n_written = x_written;
  707.     return status;
  708. }
  709. extern EIO_Status SOCK_Abort(SOCK sock)
  710. {
  711.     char       _id[32];
  712.     EIO_Status status;
  713.     if (sock->sock == SOCK_INVALID) {
  714.         CORE_LOGF(eLOG_Warning, ("%s[SOCK::Abort] "
  715.                                  " Invalid socket", s_ID(sock, _id)));
  716.         return eIO_Closed;
  717.     }
  718.     if (sock->type == eSOCK_Datagram) {
  719.         CORE_LOGF(eLOG_Error, ("%s[SOCK::Abort] "
  720.                                " Datagram socket", s_ID(sock, _id)));
  721.         assert(0);
  722.         return eIO_InvalidArg;
  723.     }
  724.     sock->eof = 0;
  725.     sock->w_len = 0;
  726.     sock->pending = 0;
  727.     sock->r_status = sock->w_status = eIO_Closed;
  728.     if (SOCK_CLOSE(sock->sock) != 0) {
  729.         int x_errno = SOCK_ERRNO;
  730.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  731.                            ("%s[SOCK::Abort] "
  732.                             " Failed close()", s_ID(sock, _id)));
  733.         status = eIO_Unknown;
  734.     } else
  735.         status = eIO_Success;
  736.     sock->sock = SOCK_INVALID;
  737.     return status;
  738. }
  739. extern EIO_Status SOCK_Status(SOCK      sock,
  740.                               EIO_Event direction)
  741. {
  742.     if (direction != eIO_Read  &&  direction != eIO_Write) {
  743.         if (direction == eIO_Open)
  744.             return sock->sock == SOCK_INVALID ? eIO_Closed  : eIO_Success;
  745.         return eIO_InvalidArg;
  746.     }
  747.     return (sock->sock == SOCK_INVALID ? eIO_Closed :
  748.             sock->pending ? eIO_Timeout : s_Status(sock, direction));
  749. }
  750. extern void SOCK_GetPeerAddress(SOCK            sock,
  751.                                 unsigned int*   host,
  752.                                 unsigned short* port,
  753.                                 ENH_ByteOrder   byte_order)
  754. {
  755.     if ( host ) {
  756.         *host = (unsigned int)
  757.             (byte_order != eNH_HostByteOrder ? sock->host : ntohl(sock->host));
  758.     }
  759.     if ( port ) {
  760.         *port = (unsigned short)
  761.             (byte_order != eNH_HostByteOrder ? sock->port : ntohs(sock->port));
  762.     }
  763. }
  764. extern char* SOCK_GetPeerAddressString(SOCK   sock,
  765.                                        char*  buf,
  766.                                        size_t buflen)
  767. {
  768.     if (!buf  ||  !buflen)
  769.         return 0;
  770. #ifdef NCBI_OS_UNIX
  771.     if (sock->file[0])
  772.         strncpy0(buf, sock->file, buflen - 1);
  773.     else
  774. #endif /*NCBI_OS_UNIX*/
  775.         HostPortToString(sock->host, ntohs(sock->port), buf, buflen);
  776.     return buf;
  777. }
  778. extern EIO_Status SOCK_GetOSHandle(SOCK   sock,
  779.                                    void*  handle,
  780.                                    size_t handle_size)
  781. {
  782.     if (!handle  ||  handle_size != sizeof(sock->sock)) {
  783.         char _id[32];
  784.         CORE_LOGF(eLOG_Error,("%s[SOCK::GetOSHandle]  Invalid handle %s%lu",
  785.                               s_ID(sock, _id), handle ? "size " : "",
  786.                               handle ? (unsigned long) handle_size : 0));
  787.         assert(0);
  788.         return eIO_InvalidArg;
  789.     }
  790.     memcpy(handle, &sock->sock, handle_size);
  791.     return sock->sock == SOCK_INVALID ? eIO_Closed : eIO_Success;
  792. }
  793. extern ESwitch SOCK_SetReadOnWriteAPI(ESwitch on_off)
  794. {
  795.     ESwitch old = s_ReadOnWrite;
  796.     if (on_off == eDefault)
  797.         on_off = eOff;
  798.     s_ReadOnWrite = on_off;
  799.     return old;
  800. }
  801. extern ESwitch SOCK_SetReadOnWrite(SOCK sock, ESwitch on_off)
  802. {
  803.     if (sock->type != eSOCK_Datagram) {
  804.         ESwitch old = sock->r_on_w;
  805.         sock->r_on_w = on_off;
  806.         return old;
  807.     }
  808.     return eDefault;
  809. }
  810. extern ESwitch SOCK_SetInterruptOnSignalAPI(ESwitch on_off)
  811. {
  812.     ESwitch old = s_InterruptOnSignal;
  813.     if (on_off == eDefault)
  814.         on_off = eOff;
  815.     s_InterruptOnSignal = on_off;
  816.     return old;
  817. }
  818. extern ESwitch SOCK_SetInterruptOnSignal(SOCK sock, ESwitch on_off)
  819. {
  820.     ESwitch old = sock->i_on_sig;
  821.     sock->i_on_sig = on_off;
  822.     return old;
  823. }
  824. extern ESwitch SOCK_SetReuseAddressAPI(ESwitch on_off)
  825. {
  826.     int old = s_ReuseAddress;
  827.     s_ReuseAddress = on_off == eOn ? 1 : 0;
  828.     return old ? eOn : eOff;
  829. }
  830. extern void SOCK_SetReuseAddress(SOCK sock, int/*bool*/ on_off)
  831. {
  832.     if (sock->sock != SOCK_INVALID && !s_SetReuseAddress(sock->sock, on_off)) {
  833.         int x_errno = SOCK_ERRNO;
  834.         char _id[32];
  835.         CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
  836.                            ("%s[SOCK::SetReuseAddress] "
  837.                             " Failed setsockopt(%sREUSEADDR)",
  838.                             s_ID(sock, _id), on_off ? "" : "NO"));
  839.     }
  840. }
  841. extern EIO_Status DSOCK_Create(SOCK* sock)
  842. {
  843.     return DSOCK_CreateEx(sock, eDefault);
  844. }
  845. extern EIO_Status DSOCK_CreateEx(SOCK* sock, ESwitch log)
  846. {
  847.     unsigned int x_id = ++s_ID_Counter * 1000;
  848.     TSOCK_Handle x_sock;
  849.     *sock = 0;
  850.     /* initialize internals */
  851.     verify(s_Initialized  ||  SOCK_InitializeAPI() == eIO_Success);
  852.     /* create new datagram socket */
  853.     if ((x_sock = socket(AF_INET, SOCK_DGRAM, 0)) == SOCK_INVALID) {
  854.         int x_errno = SOCK_ERRNO;
  855.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  856.                            ("SOCK#%u[?]: [DSOCK::Create] "
  857.                             " Cannot create socket", x_id));
  858.         return eIO_Unknown;
  859.     }
  860.     /* set to non-blocking mode */
  861.     if ( !s_SetNonblock(x_sock, 1/*true*/) ) {
  862.         CORE_LOGF(eLOG_Error, ("SOCK#%u[%u]: [DSOCK::Create]  Cannot set "
  863.                                "socket to non-blocking mode", x_id, x_sock));
  864.         SOCK_CLOSE(x_sock);
  865.         return eIO_Unknown;
  866.     }
  867.     if ( !(*sock = (SOCK) calloc(1, sizeof(**sock))) ) {
  868.         SOCK_CLOSE(x_sock);
  869.         return eIO_Unknown;
  870.     }
  871.     /* success... */
  872.     (*sock)->sock     = x_sock;
  873.     (*sock)->id       = x_id;
  874.     /* no host and port - not "connected" */
  875.     (*sock)->log      = log;
  876.     (*sock)->type     = eSOCK_Datagram;
  877.     (*sock)->r_on_w   = eOff;
  878.     (*sock)->i_on_sig = eDefault;
  879.     (*sock)->r_status = eIO_Success;
  880.     (*sock)->eof      = 0/*false*/;
  881.     (*sock)->w_status = eIO_Success;
  882.     /* all timeouts cleared - infinite */
  883.     BUF_SetChunkSize(&(*sock)->r_buf, SOCK_BUF_CHUNK_SIZE);
  884.     BUF_SetChunkSize(&(*sock)->w_buf, SOCK_BUF_CHUNK_SIZE);
  885.     /* statistics & logging */
  886.     if (log == eOn  ||  (log == eDefault  &&  s_Log == eOn))
  887.         s_DoLog(*sock, eIO_Open, 0, 0, 0);
  888.     return eIO_Success;
  889. }
  890. extern EIO_Status DSOCK_Bind(SOCK sock, unsigned short port)
  891. {
  892.     struct sockaddr_in addr;
  893.     char _id[32];
  894.     if (sock->type != eSOCK_Datagram) {
  895.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::Bind] "
  896.                                " Not a datagram socket", s_ID(sock, _id)));
  897.         assert(0);
  898.         return eIO_InvalidArg;
  899.     }
  900.     if (sock->sock == SOCK_INVALID) {
  901.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::Bind] "
  902.                                " Invalid socket", s_ID(sock, _id)));
  903.         return eIO_Closed;
  904.     }
  905.     /* bind */
  906.     memset(&addr, 0, sizeof(addr));
  907.     addr.sin_family      = AF_INET;
  908.     addr.sin_addr.s_addr = htonl(INADDR_ANY);
  909.     addr.sin_port        = htons(port);
  910. #ifdef HAVE_SIN_LEN
  911.     addr.sin_len         = sizeof(addr);
  912. #endif /*HAVE_SIN_LEN*/
  913.     if (bind(sock->sock, (struct sockaddr*) &addr, sizeof(addr)) !=0 ) {
  914.         int x_errno = SOCK_ERRNO;
  915.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  916.                            ("%s[DSOCK::Bind]  Failed bind()", s_ID(sock,_id)));
  917.         return x_errno == SOCK_EADDRINUSE ? eIO_Closed : eIO_Unknown;
  918.     }
  919.     /* statistics & logging */
  920.     if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
  921.         s_DoLog(sock, eIO_Open, 0, 0, (struct sockaddr*) &addr);
  922.     return eIO_Success;
  923. }
  924. extern EIO_Status DSOCK_Connect(SOCK sock,
  925.                                 const char* host, unsigned short port)
  926. {
  927.     struct sockaddr_in peer;
  928.     char _id[32];
  929.     if (sock->type != eSOCK_Datagram) {
  930.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect] "
  931.                                " Not a datagram socket", s_ID(sock, _id)));
  932.         assert(0);
  933.         return eIO_InvalidArg;
  934.     }
  935.     if (sock->sock == SOCK_INVALID) {
  936.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect] "
  937.                                " Invalid socket", s_ID(sock, _id)));
  938.         return eIO_Closed;
  939.     }
  940.     /* drop all pending data */
  941.     s_WipeRBuf(sock);
  942.     s_WipeWBuf(sock);
  943.     sock->id++;
  944.     /* obtain host and port of the peer */
  945.     if ( port )
  946.         sock->port = htons(port);
  947.     if (host  &&  *host) {
  948.         if ((sock->host = SOCK_gethostbyname(host)) == 0) {
  949.             CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect]  Failed "
  950.                                    "SOCK_gethostbyname("%.64s")",
  951.                                    s_ID(sock, _id), host));
  952.             return eIO_Unknown;
  953.         }
  954.     }
  955.     if (!sock->host || !sock->port) {
  956.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect] "
  957.                                " Address incomplete", s_ID(sock, _id)));
  958.         return eIO_InvalidArg;
  959.     }
  960.     /* connect */
  961.     memset(&peer, 0, sizeof(peer));
  962.     peer.sin_family      = AF_INET;
  963.     peer.sin_addr.s_addr = sock->host;
  964.     peer.sin_port        = sock->port;
  965. #ifdef HAVE_SIN_LEN
  966.     peer.sin_len         = sizeof(peer);
  967. #endif /*HAVE_SIN_LEN*/
  968.     if (connect(sock->sock, (struct sockaddr*) &peer, sizeof(peer)) != 0) {
  969.         char addr[80];
  970.         int x_errno = SOCK_ERRNO;
  971.         HostPortToString(sock->host, sock->port, addr, sizeof(addr));
  972.         CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  973.                            ("%s[DSOCK::Connect]  Failed connect() to %s",
  974.                             s_ID(sock, _id), addr));
  975.         return eIO_Unknown;
  976.     }
  977.     /* statistics & logging */
  978.     if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
  979.         s_DoLog(sock, eIO_Open, &peer, 0, (struct sockaddr*) &peer);
  980.     return eIO_Success;
  981. }
  982. extern EIO_Status DSOCK_SendMsg(SOCK            sock,
  983.                                 const char*     host,
  984.                                 unsigned short  port,
  985.                                 const void*     data,
  986.                                 size_t          datalen)
  987. {
  988.     size_t             x_msgsize;
  989.     char               w[1536];
  990.     EIO_Status         status;
  991.     unsigned short     x_port;
  992.     unsigned int       x_host;
  993.     void*              x_msg;
  994.     struct sockaddr_in addr;
  995.     if (sock->type != eSOCK_Datagram) {
  996.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
  997.                                " Not a datagram socket", s_ID(sock, w)));
  998.         assert(0);
  999.         return eIO_InvalidArg;
  1000.     }
  1001.     if (sock->sock == SOCK_INVALID) {
  1002.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
  1003.                                " Invalid socket", s_ID(sock, w)));
  1004.         return eIO_Closed;
  1005.     }
  1006.     if ( datalen ) {
  1007.         s_Write(sock, data, datalen, &x_msgsize);
  1008.         verify(x_msgsize == datalen);
  1009.     }
  1010.     sock->eof = 1/*true - finalized message*/;
  1011.     x_port = port ? htons(port) : sock->port;
  1012.     if (host  &&  *host) {
  1013.         if ( !(x_host = SOCK_gethostbyname(host)) ) {
  1014.             CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg]  Failed "
  1015.                                    "SOCK_gethostbyname("%.64s")",
  1016.                                    s_ID(sock, w), host));
  1017.             return eIO_Unknown;
  1018.         }
  1019.     } else
  1020.         x_host = sock->host;
  1021.     if (!x_host  ||  !x_port) {
  1022.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
  1023.                                " Address incomplete", s_ID(sock, w)));
  1024.         return eIO_Unknown;
  1025.     }
  1026.     if ((x_msgsize = BUF_Size(sock->w_buf)) != 0) {
  1027.         if (x_msgsize <= sizeof(w))
  1028.             x_msg = w;
  1029.         else if ( !(x_msg = malloc(x_msgsize)) )
  1030.             return eIO_Unknown;
  1031.         verify(BUF_Peek(sock->w_buf, x_msg, x_msgsize) == x_msgsize);
  1032.     } else
  1033.         x_msg = 0;
  1034.     memset(&addr, 0, sizeof(addr));
  1035.     addr.sin_family      = AF_INET;
  1036.     addr.sin_addr.s_addr = x_host;
  1037.     addr.sin_port        = x_port;
  1038. #ifdef HAVE_SIN_LEN
  1039.     addr.sin_len         = sizeof(addr);
  1040. #endif /*HAVE_SIN_LEN*/
  1041.     for (;;) { /* optionally auto-resume if interrupted by a signal */
  1042.         int  x_written;
  1043.         int  x_errno;
  1044.         if ((x_written = sendto(sock->sock, x_msg, x_msgsize, 0/*flags*/,
  1045.                                 (struct sockaddr*) &addr, sizeof(addr))) >= 0){
  1046.             /* statistics & logging */
  1047.             if (sock->log == eOn  ||  (sock->log == eDefault && s_Log == eOn)){
  1048.                 s_DoLog(sock, eIO_Write, x_msg, (size_t) x_written,
  1049.                         (struct sockaddr*) &addr);
  1050.             }
  1051.             sock->n_written += x_written;
  1052.             sock->n_out++;
  1053.             if ((size_t) x_written != x_msgsize) {
  1054.                 sock->w_status = status = eIO_Closed;
  1055.                 CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
  1056.                                        " Partial datagram sent",s_ID(sock,w)));
  1057.                 break;
  1058.             }
  1059.             sock->w_status = status = eIO_Success;
  1060.             break;
  1061.         }
  1062.         /* don't want to handle all possible errors... let them be "unknown" */
  1063.         sock->w_status = status = eIO_Unknown;
  1064.         x_errno = SOCK_ERRNO;
  1065.         /* blocked -- retry if unblocked before the timeout expires */
  1066.         /* (use stall protection if specified) */
  1067.         if (x_errno == SOCK_EWOULDBLOCK  ||  x_errno == SOCK_EAGAIN) {
  1068.             SSOCK_Poll poll;
  1069.             poll.sock   = sock;
  1070.             poll.event  = eIO_Write;
  1071.             poll.revent = eIO_Open;
  1072.             /* stall protection:  try pull incoming data from the socket */
  1073.             if ((status = s_Select(1, &poll, sock->w_timeout)) != eIO_Success)
  1074.                 break;
  1075.             if (poll.revent == eIO_Close) {
  1076.                 status = eIO_Unknown;
  1077.                 break;
  1078.             }
  1079.             assert(poll.revent == eIO_Write);
  1080.             continue;
  1081.         }
  1082.         if (x_errno != SOCK_EINTR) {
  1083.             CORE_LOGF_ERRNO_EX(eLOG_Trace, x_errno, SOCK_STRERROR(x_errno),
  1084.                                ("%s[DSOCK::SendMsg] "
  1085.                                 " Failed sendto()", s_ID(sock, w)));
  1086.             break;
  1087.         }
  1088.         if (sock->i_on_sig == eOn  ||
  1089.             (sock->i_on_sig == eDefault  &&  s_InterruptOnSignal == eOn)) {
  1090.             sock->w_status = status = eIO_Interrupt;
  1091.             break;
  1092.         }
  1093.     }
  1094.     if (x_msg  &&  x_msg != w)
  1095.         free(x_msg);
  1096.     if (status == eIO_Success)
  1097.         sock->w_status = s_WipeWBuf(sock);
  1098.     return status;
  1099. }
  1100. extern EIO_Status DSOCK_RecvMsg(SOCK            sock,
  1101.                                 void*           buf,
  1102.                                 size_t          buflen,
  1103.                                 size_t          msgsize,
  1104.                                 size_t*         msglen,
  1105.                                 unsigned int*   sender_addr,
  1106.                                 unsigned short* sender_port)
  1107. {
  1108.     size_t     x_msgsize;
  1109.     char       w[1536];
  1110.     EIO_Status status;
  1111.     void*      x_msg;
  1112.     if (sock->type != eSOCK_Datagram) {
  1113.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::RecvMsg] "
  1114.                                " Not a datagram socket", s_ID(sock, w)));
  1115.         assert(0);
  1116.         return eIO_InvalidArg;
  1117.     }
  1118.     if (sock->sock == SOCK_INVALID) {
  1119.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::RecvMsg] "
  1120.                                " Invalid socket", s_ID(sock, w)));
  1121.         return eIO_Closed;
  1122.     }
  1123.     s_WipeRBuf(sock);
  1124.     if ( msglen )
  1125.         *msglen = 0;
  1126.     if ( sender_addr )
  1127.         *sender_addr = 0;
  1128.     if ( sender_port )
  1129.         *sender_port = 0;
  1130.     x_msgsize = (msgsize  &&  msgsize < ((1 << 16) - 1))
  1131.         ? msgsize : ((1 << 16) - 1);
  1132.     if ( !(x_msg = (x_msgsize <= buflen
  1133.                     ? buf : (x_msgsize <= sizeof(w)
  1134.                              ? w : malloc(x_msgsize)))) ) {
  1135.         return eIO_Unknown;
  1136.     }
  1137.     for (;;) { /* auto-resume if either blocked or interrupted (optional) */
  1138.         int                x_errno;
  1139.         int                x_read;
  1140.         struct sockaddr_in addr;
  1141. #if defined(HAVE_SOCKLEN_T)
  1142.         typedef socklen_t  SOCK_socklen_t;
  1143. #elif defined(NCBI_OS_MAC)
  1144.         typedef UInt32     SOCK_socklen_t;
  1145. #else
  1146.         typedef int        SOCK_socklen_t;
  1147. #endif /*HAVE_SOCKLEN_T*/
  1148.         SOCK_socklen_t     addrlen = (SOCK_socklen_t) sizeof(addr);
  1149. #ifdef HAVE_SIN_LEN
  1150.         addr.sin_len = addrlen;
  1151. #endif
  1152.         x_read = recvfrom(sock->sock, x_msg, x_msgsize, 0,
  1153.                           (struct sockaddr*) &addr, &addrlen);
  1154.         if (x_read >= 0) {
  1155.             /* got a message */
  1156.             sock->r_status = status = eIO_Success;
  1157.             if ( x_read ) {
  1158.                 if ( msglen )
  1159.                     *msglen = x_read;
  1160.                 if ( sender_addr )
  1161.                     *sender_addr = addr.sin_addr.s_addr;
  1162.                 if ( sender_port )
  1163.                     *sender_port = ntohs(addr.sin_port);
  1164.                 if ((size_t) x_read > buflen  &&
  1165.                     !BUF_Write(&sock->r_buf,
  1166.                                (char*) x_msg  + buflen,
  1167.                                (size_t)x_read - buflen)) {
  1168.                     sock->r_status = eIO_Unknown;
  1169.                 }
  1170.                 if (buflen  &&  x_msgsize > buflen)
  1171.                     memcpy(buf, x_msg, buflen);
  1172.             }
  1173.             /* statistics & logging */
  1174.             if (sock->log == eOn  ||  (sock->log == eDefault && s_Log == eOn)){
  1175.                 s_DoLog(sock, eIO_Read, x_msg, (size_t) x_read,
  1176.                         (struct sockaddr*) &addr);
  1177.             }
  1178.             sock->n_read += x_read;
  1179.             sock->n_in++;
  1180.             break;
  1181.         }
  1182.         x_errno = SOCK_ERRNO;
  1183.         sock->r_status = status = eIO_Unknown;
  1184.         if (x_errno != SOCK_EWOULDBLOCK  &&
  1185.             x_errno != SOCK_EAGAIN       &&
  1186.             x_errno != SOCK_EINTR) {
  1187.             /* catch unknown ERROR */
  1188.             CORE_LOGF_ERRNO_EX(eLOG_Trace, x_errno, SOCK_STRERROR(x_errno),
  1189.                                ("%s[DSOCK::RecvMsg] "
  1190.                                 " Failed recvfrom()", s_ID(sock, w)));
  1191.             break;
  1192.         }
  1193.         if (x_errno == SOCK_EWOULDBLOCK  ||  x_errno == SOCK_EAGAIN) {
  1194.             SSOCK_Poll poll;
  1195.             poll.sock   = sock;
  1196.             poll.event  = eIO_Read;
  1197.             poll.revent = eIO_Open;
  1198.             if ((status = s_Select(1, &poll, sock->r_timeout)) != eIO_Success)
  1199.                 break;
  1200.             if (poll.revent == eIO_Close) {
  1201.                 status = eIO_Closed;
  1202.                 break;
  1203.             }
  1204.             assert(poll.event == eIO_Read  &&  poll.revent == eIO_Read);
  1205.             continue;
  1206.         }
  1207.         if (x_errno != SOCK_EINTR)
  1208.             break;
  1209.         if (sock->i_on_sig == eOn  ||
  1210.             (sock->i_on_sig == eDefault  &&  s_InterruptOnSignal == eOn)) {
  1211.             status = eIO_Interrupt;
  1212.             break;
  1213.         }
  1214.     }
  1215.     if (x_msgsize > buflen && x_msg != w)
  1216.         free(x_msg);
  1217.     return status;
  1218. }
  1219. extern EIO_Status DSOCK_WaitMsg(SOCK sock, const STimeout* timeout)
  1220. {
  1221.     char           _id[32];
  1222.     EIO_Status     status;
  1223.     SSOCK_Poll     poll;
  1224.     struct timeval tv;
  1225.     if (sock->type != eSOCK_Datagram) {
  1226.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::WaitMsg] "
  1227.                                " Not a datagram socket", s_ID(sock, _id)));
  1228.         assert(0);
  1229.         return eIO_InvalidArg;
  1230.     }
  1231.     if (sock->sock == SOCK_INVALID) {
  1232.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::WaitMsg] "
  1233.                                " Invalid socket", s_ID(sock, _id)));
  1234.         return eIO_Closed;
  1235.     }
  1236.     poll.sock   = sock;
  1237.     poll.event  = eIO_Read;
  1238.     poll.revent = eIO_Open;
  1239.     if ((status = s_Select(1, &poll, s_to2tv(timeout, &tv))) != eIO_Success ||
  1240.         poll.revent == eIO_Read) {
  1241.         return status;
  1242.     }
  1243.     assert(poll.revent == eIO_Close);
  1244.     return eIO_Closed;
  1245. }
  1246. extern EIO_Status DSOCK_WipeMsg(SOCK sock, EIO_Event direction)
  1247. {
  1248.     char _id[32];
  1249.     EIO_Status status;
  1250.     if (sock->type != eSOCK_Datagram) {
  1251.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::WipeMsg] "
  1252.                                " Not a datagram socket", s_ID(sock, _id)));
  1253.         assert(0);
  1254.         return eIO_InvalidArg;
  1255.     }
  1256.     if (sock->sock == SOCK_INVALID) {
  1257.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::WipeMsg] "
  1258.                                " Invalid socket", s_ID(sock, _id)));
  1259.         return eIO_Closed;
  1260.     }
  1261.     switch (direction) {
  1262.     case eIO_Read:
  1263.         sock->r_status = status = s_WipeRBuf(sock);
  1264.         break;
  1265.     case eIO_Write:
  1266.         sock->w_status = status = s_WipeWBuf(sock);
  1267.         break;
  1268.     default:
  1269.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::WipeMsg]  Invalid direction %u",
  1270.                                s_ID(sock, _id), (unsigned int) direction));
  1271.         assert(0);
  1272.         status = eIO_InvalidArg;
  1273.         break;
  1274.     }
  1275.     return status;
  1276. }
  1277. extern EIO_Status DSOCK_SetBroadcast(SOCK sock, int/*bool*/ broadcast)
  1278. {
  1279.     char _id[32];
  1280.     if (sock->type != eSOCK_Datagram) {
  1281.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::SetBroadcast] "
  1282.                                " Not a datagram socket", s_ID(sock, _id)));
  1283.         assert(0);
  1284.         return eIO_InvalidArg;
  1285.     }
  1286.     if (sock->sock == SOCK_INVALID) {
  1287.         CORE_LOGF(eLOG_Error, ("%s[DSOCK::SetBroadcast] "
  1288.                                " Invalid socket", s_ID(sock, _id)));
  1289.         return eIO_Closed;
  1290.     }
  1291. #if defined(NCBI_OS_UNIX)  ||  defined(NCBI_OS_MSWIN)
  1292.     /* setsockopt() is not implemented for MAC (in MIT socket emulation lib) */
  1293.     {{
  1294. #  ifdef NCBI_OS_MSWIN
  1295.         BOOL bcast = !!broadcast;
  1296. #  else
  1297.         int  bcast = !!broadcast;
  1298. #  endif /*NCBI_OS_MSWIN*/
  1299.         if (setsockopt(sock->sock, SOL_SOCKET, SO_BROADCAST,
  1300.                        (const char*) &bcast, sizeof(bcast)) != 0) {
  1301.             int x_errno = SOCK_ERRNO;
  1302.             CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1303.                                ("%s[DSOCK::SetBroadcast] "
  1304.                                 " Failed setsockopt(%sBROADCAST)",
  1305.                                 s_ID(sock, _id), bcast ? "" : "NO"));
  1306.             return eIO_Unknown;
  1307.         }
  1308.     }}
  1309. #else
  1310.     return eIO_NotSupported;
  1311. #endif /*NCBI_OS_UNIX || NXBI_OS_MSWIN*/
  1312.     return eIO_Success;
  1313. }
  1314. extern int/*bool*/ SOCK_IsDatagram(SOCK sock)
  1315. {
  1316.     return sock->sock != SOCK_INVALID  &&  sock->type == eSOCK_Datagram;
  1317. }
  1318. extern int/*bool*/ SOCK_IsClientSide(SOCK sock)
  1319. {
  1320.     return sock->sock != SOCK_INVALID  &&  sock->type == eSOCK_ClientSide;
  1321. }
  1322. extern int/*bool*/ SOCK_IsServerSide(SOCK sock)
  1323. {
  1324.     return sock->sock != SOCK_INVALID  &&  (sock->type & eSOCK_ServerSide);
  1325. }
  1326. extern int SOCK_gethostname(char*  name,
  1327.                             size_t namelen)
  1328. {
  1329.     int error = 0;
  1330.     /* initialize internals */
  1331.     verify(s_Initialized  ||  SOCK_InitializeAPI() == eIO_Success);
  1332.     assert(name && namelen > 0);
  1333.     name[0] = name[namelen - 1] = '';
  1334.     if (gethostname(name, (int) namelen) != 0) {
  1335.         int x_errno = SOCK_ERRNO;
  1336.         CORE_LOG_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
  1337.                           "[SOCK_gethostname]  Failed gethostname()");
  1338.         error = 1;
  1339.     } else if ( name[namelen - 1] ) {
  1340.         CORE_LOG(eLOG_Error, "[SOCK_gethostname]  Buffer too small");
  1341.         error = 1;
  1342.     }
  1343.     if ( !error )
  1344.         return 0/*success*/;
  1345.     name[0] = '';
  1346.     return -1/*failed*/;
  1347. }
  1348. extern int SOCK_ntoa(unsigned int host,
  1349.                      char*        buf,
  1350.                      size_t       buflen)
  1351. {
  1352.     const unsigned char* b = (const unsigned char*) &host;
  1353.     char str[16];
  1354.     assert(buf && buflen > 0);
  1355.     verify(sprintf(str, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]) > 0);
  1356.     assert(strlen(str) < sizeof(str));
  1357.     if (strlen(str) >= buflen) {
  1358.         buf[0] = '';
  1359.         return -1/*failed*/;
  1360.     }
  1361.     strcpy(buf, str);
  1362.     return 0/*success*/;
  1363. }
  1364. extern unsigned int SOCK_HostToNetLong(unsigned int value)
  1365. {
  1366.     return htonl(value);
  1367. }
  1368. extern unsigned short SOCK_HostToNetShort(unsigned short value)
  1369. {
  1370.     return htons(value);
  1371. }
  1372. extern unsigned int SOCK_gethostbyname(const char* hostname)
  1373. {
  1374.     unsigned int host;
  1375.     char buf[256];
  1376.     /* initialize internals */
  1377.     verify(s_Initialized  ||  SOCK_InitializeAPI() == eIO_Success);
  1378.     if (!hostname || !*hostname) {
  1379.         if (SOCK_gethostname(buf, sizeof(buf)) != 0)
  1380.             return 0;
  1381.         hostname = buf;
  1382.     }
  1383.     host = inet_addr(hostname);
  1384.     if (host == htonl(INADDR_NONE)) {
  1385.         int x_errno;
  1386. #if defined(HAVE_GETADDRINFO)
  1387.         struct addrinfo hints, *out = 0;
  1388.         memset(&hints, 0, sizeof(hints));
  1389.         hints.ai_family = PF_INET; /* currently, we only handle IPv4 */
  1390.         if ((x_errno = getaddrinfo(hostname, 0, &hints, &out)) == 0  &&  out) {
  1391.             struct sockaddr_in* addr = (struct sockaddr_in *) out->ai_addr;
  1392.             assert(addr->sin_family == AF_INET);
  1393.             host = addr->sin_addr.s_addr;
  1394.         } else {
  1395.             if (s_Log == eOn) {
  1396.                 if (x_errno == EAI_SYSTEM)
  1397.                     x_errno = SOCK_ERRNO;
  1398.                 else
  1399.                     x_errno += EAI_BASE;
  1400.                 CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
  1401.                                    ("[SOCK_gethostbyname]  Failed "
  1402.                                     "getaddrinfo("%.64s")", hostname));
  1403.             }
  1404.             host = 0;
  1405.         }
  1406.         if ( out ) {
  1407.             freeaddrinfo(out);
  1408.         }
  1409. #else /* use some variant of gethostbyname */
  1410.         struct hostent* he;
  1411. #  if defined(HAVE_GETHOSTBYNAME_R)
  1412.         static const char suffix[] = "_r";
  1413.         struct hostent  x_he;
  1414.         char            x_buf[1024];
  1415.         x_errno = 0;
  1416. #    if (HAVE_GETHOSTBYNAME_R == 5)
  1417.         he = gethostbyname_r(hostname, &x_he, x_buf, sizeof(x_buf), &x_errno);
  1418. #    elif (HAVE_GETHOSTBYNAME_R == 6)
  1419.         if (gethostbyname_r(hostname, &x_he, x_buf, sizeof(x_buf),
  1420.                             &he, &x_errno) != 0) {
  1421.             assert(he == 0);
  1422.             he = 0;
  1423.         }
  1424. #    else
  1425. #      error "Unknown HAVE_GETHOSTBYNAME_R value"
  1426. #    endif /*HAVE_GETHOSTNBYNAME_R == N*/
  1427. #  else
  1428.         static const char suffix[] = "";
  1429.         CORE_LOCK_WRITE;
  1430.         he = gethostbyname(hostname);
  1431. #    ifdef NCBI_OS_MAC
  1432.         x_errno = SOCK_ERRNO;
  1433. #    else
  1434.         x_errno = h_errno + DNS_BASE;
  1435. #    endif /*NCBI_OS_MAC*/
  1436. #  endif /*HAVE_GETHOSTBYNAME_R*/
  1437.         if (he && he->h_addrtype == AF_INET && he->h_length == sizeof(host)) {
  1438.             memcpy(&host, he->h_addr, sizeof(host));
  1439.         } else {
  1440.             host = 0;
  1441.             if ( he )
  1442.                 x_errno = EINVAL;
  1443.         }
  1444. #  if !defined(HAVE_GETHOSTBYNAME_R)
  1445.         CORE_UNLOCK;
  1446. #  endif /*HAVE_GETHOSTBYNAME_R*/
  1447.         if (!host  &&  s_Log == eOn) {
  1448. #  ifdef NETDB_INTERNAL
  1449.             if (x_errno == NETDB_INTERNAL + DNS_BASE)
  1450.                 x_errno = SOCK_ERRNO;
  1451. #  endif /*NETDB_INTERNAL*/
  1452.             CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
  1453.                               ("[SOCK_gethostbyname]  Failed "
  1454.                               "gethostbyname%s("%.64s")", suffix, hostname));
  1455.         }
  1456. #endif /*HAVE_GETADDR_INFO*/
  1457.     }
  1458.     return host;
  1459. }
  1460. extern char* SOCK_gethostbyaddr(unsigned int host,
  1461.                                 char*        name,
  1462.                                 size_t       namelen)
  1463. {
  1464.     /* initialize internals */
  1465.     verify(s_Initialized  ||  SOCK_InitializeAPI() == eIO_Success);
  1466.     assert(name && namelen > 0);
  1467.     if ( !host ) {
  1468.         host = SOCK_gethostbyname(0);
  1469.     }
  1470.     if ( host ) {
  1471.         int x_errno;
  1472. #if defined(HAVE_GETNAMEINFO)
  1473.         struct sockaddr_in addr;
  1474.         memset(&addr, 0, sizeof(addr));
  1475.         addr.sin_family      = AF_INET; /* currently, we only handle IPv4 */
  1476.         addr.sin_addr.s_addr = host;
  1477. #  ifdef HAVE_SIN_LEN
  1478.         addr.sin_len = sizeof(addr);
  1479. #  endif /*HAVE_SIN_LEN*/
  1480.         if ((x_errno = getnameinfo((struct sockaddr*) &addr, sizeof(addr),
  1481.                                    name, namelen, 0, 0, 0)) == 0) {
  1482.             return name;
  1483.         } else {
  1484.             if (s_Log == eOn) {
  1485.                 char addr[16];
  1486.                 if (x_errno == EAI_SYSTEM)
  1487.                     x_errno = SOCK_ERRNO;
  1488.                 else
  1489.                     x_errno += EAI_BASE;
  1490.                 if (SOCK_ntoa(host, addr, sizeof(addr)) != 0)
  1491.                     strcpy(addr, "<unknown>");
  1492.                 CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
  1493.                                   ("[SOCK_gethostbyaddr]  Failed "
  1494.                                    "getnameinfo(%s)", addr));
  1495.             }
  1496.             name[0] = '';
  1497.             return 0;
  1498.         }
  1499. #else /* use some variant of gethostbyaddr */
  1500.         struct hostent* he;
  1501. #  if defined(HAVE_GETHOSTBYADDR_R)
  1502.         static const char suffix[] = "_r";
  1503.         struct hostent  x_he;
  1504.         char            x_buf[1024];
  1505.         x_errno = 0;
  1506. #    if (HAVE_GETHOSTBYADDR_R == 7)
  1507.         he = gethostbyaddr_r((char*) &host, sizeof(host), AF_INET, &x_he,
  1508.                              x_buf, sizeof(x_buf), &x_errno);
  1509. #    elif (HAVE_GETHOSTBYADDR_R == 8)
  1510.         if (gethostbyaddr_r((char*) &host, sizeof(host), AF_INET, &x_he,
  1511.                             x_buf, sizeof(x_buf), &he, &x_errno) != 0) {
  1512.             assert(he == 0);
  1513.             he = 0;
  1514.         }
  1515. #    else
  1516. #      error "Unknown HAVE_GETHOSTBYADDR_R value"
  1517. #    endif /*HAVE_GETHOSTBYADDR_R == N*/
  1518. #  else /*HAVE_GETHOSTBYADDR_R*/
  1519.         static const char suffix[] = "";
  1520.         CORE_LOCK_WRITE;
  1521.         he = gethostbyaddr((char*) &host, sizeof(host), AF_INET);
  1522. #    ifdef NCBI_OS_MAC
  1523.         x_errno = SOCK_ERRNO;
  1524. #    else
  1525.         x_errno = h_errno + DNS_BASE;
  1526. #    endif /*NCBI_OS_MAC*/
  1527. #  endif /*HAVE_GETHOSTBYADDR_R*/
  1528.         if (!he  ||  strlen(he->h_name) >= namelen) {
  1529.             if (he  ||  SOCK_ntoa(host, name, namelen) != 0) {
  1530.                 x_errno = ERANGE;
  1531.                 name[0] = '';
  1532.                 name = 0;
  1533.             }
  1534.         } else {
  1535.             strcpy(name, he->h_name);
  1536.         }
  1537. #  ifndef HAVE_GETHOSTBYADDR_R
  1538.         CORE_UNLOCK;
  1539. #  endif /*HAVE_GETHOSTBYADDR_R*/
  1540.         if (!name  &&  s_Log == eOn) {
  1541.             char addr[16];
  1542. #  ifdef NETDB_INTERNAL
  1543.             if (x_errno == NETDB_INTERNAL + DNS_BASE)
  1544.                 x_errno = SOCK_ERRNO;
  1545. #  endif /*NETDB_INTERNAL*/
  1546.             if (SOCK_ntoa(host, addr, sizeof(addr)) != 0)
  1547.                 strcpy(addr, "<unknown>");
  1548.             CORE_LOG_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
  1549.                               ("[SOCK_gethostbyaddr]  Failed "
  1550.                               "gethostbyaddr%s(%s)", suffix, addr));
  1551.         }
  1552.         return name;
  1553. #endif /*HAVE_GETNAMEINFO*/
  1554.     }
  1555.     name[0] = '';
  1556.     return 0;
  1557. }
  1558. /*
  1559.  * ===========================================================================
  1560.  * $Log: ncbi_socket.c,v $
  1561.  * Revision 1000.4  2004/06/01 18:45:25  gouriano
  1562.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.145
  1563.  *
  1564.  * Revision 6.145  2004/05/05 11:31:16  ivanov
  1565.  * Fixed compile errors
  1566.  *
  1567.  * Revision 6.144  2004/05/04 19:51:27  lavr
  1568.  * More elaborate diagnostics and better event dispatching
  1569.  *
  1570.  * Revision 6.143  2003/11/25 15:08:40  lavr
  1571.  * DSOCK_Connect(): fix diag messages
  1572.  *
  1573.  * Revision 6.142  2003/11/24 19:21:42  lavr
  1574.  * SOCK_SetSelectInternalRestartTimeout() to accept ptr to STimeout
  1575.  *
  1576.  * Revision 6.141  2003/11/18 20:19:48  lavr
  1577.  * +SOCK_SetSelectInternalRestartTimeout() and restart impl. in s_Select()
  1578.  *
  1579.  * Revision 6.140  2003/11/14 13:05:23  lavr
  1580.  * Eliminate race on socket file descriptors in s_Select() when socket aborted
  1581.  *
  1582.  * Revision 6.138  2003/11/12 17:49:42  lavr
  1583.  * Implement close w/o destruction (SOCK_CloseEx()) and make
  1584.  * corresponding provisions throughout the file.
  1585.  * More consistent return status in SOCK and DSOCK API calls.
  1586.  *
  1587.  * Revision 6.137  2003/10/27 16:45:46  ivanov
  1588.  * Use workaround for unnamed peer's UNIX sockets on DARWIN also.
  1589.  *
  1590.  * Revision 6.136  2003/10/24 17:39:43  lavr
  1591.  * Fix '==' => '!=' bug in s_Select() introduced by previous commit
  1592.  *
  1593.  * Revision 6.135  2003/10/24 16:52:08  lavr
  1594.  * GetTimeout(eIO_ReadWrite): return the lesser of eIO_Read and eIO_Write
  1595.  * s_Select(): first check RW bits then E (otherwise, problems on Solaris)
  1596.  *
  1597.  * Revision 6.134  2003/10/23 12:15:07  lavr
  1598.  * Socket feature setters made returning old feature values
  1599.  *
  1600.  * Revision 6.133  2003/10/14 14:40:44  lavr
  1601.  * SOCK_gethostbyname(): fix to obtain local host name in case of empty input
  1602.  *
  1603.  * Revision 6.132  2003/10/02 16:30:40  lavr
  1604.  * s_IsConnected(): Cast buf arg to (void*) in getsockopt()
  1605.  *
  1606.  * Revision 6.131  2003/10/02 16:04:42  lavr
  1607.  * Fix conditional compilation of s_IsConnected() on MS-Windows
  1608.  *
  1609.  * Revision 6.130  2003/10/02 14:51:22  lavr
  1610.  * Better processing of delayed connections
  1611.  *
  1612.  * Revision 6.129  2003/09/23 21:10:42  lavr
  1613.  * s_Select(): Do not check for read in listening socks if write-only requested
  1614.  *
  1615.  * Revision 6.128  2003/09/05 19:29:50  ivanov
  1616.  * SOCK_CreateOnTopEx(): Workaround for unnamed peer's UNIX sockets on IRIX
  1617.  *
  1618.  * Revision 6.127  2003/09/02 20:59:21  lavr
  1619.  * -<connect/ncbi_buffer.h> [expilictly]
  1620.  *
  1621.  * Revision 6.126  2003/08/25 14:51:13  lavr
  1622.  * Change log:  typos fixed
  1623.  *
  1624.  * Revision 6.125  2003/08/25 14:40:05  lavr
  1625.  * Sync listening sockets with their SOCK counterparts and implement uniform
  1626.  * polling mechanism on sockets of different nature [listening vs connecting]
  1627.  *
  1628.  * Revision 6.124  2003/08/19 19:45:54  ivanov
  1629.  * SOCK_CreateOnTopEx(): Workaround for unnamed peer's UNIX sockets on BSD
  1630.  *
  1631.  * Revision 6.123  2003/08/18 20:01:13  lavr
  1632.  * Retry 'connect()' syscall if interrupted and allowed to restart
  1633.  *
  1634.  * Revision 6.122  2003/07/24 15:34:29  lavr
  1635.  * Fix socket name discovery procedure for UNIX On-Top SOCKs
  1636.  *
  1637.  * Revision 6.121  2003/07/23 20:31:01  lavr
  1638.  * SOCK_CreateOnTopEx(): Do not check for returned peer's address size
  1639.  *
  1640.  * Revision 6.120  2003/07/18 20:05:49  lavr
  1641.  * Fix log message of the previous check-in
  1642.  *
  1643.  * Revision 6.119  2003/07/18 20:04:49  lavr
  1644.  * Close all preprocessor conditionals with #endif's showing the conditions
  1645.  *
  1646.  * Revision 6.118  2003/07/17 18:28:50  lavr
  1647.  * On I/O errors in connected socket: modify only direction affected, not both
  1648.  *
  1649.  * Revision 6.117  2003/07/15 18:09:07  lavr
  1650.  * Fix MS-Win compilation
  1651.  *
  1652.  * Revision 6.116  2003/07/15 16:50:20  lavr
  1653.  * Allow to build on-top SOCKs from UNIX socket fds (on UNIX only)
  1654.  * +SOCK_GetPeerAddressString()
  1655.  *
  1656.  * Revision 6.115  2003/06/09 19:47:52  lavr
  1657.  * Few changes to relocate some arg checks and asserts
  1658.  *
  1659.  * Revision 6.114  2003/06/04 20:59:14  lavr
  1660.  * s_Read() not to call s_Select() if read timeout is {0, 0}
  1661.  *
  1662.  * Revision 6.113  2003/05/31 05:17:32  lavr
  1663.  * Swap bitfields and enums in chain assignments
  1664.  *
  1665.  * Revision 6.112  2003/05/21 17:53:40  lavr
  1666.  * Add logs for broken connections; update both R and W status on them
  1667.  *
  1668.  * Revision 6.111  2003/05/21 04:00:12  lavr
  1669.  * Latch connection refusals in SOCK state properly
  1670.  *
  1671.  * Revision 6.110  2003/05/20 21:20:41  lavr
  1672.  * Special treatment of size==0 in SOCK_Write()
  1673.  *
  1674.  * Revision 6.109  2003/05/20 16:47:56  lavr
  1675.  * More accurate checks for pending connections/data
  1676.  *
  1677.  * Revision 6.108  2003/05/19 21:04:37  lavr
  1678.  * Fix omission to make listening sockets "connected"
  1679.  *
  1680.  * Revision 6.107  2003/05/19 18:47:42  lavr
  1681.  * Fix MSVC compilation errors
  1682.  *
  1683.  * Revision 6.106  2003/05/19 16:51:33  lavr
  1684.  * +SOCK_SetReuseAddress[API]() - both experimental!
  1685.  * Fix for bitfield signedness in some compilers (including MSVC).
  1686.  * More development in I/O tolerance to {0,0}-timeout.
  1687.  *
  1688.  * Revision 6.105  2003/05/14 15:48:54  lavr
  1689.  * Typo fix in s_Shutdown() for MSVC (x_how should be used instead of how)
  1690.  *
  1691.  * Revision 6.104  2003/05/14 14:51:27  lavr
  1692.  * BUGFIX: Connection stall in s_Connect()
  1693.  *
  1694.  * Revision 6.103  2003/05/14 13:19:18  lavr
  1695.  * Define SOCK_SHUTDOWN_RDWR for MSVC compilation
  1696.  *
  1697.  * Revision 6.102  2003/05/14 05:24:36  lavr
  1698.  * FIX: Yet another MSVC compilation fix
  1699.  *
  1700.  * Revision 6.101  2003/05/14 04:30:58  lavr
  1701.  * FIX: MSVC compilation of s_Shutdown()
  1702.  *
  1703.  * Revision 6.100  2003/05/14 04:28:01  lavr
  1704.  * BUGFIX: s_LogData -> s_Log
  1705.  *
  1706.  * Revision 6.99  2003/05/14 03:50:25  lavr
  1707.  * Revamped to allow pending connect and initial data output
  1708.  *
  1709.  * Revision 6.98  2003/05/05 20:24:13  lavr
  1710.  * Added EOF-on-read as a trace event to log when verbose mode is on
  1711.  *
  1712.  * Revision 6.97  2003/05/05 11:41:09  rsmith
  1713.  * added defines and declarations to allow cross compilation Mac->Win32
  1714.  * using Metrowerks Codewarrior.
  1715.  *
  1716.  * Revision 6.96  2003/04/30 17:00:18  lavr
  1717.  * Added on-stack buffers for small datagrams; few name collisions resolved
  1718.  *
  1719.  * Revision 6.95  2003/04/25 15:21:26  lavr
  1720.  * Explicit cast of calloc()'s result
  1721.  *
  1722.  * Revision 6.94  2003/04/14 15:14:20  lavr
  1723.  * Define SOCK_socklen_t for Mac's recvfrom() specially
  1724.  *
  1725.  * Revision 6.93  2003/04/11 20:59:06  lavr
  1726.  * Aux type SOCK_socklen_t defined centrally
  1727.  *
  1728.  * Revision 6.92  2003/04/04 21:00:37  lavr
  1729.  * +SOCK_CreateOnTop()
  1730.  *
  1731.  * Revision 6.91  2003/04/04 20:44:35  rsmith
  1732.  * do not include arpa/inet.h on CW with MSL.
  1733.  *
  1734.  * Revision 6.90  2003/04/03 14:16:18  rsmith
  1735.  * combine pp symbols NCBI_COMPILER_METROWERKS & _MSL_USING_MW_C_HEADERS into
  1736.  * NCBI_COMPILER_MW_MSL
  1737.  *
  1738.  * Revision 6.89  2003/04/02 16:21:34  rsmith
  1739.  * replace _MWERKS_ with NCBI_COMPILER_METROWERKS
  1740.  *
  1741.  * Revision 6.88  2003/04/02 13:26:07  rsmith
  1742.  * include ncbi_mslextras.h when compiling with MSL libs in Codewarrior.
  1743.  *
  1744.  * Revision 6.87  2003/03/25 22:18:06  lavr
  1745.  * shutdown(): Do not warn on ENOTCONN on SGI and OSF1 (in addition to Linux)
  1746.  *
  1747.  * Revision 6.86  2003/02/28 14:50:18  lavr
  1748.  * Add one more explicit cast to "unsigned" in s_DoLogData()
  1749.  *
  1750.  * Revision 6.85  2003/02/24 21:13:23  lavr
  1751.  * More comments added; fix for read-ahead on shut-down-for-write socket
  1752.  *
  1753.  * Revision 6.84  2003/02/20 17:52:30  lavr
  1754.  * Resolve dead-lock condition in s_SelectStallsafe()
  1755.  *
  1756.  * Revision 6.83  2003/02/04 22:03:54  lavr
  1757.  * Workaround for ENOTCONN in shutdown() on Linux; few more fixes
  1758.  *
  1759.  * Revision 6.82  2003/01/17 16:56:59  lavr
  1760.  * Always clear all pending data when reconnecting
  1761.  *
  1762.  * Revision 6.81  2003/01/17 15:56:05  lavr
  1763.  * Keep as much status as possible in failed pending connect
  1764.  *
  1765.  * Revision 6.80  2003/01/17 15:11:36  lavr
  1766.  * Update stat counters in s_Close() instead of s_Connect()
  1767.  *
  1768.  * Revision 6.79  2003/01/17 01:23:31  lavr
  1769.  * Better tracing and message counting
  1770.  *
  1771.  * Revision 6.78  2003/01/16 19:45:18  lavr
  1772.  * Minor patching and cleaning
  1773.  *
  1774.  * Revision 6.77  2003/01/16 16:32:34  lavr
  1775.  * Better logging; few minor patches in datagram socket API functions
  1776.  *
  1777.  * Revision 6.76  2003/01/15 19:52:47  lavr
  1778.  * Datagram sockets added
  1779.  *
  1780.  * Revision 6.75  2002/12/06 16:38:35  lavr
  1781.  * Fix for undefined h_errno on MacOS 9
  1782.  *
  1783.  * Revision 6.74  2002/12/06 15:06:54  lavr
  1784.  * Add missing x_errno definition in s_Connect() for non-Unix platforms
  1785.  *
  1786.  * Revision 6.73  2002/12/05 21:44:12  lavr
  1787.  * Implement SOCK_STRERROR() and do more accurate error logging
  1788.  *
  1789.  * Revision 6.72  2002/12/05 16:31:14  lavr
  1790.  * Define SOCK_Create() as a call
  1791.  *
  1792.  * Revision 6.71  2002/12/04 21:01:05  lavr
  1793.  * -CORE_LOG[F]_SYS_ERRNO()
  1794.  *
  1795.  * Revision 6.70  2002/12/04 16:55:02  lavr
  1796.  * Implement logging on connect and close
  1797.  *
  1798.  * Revision 6.69  2002/11/08 17:18:18  lavr
  1799.  * Minor change: spare -1 in >= by replacing it with >
  1800.  *
  1801.  * Revision 6.68  2002/11/01 20:12:55  lavr
  1802.  * Reimplement SOCK_gethostname() - was somewhat potentally buggy
  1803.  *
  1804.  * Revision 6.67  2002/10/29 22:20:52  lavr
  1805.  * Use proper indentation of preproc. macros; note post-accept() socket state
  1806.  *
  1807.  * Revision 6.66  2002/10/28 15:45:58  lavr
  1808.  * Use "ncbi_ansi_ext.h" privately and use strncpy0()
  1809.  *
  1810.  * Revision 6.65  2002/10/11 19:50:55  lavr
  1811.  * Few renames of internal functions (s_NCBI_Recv, s_Recv, etc)
  1812.  * Interface change: SOCK_gethostbyaddr() returns dotted IP address
  1813.  * when failed to convert given address into FQDN, it also now accepts
  1814.  * 0 to return the name (or dotted IP) of the local host
  1815.  *
  1816.  * Revision 6.64  2002/09/13 19:26:46  lavr
  1817.  * Few style-conforming changes
  1818.  *
  1819.  * Revision 6.63  2002/09/06 15:45:03  lavr
  1820.  * Return eIO_InvalidArg instead of generic eIO_Unknown where appropriate
  1821.  *
  1822.  * Revision 6.62  2002/09/04 15:11:00  lavr
  1823.  * Print ERRNO with failed connection attempt
  1824.  *
  1825.  * Revision 6.61  2002/08/28 15:59:24  lavr
  1826.  * Removed few redundant checks in s_SelectStallsafe()
  1827.  *
  1828.  * Revision 6.60  2002/08/27 03:16:15  lavr
  1829.  * Rename SOCK_htonl -> SOCK_HostToNetLong, SOCK_htons -> SOCK_HostToNetShort
  1830.  *
  1831.  * Revision 6.59  2002/08/15 18:46:52  lavr
  1832.  * s_Select(): do not return immediately if given all NULL sockets in "polls"
  1833.  *
  1834.  * Revision 6.58  2002/08/13 19:51:44  lavr
  1835.  * Fix letter case in s_SetNonblock() call
  1836.  *
  1837.  * Revision 6.57  2002/08/13 19:39:04  lavr
  1838.  * Set accepted socket in non-blocking mode after accept (not inherited)
  1839.  *
  1840.  * Revision 6.56  2002/08/13 19:29:30  lavr
  1841.  * Implement interrupted I/O
  1842.  *
  1843.  * Revision 6.55  2002/08/12 15:06:38  lavr
  1844.  * Implementation of plain and persistent SOCK_Write()
  1845.  *
  1846.  * Revision 6.54  2002/08/07 16:36:45  lavr
  1847.  * Added SOCK_SetInterruptOnSignal[API] calls and support placeholders
  1848.  * Renamed SOCK_GetAddress() -> SOCK_GetPeerAddress() and enum
  1849.  * ENH_ByteOrder employed in the latter call as the last arg
  1850.  * All-UNIX-specific kludge to check connected status on non-blocking socket
  1851.  * Added more checks against SOCK_INVALID and more error log messages
  1852.  *
  1853.  * Revision 6.53  2002/07/18 20:19:58  lebedev
  1854.  * NCBI_OS_MAC: unistd.h added
  1855.  *
  1856.  * Revision 6.52  2002/07/15 19:32:03  lavr
  1857.  * Do not intercept SIGPIPE in the case of an installed signal handler
  1858.  *
  1859.  * Revision 6.51  2002/07/01 20:52:23  lavr
  1860.  * Error (trace) printouts added in s_Select() and s_NCBI_Recv()
  1861.  *
  1862.  * Revision 6.50  2002/06/17 18:28:52  lavr
  1863.  * +BeOS specifics (by Vladimir Ivanov)
  1864.  *
  1865.  * Revision 6.49  2002/06/10 21:14:22  ucko
  1866.  * [SOCK_gethostbyaddr] When using getnameinfo, properly initialize the
  1867.  * sockaddr_in; in particular, set sin_len when present.
  1868.  * Also set sin_len in other functions that build a struct sockaddr_in.
  1869.  *
  1870.  * Revision 6.48  2002/06/10 19:52:45  lavr
  1871.  * Additional failsafe check whether the socket actually connected (Solaris)
  1872.  *
  1873.  * Revision 6.47  2002/05/13 19:49:22  ucko
  1874.  * Indent with spaces rather than tabs
  1875.  *
  1876.  * Revision 6.46  2002/05/13 19:08:11  ucko
  1877.  * Use get{addr,name}info in favor of gethostby{name,addr}(_r) when available
  1878.  *
  1879.  * Revision 6.45  2002/05/06 19:19:43  lavr
  1880.  * Remove unnecessary inits of fields returned from s_Select()
  1881.  *
  1882.  * Revision 6.44  2002/04/26 16:41:16  lavr
  1883.  * Redesign of waiting mechanism, and implementation of SOCK_Poll()
  1884.  *
  1885.  * Revision 6.43  2002/04/22 20:53:16  lavr
  1886.  * +SOCK_htons(); Set close timeout only when the socket was not yet shut down
  1887.  *
  1888.  * Revision 6.42  2002/04/17 20:05:05  lavr
  1889.  * Cosmetic changes
  1890.  *
  1891.  * Revision 6.41  2002/03/22 19:52:19  lavr
  1892.  * Do not include <stdio.h>: included from ncbi_util.h or ncbi_priv.h
  1893.  *
  1894.  * Revision 6.40  2002/02/11 20:36:44  lavr
  1895.  * Use "ncbi_config.h"
  1896.  *
  1897.  * Revision 6.39  2002/01/28 20:29:52  lavr
  1898.  * Distinguish between EOF and severe read error
  1899.  * Return eIO_Success if waiting for read in a stream with EOF already seen
  1900.  *
  1901.  * Revision 6.38  2001/12/03 21:35:32  vakatov
  1902.  * + SOCK_IsServerSide()
  1903.  * SOCK_Reconnect() - check against reconnect of server-side socket to its peer
  1904.  *
  1905.  * Revision 6.37  2001/11/07 19:00:11  vakatov
  1906.  * LSOCK_Accept() -- minor adjustments
  1907.  *
  1908.  * Revision 6.36  2001/08/31 16:00:58  vakatov
  1909.  * [MSWIN] "setsockopt()" -- Start using SO_REUSEADDR on MS-Win.
  1910.  * [MAC]   "setsockopt()" -- Do not use it on MAC whatsoever (as it is not
  1911.  *         implemented in the M.I.T. socket emulation lib).
  1912.  *
  1913.  * Revision 6.35  2001/08/29 17:32:56  juran
  1914.  * Define POSIX macros missing from Universal Interfaces 3.4
  1915.  * in terms of the 'proper' constants.
  1916.  * Complain about unsupported platforms at compile-time, not runtime.
  1917.  *
  1918.  * Revision 6.34  2001/07/11 16:16:39  vakatov
  1919.  * Fixed comments for HAVE_GETHOSTBYNAME_R, HAVE_GETHOSTBYADDR_R; other
  1920.  * minor (style and messages) fixes
  1921.  *
  1922.  * Revision 6.33  2001/07/11 00:54:35  vakatov
  1923.  * SOCK_gethostbyname() and SOCK_gethostbyaddr() -- now can work with
  1924.  * gethostbyname_r() with 6 args and gethostbyaddr_r() with 8 args
  1925.  * (in addition to those with 5 and 7 args, repectively).
  1926.  * [NCBI_OS_IRIX] s_Select() -- no final ASSERT() if built on IRIX.
  1927.  * SOCK_gethostbyaddr() -- added missing CORE_UNLOCK.
  1928.  *
  1929.  * Revision 6.32  2001/06/20 21:26:18  vakatov
  1930.  * As per A.Grichenko/A.Lavrentiev report:
  1931.  *   SOCK_Shutdown() -- typo fixed (use "how" rather than "x_how").
  1932.  *   SOCK_Shutdown(READ) -- do not call system shutdown if EOF was hit.
  1933.  *   Whenever shutdown on both READ and WRITE:  do the WRITE shutdown first.
  1934.  *
  1935.  * Revision 6.31  2001/06/04 21:03:08  vakatov
  1936.  * + HAVE_SOCKLEN_T
  1937.  *
  1938.  * Revision 6.30  2001/05/31 15:42:10  lavr
  1939.  * INADDR_* constants are all and always in host byte order -
  1940.  * this was mistakenly forgotten, and now fixed by use of htonl().
  1941.  *
  1942.  * Revision 6.29  2001/05/23 21:03:35  vakatov
  1943.  * s_SelectStallsafe() -- fix for the interpretation of "default" R-on-W mode
  1944.  * (by A.Lavrentiev)
  1945.  *
  1946.  * Revision 6.28  2001/05/21 15:10:32  ivanov
  1947.  * Added (with Denis Vakatov) automatic read on write data from the socket
  1948.  * (stall protection).
  1949.  * Added functions SOCK_SetReadOnWriteAPI(), SOCK_SetReadOnWrite()
  1950.  * and internal function s_SelectStallsafe().
  1951.  *
  1952.  * Revision 6.27  2001/04/25 19:16:01  juran
  1953.  * Set non-blocking mode on Mac OS. (from pjc)
  1954.  *
  1955.  * Revision 6.26  2001/04/24 21:03:42  vakatov
  1956.  * s_NCBI_Recv()   -- restore "r_status" to eIO_Success on success.
  1957.  * SOCK_Wait(READ) -- return eIO_Success if data pending in the buffer.
  1958.  * (w/A.Lavrentiev)
  1959.  *
  1960.  * Revision 6.25  2001/04/23 22:22:08  vakatov
  1961.  * SOCK_Read() -- special treatment for "buf" == NULL
  1962.  *
  1963.  * Revision 6.24  2001/04/04 14:58:59  vakatov
  1964.  * Cleaned up after R6.23 (and get rid of the C++ style comments)
  1965.  *
  1966.  * Revision 6.23  2001/04/03 20:30:15  juran
  1967.  * Changes to work with OT sockets.
  1968.  * Not all of pjc's changes are here -- I will test them shortly.
  1969.  *
  1970.  * Revision 6.22  2001/03/29 21:15:36  lavr
  1971.  * More accurate length calculation in 'SOCK_gethostbyaddr'
  1972.  *
  1973.  * Revision 6.21  2001/03/22 17:43:54  vakatov
  1974.  * Typo fixed in the SOCK_AllowSigPipeAPI() proto
  1975.  *
  1976.  * Revision 6.20  2001/03/22 17:40:36  vakatov
  1977.  * + SOCK_AllowSigPipeAPI()
  1978.  *
  1979.  * Revision 6.19  2001/03/06 23:54:20  lavr
  1980.  * Renamed: SOCK_gethostaddr -> SOCK_gethostbyname
  1981.  * Added:   SOCK_gethostbyaddr
  1982.  *
  1983.  * Revision 6.18  2001/03/02 20:10:29  lavr
  1984.  * Typos fixed
  1985.  *
  1986.  * Revision 6.17  2001/02/28 00:55:38  lavr
  1987.  * SOCK_gethostaddr: InitAPI added, SOCK_gethostname used instead of
  1988.  * gethostname
  1989.  *
  1990.  * Revision 6.16  2001/01/26 23:50:32  vakatov
  1991.  * s_NCBI_Recv() -- added check for ENOTCONN to catch EOF (mostly for Mac)
  1992.  *
  1993.  * Revision 6.15  2001/01/25 17:10:41  lavr
  1994.  * The following policy applied: on either read or write,
  1995.  * n_read and n_written returned to indicate actual number of passed
  1996.  * bytes, regardless of error status. eIO_Success means that the
  1997.  * operation went through smoothly, while any other status has to
  1998.  * be analyzed. Anyway, the number of passed bytes prior the error
  1999.  * occurred is returned in n_read and n_written respectively.
  2000.  *
  2001.  * Revision 6.14  2001/01/23 23:19:34  lavr
  2002.  * Typo fixed in comment
  2003.  *
  2004.  * Revision 6.13  2000/12/28 21:26:27  lavr
  2005.  * Cosmetic fix to get rid of "converting -1 to unsigned" warning
  2006.  *
  2007.  * Revision 6.12  2000/12/26 21:40:03  lavr
  2008.  * SOCK_Read modified to handle properly the case of 0 byte reading
  2009.  *
  2010.  * Revision 6.11  2000/12/05 23:27:09  lavr
  2011.  * Added SOCK_gethostaddr
  2012.  *
  2013.  * Revision 6.10  2000/12/04 17:34:19  beloslyu
  2014.  * the order of include files is important, especially on other Unixes!
  2015.  * Look the man on inet_ntoa
  2016.  *
  2017.  * Revision 6.9  2000/11/22 19:29:16  vakatov
  2018.  * SOCK_Create() -- pre-set the sock handle to SOCK_INVALID before connect
  2019.  *
  2020.  * Revision 6.8  2000/11/15 18:51:21  vakatov
  2021.  * Add SOCK_Shutdown() and SOCK_Status().  Remove SOCK_Eof().
  2022.  * Add more checking and diagnostics.
  2023.  * [NOTE: not tested on Mac]
  2024.  *
  2025.  * Revision 6.7  2000/06/23 19:34:44  vakatov
  2026.  * Added means to log binary data
  2027.  *
  2028.  * Revision 6.6  2000/05/30 23:31:44  vakatov
  2029.  * SOCK_host2inaddr() renamed to SOCK_ntoa(), the home-made out-of-scratch
  2030.  * implementation to work properly with GCC on IRIX64 platforms
  2031.  *
  2032.  * Revision 6.5  2000/03/24 23:12:08  vakatov
  2033.  * Starting the development quasi-branch to implement CONN API.
  2034.  * All development is performed in the NCBI C++ tree only, while
  2035.  * the NCBI C tree still contains "frozen" (see the last revision) code.
  2036.  *
  2037.  * Revision 6.4  2000/02/23 22:34:35  vakatov
  2038.  * Can work both "standalone" and as a part of NCBI C++ or C toolkits
  2039.  *
  2040.  * Revision 6.3  1999/10/19 22:21:48  vakatov
  2041.  * Put the call to "gethostbyname()" into a CRITICAL_SECTION
  2042.  *
  2043.  * Revision 6.2  1999/10/19 16:16:01  vakatov
  2044.  * Try the NCBI C and C++ headers only if NCBI_OS_{UNIX, MSWIN, MAC} is
  2045.  * not #define'd
  2046.  *
  2047.  * Revision 6.1  1999/10/18 15:36:38  vakatov
  2048.  * Initial revision (derived from the former "ncbisock.[ch]")
  2049.  *
  2050.  * ===========================================================================
  2051.  */