ncbi_socket.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:153k
- }
- x_how = SOCK_SHUTDOWN_RDWR;
- sock->eof = 0/*false*/;
- sock->r_status = sock->w_status = eIO_Closed;
- break;
- #else
- {{
- EIO_Status sw = s_Shutdown(sock, eIO_Write, tv);
- EIO_Status sr = s_Shutdown(sock, eIO_Read, tv);
- if (sw != eIO_Success || sr != eIO_Success)
- return (sw == eIO_Success ? sr :
- sr == eIO_Success ? sw : eIO_Unknown);
- }}
- return eIO_Success;
- #endif /*NCBI_OS_MSWIN*/
- default:
- CORE_LOGF(eLOG_Error, ("%s[SOCK::s_Shutdown] Invalid direction %u",
- s_ID(sock, _id), (unsigned int) how));
- return eIO_InvalidArg;
- }
- if (SOCK_SHUTDOWN(sock->sock, x_how) != 0) {
- int x_errno = SOCK_ERRNO;
- if (
- #if defined(NCBI_OS_LINUX)/*bug in the Linux kernel to report*/ ||
- defined(NCBI_OS_IRIX) ||
- defined(NCBI_OS_OSF1)
- x_errno != SOCK_ENOTCONN
- #else
- x_errno != SOCK_ENOTCONN || sock->pending
- #endif /*UNIX flavors*/
- )
- CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
- ("%s[SOCK::s_Shutdown] Failed shutdown(%s)",
- s_ID(sock, _id), how == eIO_Read ? "READ" :
- how == eIO_Write ? "WRITE" : "READ/WRITE"));
- }
- return eIO_Success;
- }
- /* Close the socket
- */
- static EIO_Status s_Close(SOCK sock)
- {
- EIO_Status status;
- char _id[32];
- /* reset the auxiliary data buffers */
- s_WipeRBuf(sock);
- if (sock->type == eSOCK_Datagram) {
- s_WipeWBuf(sock);
- } else if (sock->type != eSOCK_ServerSideKeep) {
- /* set the close()'s linger period be equal to the close timeout */
- #if (defined(NCBI_OS_UNIX) && !defined(NCBI_OS_BEOS)) || defined(NCBI_OS_MSWIN)
- /* setsockopt() is not implemented for MAC (MIT socket emulation lib)*/
- if (sock->w_status != eIO_Closed && (!sock->c_timeout ||
- sock->c_timeout->tv_sec ||
- sock->c_timeout->tv_usec)) {
- const struct timeval* tv = sock->c_timeout;
- unsigned int tmo;
- struct linger lgr;
- if (!tv)
- tmo = 120; /*this is a standard TCP TTL, 2 minutes*/
- else if (!(tmo = tv->tv_sec + (tv->tv_usec + 500000)/1000000))
- tmo = 1;
- lgr.l_onoff = 1;
- lgr.l_linger = tmo;
- if (setsockopt(sock->sock, SOL_SOCKET, SO_LINGER,
- (char*) &lgr, sizeof(lgr)) != 0) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
- ("%s[SOCK::s_Close] Failed "
- "setsockopt(SO_LINGER)", s_ID(sock, _id)));
- }
- }
- #endif /*(NCBI_OS_UNIX && !NCBI_OS_BEOS) || NCBI_OS_MSWIN*/
- /* shutdown in both directions */
- s_Shutdown(sock, eIO_ReadWrite, sock->c_timeout);
- /* set the socket back to blocking mode */
- if ( !s_SetNonblock(sock->sock, 0/*false*/) ) {
- CORE_LOGF(eLOG_Warning,("%s[SOCK::s_Close] Cannot set socket "
- "back to blocking mode", s_ID(sock, _id)));
- }
- } else {
- status = s_WritePending(sock, sock->c_timeout, 0);
- if (status != eIO_Success) {
- CORE_LOGF(eLOG_Warning, ("%s[SOCK::s_Close] Leaving with some "
- "output data pending (%s)",
- s_ID(sock, _id), IO_StatusStr(status)));
- }
- }
- sock->w_len = 0;
- /* statistics & logging */
- if (sock->type != eSOCK_Datagram) {
- sock->n_in += sock->n_read;
- sock->n_out += sock->n_written;
- }
- if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn))
- s_DoLog(sock, eIO_Close, 0, 0, 0);
- status = eIO_Success;
- if (sock->type != eSOCK_ServerSideKeep) {
- for (;;) { /* close persistently - retry if interrupted by a signal */
- if (SOCK_CLOSE(sock->sock) == 0)
- break;
- /* error */
- if (SOCK_ERRNO != SOCK_EINTR) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
- ("%s[SOCK::s_Close] "
- " Failed close()", s_ID(sock, _id)));
- status = eIO_Unknown;
- break;
- }
- }
- }
- /* return */
- sock->sock = SOCK_INVALID;
- return status;
- }
- extern EIO_Status SOCK_Create(const char* host,
- unsigned short port,
- const STimeout* timeout,
- SOCK* sock)
- {
- return SOCK_CreateEx(host, port, timeout, sock, 0, 0, eDefault);
- }
- extern EIO_Status SOCK_CreateEx(const char* host,
- unsigned short port,
- const STimeout* timeout,
- SOCK* sock,
- const void* data,
- size_t datalen,
- ESwitch log)
- {
- unsigned int x_id = ++s_ID_Counter * 1000;
- SOCK x_sock;
- *sock = 0;
- /* allocate memory for the internal socket structure */
- if (!(x_sock = (SOCK) calloc(1, sizeof(*x_sock))))
- return eIO_Unknown;
- x_sock->sock = SOCK_INVALID;
- x_sock->id = x_id;
- x_sock->log = log;
- x_sock->type = eSOCK_ClientSide;
- /* setup the I/O data buffer properties */
- BUF_SetChunkSize(&x_sock->r_buf, SOCK_BUF_CHUNK_SIZE);
- if (datalen) {
- if (!BUF_SetChunkSize(&x_sock->w_buf, datalen) ||
- !BUF_Write(&x_sock->w_buf, data, datalen)) {
- char _id[32];
- CORE_LOGF_ERRNO(eLOG_Error, errno,
- ("%s[SOCK::CreateEx] "
- " Cannot store initial data", s_ID(x_sock, _id)));
- SOCK_Close(x_sock);
- return eIO_Unknown;
- }
- }
- /* connect */
- {{
- EIO_Status status;
- if ((status = s_Connect(x_sock, host, port, timeout)) != eIO_Success) {
- SOCK_Close(x_sock);
- return status;
- }
- }}
- /* success */
- x_sock->r_on_w = eDefault;
- x_sock->i_on_sig = eDefault;
- *sock = x_sock;
- return eIO_Success;
- }
- extern EIO_Status SOCK_CreateOnTop(const void* handle,
- size_t handle_size,
- SOCK* sock)
- {
- return SOCK_CreateOnTopEx(handle, handle_size, sock, 0, 0,
- eDefault, eSCOT_CloseOnClose);
- }
- extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
- size_t handle_size,
- SOCK* sock,
- const void* data,
- size_t datalen,
- ESwitch log,
- ESCOT_OnClose on_close)
- {
- union {
- struct sockaddr sa;
- struct sockaddr_in in;
- #ifdef NCBI_OS_UNIX
- struct sockaddr_un un;
- #endif /*NCBI_OS_UNIX*/
- } peer;
- SOCK x_sock;
- TSOCK_Handle xx_sock;
- BUF w_buf = 0;
- unsigned int x_id = ++s_ID_Counter * 1000;
- SOCK_socklen_t peerlen;
- size_t socklen;
- *sock = 0;
- assert(!datalen || data);
- if (!handle || handle_size != sizeof(xx_sock)) {
- CORE_LOGF(eLOG_Error, ("SOCK#%u[?]: [SOCK::CreateOnTopEx] "
- " Invalid handle %s%lu", x_id,
- handle ? "size " : "",
- handle ? (unsigned long) handle_size : 0));
- assert(0);
- return eIO_InvalidArg;
- }
- memcpy(&xx_sock, handle, sizeof(xx_sock));
- /* initialize internals */
- verify(s_Initialized || SOCK_InitializeAPI() == eIO_Success);
- /* get peer's address */
- peerlen = (SOCK_socklen_t) sizeof(peer);
- memset(&peer, 0, peerlen);
- #ifdef HAVE_SIN_LEN
- peer.sa.sa_len = sizeof(peer);
- #endif
- if (getpeername(xx_sock, &peer.sa, &peerlen) < 0)
- return eIO_Closed;
- #ifdef NCBI_OS_UNIX
- if (peer.sa.sa_family != AF_INET && peer.sa.sa_family != AF_UNIX)
- # if defined(NCBI_OS_BSD) ||
- defined(NCBI_OS_DARWIN) ||
- defined(NCBI_OS_IRIX)
- if (peer.sa.sa_family != AF_UNSPEC/*0*/)
- # endif /*NCBI_OS_???*/
- return eIO_InvalidArg;
- #else
- if (peer.sa.sa_family != AF_INET)
- return eIO_InvalidArg;
- #endif /*NCBI_OS_UNIX*/
- #ifdef NCBI_OS_UNIX
- if (
- # if defined(NCBI_OS_BSD) ||
- defined(NCBI_OS_DARWIN) ||
- defined(NCBI_OS_IRIX)
- peer.sa.sa_family == AF_UNSPEC/*0*/ ||
- # endif /*NCBI_OS_???*/
- peer.sa.sa_family == AF_UNIX) {
- if (!peer.un.sun_path[0]) {
- peerlen = (SOCK_socklen_t) sizeof(peer);
- memset(&peer, 0, sizeof(peer));
- # ifdef HAVE_SIN_LEN
- peer.sa.sa_len = sizeof(peer);
- # endif
- if (getsockname(xx_sock, &peer.sa, &peerlen) < 0)
- return eIO_Closed;
- assert(peer.sa.sa_family == AF_UNIX);
- if (!peer.un.sun_path[0]) {
- CORE_LOGF(eLOG_Error, ("SOCK#%u[%u]: [SOCK::CreateOnTopEx] "
- " Unbound UNIX socket",
- x_id, (unsigned int) xx_sock));
- assert(0);
- return eIO_InvalidArg;
- }
- }
- socklen = strlen(peer.un.sun_path);
- } else
- #endif /*NCBI_OS_UNIX*/
- socklen = 0;
-
- /* store initial data */
- if (datalen && (!BUF_SetChunkSize(&w_buf, datalen) ||
- !BUF_Write(&w_buf, data, datalen))) {
- CORE_LOGF_ERRNO(eLOG_Error, errno,
- ("SOCK#%u[%u]: [SOCK::CreateOnTopEx] Cannot store "
- "initial data", x_id, (unsigned int) xx_sock));
- BUF_Destroy(w_buf);
- return eIO_Unknown;
- }
-
- /* create and fill socket handle */
- if (!(x_sock = (SOCK) calloc(1, sizeof(*x_sock) + socklen))) {
- BUF_Destroy(w_buf);
- return eIO_Unknown;
- }
- x_sock->sock = xx_sock;
- x_sock->id = x_id;
- #ifdef NCBI_OS_UNIX
- if (peer.sa.sa_family != AF_UNIX) {
- x_sock->host = peer.in.sin_addr.s_addr;
- x_sock->port = peer.in.sin_port;
- } else
- strcpy(x_sock->file, peer.un.sun_path);
- #else
- x_sock->host = peer.in.sin_addr.s_addr;
- x_sock->port = peer.in.sin_port;
- #endif /*NCBI_OS_UNIX*/
- x_sock->log = log;
- x_sock->type = (on_close != eSCOT_KeepOnClose
- ? eSOCK_ServerSide
- : eSOCK_ServerSideKeep);
- x_sock->r_on_w = eDefault;
- x_sock->i_on_sig = eDefault;
- x_sock->r_status = eIO_Success;
- x_sock->eof = 0/*false*/;
- x_sock->w_status = eIO_Success;
- x_sock->pending = 1/*have to check at the nearest I/O*/;
- /* all timeouts zeroed - infinite */
- BUF_SetChunkSize(&x_sock->r_buf, SOCK_BUF_CHUNK_SIZE);
- x_sock->w_buf = w_buf;
- x_sock->w_len = datalen;
- /* set to non-blocking mode */
- if ( !s_SetNonblock(xx_sock, 1/*true*/) ) {
- char _id[32];
- CORE_LOGF(eLOG_Error, ("%s[SOCK::CreateOnTopEx] Cannot set socket "
- "to non-blocking mode", s_ID(x_sock, _id)));
- x_sock->sock = SOCK_INVALID;
- SOCK_Close(x_sock);
- return eIO_Unknown;
- }
-
- /* statistics & logging */
- if (log == eOn || (log == eDefault && s_Log == eOn))
- s_DoLog(x_sock, eIO_Open, &peer, 0, &peer.sa);
- /* success */
- *sock = x_sock;
- return eIO_Success;
- }
- extern EIO_Status SOCK_Reconnect(SOCK sock,
- const char* host,
- unsigned short port,
- const STimeout* timeout)
- {
- char _id[32];
- if (sock->sock == eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] "
- " Datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- #ifdef NCBI_OS_UNIX
- if (sock->file[0]) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] UNIX socket "%s"",
- s_ID(sock, _id), sock->file));
- assert(0);
- return eIO_InvalidArg;
- }
- #endif /*NCBI_OS_UNIX*/
- /* close the socket if necessary */
- if (sock->sock != SOCK_INVALID)
- s_Close(sock);
- /* special treatment for server-side socket */
- if (sock->type & eSOCK_ServerSide) {
- if (!host || !*host || !port) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Reconnect] Attempt to reconnect "
- "server-side socket as the client one to "
- "its peer address", s_ID(sock, _id)));
- return eIO_InvalidArg;
- }
- sock->type = eSOCK_ClientSide;
- }
- /* connect */
- sock->id++;
- sock->n_read = 0;
- sock->n_written = 0;
- return s_Connect(sock, host, port, timeout);
- }
- extern EIO_Status SOCK_Shutdown(SOCK sock,
- EIO_Event how)
- {
- char _id[32];
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Shutdown] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- if (sock->type == eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Shutdown] "
- " Datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- return s_Shutdown(sock, how, sock->w_timeout);
- }
- extern EIO_Status SOCK_CloseEx(SOCK sock, int/*bool*/ destroy)
- {
- EIO_Status status = sock->sock==SOCK_INVALID ? eIO_Success : s_Close(sock);
- assert(sock->sock == SOCK_INVALID);
- if (destroy) {
- BUF_Destroy(sock->r_buf);
- BUF_Destroy(sock->w_buf);
- free(sock);
- }
- return status;
- }
- extern EIO_Status SOCK_Close(SOCK sock)
- {
- return SOCK_CloseEx(sock, 1/*destroy*/);
- }
- extern EIO_Status SOCK_Wait(SOCK sock,
- EIO_Event event,
- const STimeout* timeout)
- {
- char _id[32];
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Wait] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- /* check against already shutdown socket there */
- switch ( event ) {
- case eIO_Read:
- if (BUF_Size(sock->r_buf) != 0)
- return eIO_Success;
- if (sock->type == eSOCK_Datagram)
- return eIO_Closed;
- if (sock->r_status == eIO_Closed) {
- CORE_LOGF(eLOG_Warning, ("%s[SOCK::Wait(R)] Socket has already "
- "been %s", s_ID(sock, _id),
- sock->eof ? "closed" : "shut down"));
- return eIO_Closed;
- }
- if ( sock->eof )
- return eIO_Closed;
- break;
- case eIO_Write:
- if (sock->type == eSOCK_Datagram)
- return eIO_Success;
- if (sock->w_status == eIO_Closed) {
- CORE_LOGF(eLOG_Warning, ("%s[SOCK::Wait(W)] Socket has already "
- "been shut down", s_ID(sock, _id)));
- return eIO_Closed;
- }
- break;
- case eIO_ReadWrite:
- if (sock->type == eSOCK_Datagram || BUF_Size(sock->r_buf) != 0)
- return eIO_Success;
- if ((sock->r_status == eIO_Closed || sock->eof) &&
- (sock->w_status == eIO_Closed)) {
- if (sock->r_status == eIO_Closed) {
- CORE_LOGF(eLOG_Warning, ("%s[SOCK::Wait(RW)] Socket has "
- "already been shut down",
- s_ID(sock, _id)));
- }
- return eIO_Closed;
- }
- if (sock->r_status == eIO_Closed || sock->eof) {
- if (sock->r_status == eIO_Closed) {
- CORE_LOGF(eLOG_Note, ("%s[SOCK::Wait(RW)] Socket has already "
- "been %s", s_ID(sock, _id), sock->eof
- ? "closed" : "shut down for reading"));
- }
- event = eIO_Write;
- break;
- }
- if (sock->w_status == eIO_Closed) {
- CORE_LOGF(eLOG_Note,("%s[SOCK::Wait(RW)] Socket has already been "
- "shut down for writing", s_ID(sock, _id)));
- event = eIO_Read;
- break;
- }
- break;
- default:
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Wait] Invalid event %u",
- s_ID(sock, _id), (unsigned int) event));
- return eIO_InvalidArg;
- }
- assert(sock->type != eSOCK_Datagram);
- /* do wait */
- {{
- struct timeval tv;
- SSOCK_Poll poll;
- EIO_Status status;
- const struct timeval* x_tv = s_to2tv(timeout, &tv);
- if ((status = s_WritePending(sock, x_tv, 0)) != eIO_Success) {
- if (event == eIO_Write || sock->pending)
- return status;
- }
- poll.sock = sock;
- poll.event = event;
- poll.revent = eIO_Open;
- if ((status = s_SelectStallsafe(1, &poll, x_tv, 0)) != eIO_Success)
- return status;
- if (poll.revent == eIO_Close)
- return eIO_Unknown;
- assert(poll.event == poll.revent);
- return status/*success*/;
- }}
- }
- extern EIO_Status SOCK_Poll(size_t n,
- SSOCK_Poll polls[],
- const STimeout* timeout,
- size_t* n_ready)
- {
- SSOCK_Poll xx_polls[2];
- SSOCK_Poll* x_polls;
- EIO_Status status;
- size_t x_n;
- struct timeval tv;
- if ((n == 0) != (polls == 0)) {
- if ( n_ready )
- *n_ready = 0;
- return eIO_InvalidArg;
- }
- for (x_n = 0; x_n < n; x_n++) {
- if (!IS_LISTENING(polls[x_n].sock) &&
- polls[x_n].sock &&
- polls[x_n].sock->sock != SOCK_INVALID &&
- (polls[x_n].event == eIO_Read ||
- polls[x_n].event == eIO_ReadWrite) &&
- BUF_Size(polls[x_n].sock->r_buf) != 0) {
- polls[x_n].revent = eIO_Read;
- } else
- polls[x_n].revent = eIO_Open;
- }
- if (n == 1) {
- xx_polls[0] = polls[0];
- xx_polls[1].sock = 0;
- x_polls = xx_polls;
- x_n = 2;
- } else {
- x_polls = polls;
- x_n = n;
- }
- status = s_SelectStallsafe(x_n, x_polls, s_to2tv(timeout, &tv), n_ready);
- if (n == 1)
- polls[0].revent = xx_polls[0].revent;
- return status;
- }
- extern EIO_Status POLLABLE_Poll(size_t n,
- SPOLLABLE_Poll polls[],
- const STimeout* timeout,
- size_t* n_ready)
- {
- return SOCK_Poll(n, (SSOCK_Poll *const) polls, timeout, n_ready);
- }
- extern POLLABLE POLLABLE_FromSOCK(SOCK sock)
- {
- assert(!sock || !IS_LISTENING(sock));
- return (POLLABLE) sock;
- }
- extern POLLABLE POLLABLE_FromLSOCK(LSOCK lsock)
- {
- assert(!lsock || IS_LISTENING(lsock));
- return (POLLABLE) lsock;
- }
- extern SOCK POLLABLE_ToSOCK(POLLABLE poll)
- {
- SOCK sock = (SOCK) poll;
- return !sock || IS_LISTENING(sock) ? 0 : sock;
- }
- extern LSOCK POLLABLE_ToLSOCK(POLLABLE poll)
- {
- LSOCK lsock = (LSOCK) poll;
- return !lsock || IS_LISTENING(lsock) ? lsock : 0;
- }
- extern EIO_Status SOCK_SetTimeout(SOCK sock,
- EIO_Event event,
- const STimeout* timeout)
- {
- char _id[32];
- switch ( event ) {
- case eIO_Read:
- sock->r_timeout = s_to2tv(timeout, &sock->r_tv);
- break;
- case eIO_Write:
- sock->w_timeout = s_to2tv(timeout, &sock->w_tv);
- break;
- case eIO_ReadWrite:
- sock->r_timeout = s_to2tv(timeout, &sock->r_tv);
- sock->w_timeout = s_to2tv(timeout, &sock->w_tv);
- break;
- case eIO_Close:
- sock->c_timeout = s_to2tv(timeout, &sock->c_tv);
- break;
- default:
- CORE_LOGF(eLOG_Error, ("%s[SOCK::SetTimeout] Invalid event %u",
- s_ID(sock, _id), (unsigned int) event));
- assert(0);
- return eIO_InvalidArg;
- }
- return eIO_Success;
- }
- extern const STimeout* SOCK_GetTimeout(SOCK sock,
- EIO_Event event)
- {
- const STimeout *tr, *tw;
- char _id[32];
- switch ( event ) {
- case eIO_Read:
- return s_tv2to(sock->r_timeout, &sock->r_to);
- case eIO_Write:
- return s_tv2to(sock->w_timeout, &sock->w_to);
- case eIO_ReadWrite:
- /* both timeouts come out normalized */
- tr = s_tv2to(sock->r_timeout, &sock->r_to);
- tw = s_tv2to(sock->w_timeout, &sock->w_to);
- if ( !tr )
- return tw;
- if ( !tw )
- return tr;
- if (tr->sec > tw->sec)
- return tw;
- if (tw->sec > tr->sec)
- return tr;
- assert(tr->sec == tw->sec);
- return tr->usec > tw->usec ? tw : tr;
- case eIO_Close:
- return s_tv2to(sock->c_timeout, &sock->c_to);
- default:
- CORE_LOGF(eLOG_Error, ("%s[SOCK::GetTimeout] Invalid event %u",
- s_ID(sock, _id), (unsigned int) event));
- assert(0);
- }
- return 0;
- }
- extern EIO_Status SOCK_Read(SOCK sock,
- void* buf,
- size_t size,
- size_t* n_read,
- EIO_ReadMethod how)
- {
- EIO_Status status;
- size_t x_read;
- char _id[32];
- if (sock->sock != SOCK_INVALID) {
- switch ( how ) {
- case eIO_ReadPlain:
- status = s_Read(sock, buf, size, &x_read, 0/*false, read*/);
- break;
- case eIO_ReadPeek:
- status = s_Read(sock, buf, size, &x_read, 1/*true, peek*/);
- break;
- case eIO_ReadPersist:
- x_read = 0;
- do {
- size_t xx_read;
- status = SOCK_Read(sock, (char*) buf + (buf? x_read : 0), size,
- &xx_read, eIO_ReadPlain);
- if (status != eIO_Success)
- break;
- x_read += xx_read;
- size -= xx_read;
- } while ( size );
- break;
- default:
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Read] Invalid read method %u",
- s_ID(sock, _id), (unsigned int) how));
- assert(0);
- x_read = 0;
- status = eIO_InvalidArg;
- break;
- }
- } else {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Read] "
- " Invalid socket", s_ID(sock, _id)));
- x_read = 0;
- status = eIO_Closed;
- }
- if ( n_read )
- *n_read = x_read;
- return status;
- }
- extern EIO_Status SOCK_PushBack(SOCK sock,
- const void* buf,
- size_t size)
- {
- if (sock->sock == SOCK_INVALID) {
- char _id[32];
- CORE_LOGF(eLOG_Error, ("%s[SOCK::PushBack] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- return BUF_PushBack(&sock->r_buf, buf, size) ? eIO_Success : eIO_Unknown;
- }
- extern EIO_Status SOCK_Write(SOCK sock,
- const void* buf,
- size_t size,
- size_t* n_written,
- EIO_WriteMethod how)
- {
- EIO_Status status;
- char _id[32];
- size_t x_written;
- if (sock->sock != SOCK_INVALID) {
- switch ( how ) {
- case eIO_WritePlain:
- status = s_Write(sock, buf, size, &x_written);
- break;
- case eIO_WritePersist:
- x_written = 0;
- do {
- size_t xx_written;
- status = SOCK_Write(sock, (char*) buf + x_written, size,
- &xx_written, eIO_WritePlain);
- if (status != eIO_Success)
- break;
- x_written += xx_written;
- size -= xx_written;
- } while ( size );
- break;
- default:
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Write] Invalid write method %u",
- s_ID(sock, _id), (unsigned int) how));
- assert(0);
- x_written = 0;
- status = eIO_InvalidArg;
- break;
- }
- } else {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Write] "
- " Invalid socket", s_ID(sock, _id)));
- x_written = 0;
- status = eIO_Closed;
- }
- if ( n_written )
- *n_written = x_written;
- return status;
- }
- extern EIO_Status SOCK_Abort(SOCK sock)
- {
- char _id[32];
- EIO_Status status;
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Warning, ("%s[SOCK::Abort] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- if (sock->type == eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[SOCK::Abort] "
- " Datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- sock->eof = 0;
- sock->w_len = 0;
- sock->pending = 0;
- sock->r_status = sock->w_status = eIO_Closed;
- if (SOCK_CLOSE(sock->sock) != 0) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("%s[SOCK::Abort] "
- " Failed close()", s_ID(sock, _id)));
- status = eIO_Unknown;
- } else
- status = eIO_Success;
- sock->sock = SOCK_INVALID;
- return status;
- }
- extern EIO_Status SOCK_Status(SOCK sock,
- EIO_Event direction)
- {
- if (direction != eIO_Read && direction != eIO_Write) {
- if (direction == eIO_Open)
- return sock->sock == SOCK_INVALID ? eIO_Closed : eIO_Success;
- return eIO_InvalidArg;
- }
- return (sock->sock == SOCK_INVALID ? eIO_Closed :
- sock->pending ? eIO_Timeout : s_Status(sock, direction));
- }
- extern void SOCK_GetPeerAddress(SOCK sock,
- unsigned int* host,
- unsigned short* port,
- ENH_ByteOrder byte_order)
- {
- if ( host ) {
- *host = (unsigned int)
- (byte_order != eNH_HostByteOrder ? sock->host : ntohl(sock->host));
- }
- if ( port ) {
- *port = (unsigned short)
- (byte_order != eNH_HostByteOrder ? sock->port : ntohs(sock->port));
- }
- }
- extern char* SOCK_GetPeerAddressString(SOCK sock,
- char* buf,
- size_t buflen)
- {
- if (!buf || !buflen)
- return 0;
- #ifdef NCBI_OS_UNIX
- if (sock->file[0])
- strncpy0(buf, sock->file, buflen - 1);
- else
- #endif /*NCBI_OS_UNIX*/
- HostPortToString(sock->host, ntohs(sock->port), buf, buflen);
- return buf;
- }
- extern EIO_Status SOCK_GetOSHandle(SOCK sock,
- void* handle,
- size_t handle_size)
- {
- if (!handle || handle_size != sizeof(sock->sock)) {
- char _id[32];
- CORE_LOGF(eLOG_Error,("%s[SOCK::GetOSHandle] Invalid handle %s%lu",
- s_ID(sock, _id), handle ? "size " : "",
- handle ? (unsigned long) handle_size : 0));
- assert(0);
- return eIO_InvalidArg;
- }
- memcpy(handle, &sock->sock, handle_size);
- return sock->sock == SOCK_INVALID ? eIO_Closed : eIO_Success;
- }
- extern ESwitch SOCK_SetReadOnWriteAPI(ESwitch on_off)
- {
- ESwitch old = s_ReadOnWrite;
- if (on_off == eDefault)
- on_off = eOff;
- s_ReadOnWrite = on_off;
- return old;
- }
- extern ESwitch SOCK_SetReadOnWrite(SOCK sock, ESwitch on_off)
- {
- if (sock->type != eSOCK_Datagram) {
- ESwitch old = sock->r_on_w;
- sock->r_on_w = on_off;
- return old;
- }
- return eDefault;
- }
- extern ESwitch SOCK_SetInterruptOnSignalAPI(ESwitch on_off)
- {
- ESwitch old = s_InterruptOnSignal;
- if (on_off == eDefault)
- on_off = eOff;
- s_InterruptOnSignal = on_off;
- return old;
- }
- extern ESwitch SOCK_SetInterruptOnSignal(SOCK sock, ESwitch on_off)
- {
- ESwitch old = sock->i_on_sig;
- sock->i_on_sig = on_off;
- return old;
- }
- extern ESwitch SOCK_SetReuseAddressAPI(ESwitch on_off)
- {
- int old = s_ReuseAddress;
- s_ReuseAddress = on_off == eOn ? 1 : 0;
- return old ? eOn : eOff;
- }
- extern void SOCK_SetReuseAddress(SOCK sock, int/*bool*/ on_off)
- {
- if (sock->sock != SOCK_INVALID && !s_SetReuseAddress(sock->sock, on_off)) {
- int x_errno = SOCK_ERRNO;
- char _id[32];
- CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
- ("%s[SOCK::SetReuseAddress] "
- " Failed setsockopt(%sREUSEADDR)",
- s_ID(sock, _id), on_off ? "" : "NO"));
- }
- }
- extern EIO_Status DSOCK_Create(SOCK* sock)
- {
- return DSOCK_CreateEx(sock, eDefault);
- }
- extern EIO_Status DSOCK_CreateEx(SOCK* sock, ESwitch log)
- {
- unsigned int x_id = ++s_ID_Counter * 1000;
- TSOCK_Handle x_sock;
- *sock = 0;
- /* initialize internals */
- verify(s_Initialized || SOCK_InitializeAPI() == eIO_Success);
- /* create new datagram socket */
- if ((x_sock = socket(AF_INET, SOCK_DGRAM, 0)) == SOCK_INVALID) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("SOCK#%u[?]: [DSOCK::Create] "
- " Cannot create socket", x_id));
- return eIO_Unknown;
- }
- /* set to non-blocking mode */
- if ( !s_SetNonblock(x_sock, 1/*true*/) ) {
- CORE_LOGF(eLOG_Error, ("SOCK#%u[%u]: [DSOCK::Create] Cannot set "
- "socket to non-blocking mode", x_id, x_sock));
- SOCK_CLOSE(x_sock);
- return eIO_Unknown;
- }
- if ( !(*sock = (SOCK) calloc(1, sizeof(**sock))) ) {
- SOCK_CLOSE(x_sock);
- return eIO_Unknown;
- }
- /* success... */
- (*sock)->sock = x_sock;
- (*sock)->id = x_id;
- /* no host and port - not "connected" */
- (*sock)->log = log;
- (*sock)->type = eSOCK_Datagram;
- (*sock)->r_on_w = eOff;
- (*sock)->i_on_sig = eDefault;
- (*sock)->r_status = eIO_Success;
- (*sock)->eof = 0/*false*/;
- (*sock)->w_status = eIO_Success;
- /* all timeouts cleared - infinite */
- BUF_SetChunkSize(&(*sock)->r_buf, SOCK_BUF_CHUNK_SIZE);
- BUF_SetChunkSize(&(*sock)->w_buf, SOCK_BUF_CHUNK_SIZE);
- /* statistics & logging */
- if (log == eOn || (log == eDefault && s_Log == eOn))
- s_DoLog(*sock, eIO_Open, 0, 0, 0);
- return eIO_Success;
- }
- extern EIO_Status DSOCK_Bind(SOCK sock, unsigned short port)
- {
- struct sockaddr_in addr;
- char _id[32];
- if (sock->type != eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::Bind] "
- " Not a datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::Bind] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- /* bind */
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(port);
- #ifdef HAVE_SIN_LEN
- addr.sin_len = sizeof(addr);
- #endif /*HAVE_SIN_LEN*/
- if (bind(sock->sock, (struct sockaddr*) &addr, sizeof(addr)) !=0 ) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("%s[DSOCK::Bind] Failed bind()", s_ID(sock,_id)));
- return x_errno == SOCK_EADDRINUSE ? eIO_Closed : eIO_Unknown;
- }
- /* statistics & logging */
- if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn))
- s_DoLog(sock, eIO_Open, 0, 0, (struct sockaddr*) &addr);
- return eIO_Success;
- }
- extern EIO_Status DSOCK_Connect(SOCK sock,
- const char* host, unsigned short port)
- {
- struct sockaddr_in peer;
- char _id[32];
- if (sock->type != eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect] "
- " Not a datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- /* drop all pending data */
- s_WipeRBuf(sock);
- s_WipeWBuf(sock);
- sock->id++;
- /* obtain host and port of the peer */
- if ( port )
- sock->port = htons(port);
- if (host && *host) {
- if ((sock->host = SOCK_gethostbyname(host)) == 0) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect] Failed "
- "SOCK_gethostbyname("%.64s")",
- s_ID(sock, _id), host));
- return eIO_Unknown;
- }
- }
- if (!sock->host || !sock->port) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::Connect] "
- " Address incomplete", s_ID(sock, _id)));
- return eIO_InvalidArg;
- }
- /* connect */
- memset(&peer, 0, sizeof(peer));
- peer.sin_family = AF_INET;
- peer.sin_addr.s_addr = sock->host;
- peer.sin_port = sock->port;
- #ifdef HAVE_SIN_LEN
- peer.sin_len = sizeof(peer);
- #endif /*HAVE_SIN_LEN*/
- if (connect(sock->sock, (struct sockaddr*) &peer, sizeof(peer)) != 0) {
- char addr[80];
- int x_errno = SOCK_ERRNO;
- HostPortToString(sock->host, sock->port, addr, sizeof(addr));
- CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("%s[DSOCK::Connect] Failed connect() to %s",
- s_ID(sock, _id), addr));
- return eIO_Unknown;
- }
- /* statistics & logging */
- if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn))
- s_DoLog(sock, eIO_Open, &peer, 0, (struct sockaddr*) &peer);
- return eIO_Success;
- }
- extern EIO_Status DSOCK_SendMsg(SOCK sock,
- const char* host,
- unsigned short port,
- const void* data,
- size_t datalen)
- {
- size_t x_msgsize;
- char w[1536];
- EIO_Status status;
- unsigned short x_port;
- unsigned int x_host;
- void* x_msg;
- struct sockaddr_in addr;
- if (sock->type != eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
- " Not a datagram socket", s_ID(sock, w)));
- assert(0);
- return eIO_InvalidArg;
- }
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
- " Invalid socket", s_ID(sock, w)));
- return eIO_Closed;
- }
- if ( datalen ) {
- s_Write(sock, data, datalen, &x_msgsize);
- verify(x_msgsize == datalen);
- }
- sock->eof = 1/*true - finalized message*/;
- x_port = port ? htons(port) : sock->port;
- if (host && *host) {
- if ( !(x_host = SOCK_gethostbyname(host)) ) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] Failed "
- "SOCK_gethostbyname("%.64s")",
- s_ID(sock, w), host));
- return eIO_Unknown;
- }
- } else
- x_host = sock->host;
- if (!x_host || !x_port) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
- " Address incomplete", s_ID(sock, w)));
- return eIO_Unknown;
- }
- if ((x_msgsize = BUF_Size(sock->w_buf)) != 0) {
- if (x_msgsize <= sizeof(w))
- x_msg = w;
- else if ( !(x_msg = malloc(x_msgsize)) )
- return eIO_Unknown;
- verify(BUF_Peek(sock->w_buf, x_msg, x_msgsize) == x_msgsize);
- } else
- x_msg = 0;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = x_host;
- addr.sin_port = x_port;
- #ifdef HAVE_SIN_LEN
- addr.sin_len = sizeof(addr);
- #endif /*HAVE_SIN_LEN*/
- for (;;) { /* optionally auto-resume if interrupted by a signal */
- int x_written;
- int x_errno;
- if ((x_written = sendto(sock->sock, x_msg, x_msgsize, 0/*flags*/,
- (struct sockaddr*) &addr, sizeof(addr))) >= 0){
- /* statistics & logging */
- if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn)){
- s_DoLog(sock, eIO_Write, x_msg, (size_t) x_written,
- (struct sockaddr*) &addr);
- }
- sock->n_written += x_written;
- sock->n_out++;
- if ((size_t) x_written != x_msgsize) {
- sock->w_status = status = eIO_Closed;
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::SendMsg] "
- " Partial datagram sent",s_ID(sock,w)));
- break;
- }
- sock->w_status = status = eIO_Success;
- break;
- }
- /* don't want to handle all possible errors... let them be "unknown" */
- sock->w_status = status = eIO_Unknown;
- x_errno = SOCK_ERRNO;
- /* blocked -- retry if unblocked before the timeout expires */
- /* (use stall protection if specified) */
- if (x_errno == SOCK_EWOULDBLOCK || x_errno == SOCK_EAGAIN) {
- SSOCK_Poll poll;
- poll.sock = sock;
- poll.event = eIO_Write;
- poll.revent = eIO_Open;
- /* stall protection: try pull incoming data from the socket */
- if ((status = s_Select(1, &poll, sock->w_timeout)) != eIO_Success)
- break;
- if (poll.revent == eIO_Close) {
- status = eIO_Unknown;
- break;
- }
- assert(poll.revent == eIO_Write);
- continue;
- }
- if (x_errno != SOCK_EINTR) {
- CORE_LOGF_ERRNO_EX(eLOG_Trace, x_errno, SOCK_STRERROR(x_errno),
- ("%s[DSOCK::SendMsg] "
- " Failed sendto()", s_ID(sock, w)));
- break;
- }
- if (sock->i_on_sig == eOn ||
- (sock->i_on_sig == eDefault && s_InterruptOnSignal == eOn)) {
- sock->w_status = status = eIO_Interrupt;
- break;
- }
- }
- if (x_msg && x_msg != w)
- free(x_msg);
- if (status == eIO_Success)
- sock->w_status = s_WipeWBuf(sock);
- return status;
- }
- extern EIO_Status DSOCK_RecvMsg(SOCK sock,
- void* buf,
- size_t buflen,
- size_t msgsize,
- size_t* msglen,
- unsigned int* sender_addr,
- unsigned short* sender_port)
- {
- size_t x_msgsize;
- char w[1536];
- EIO_Status status;
- void* x_msg;
- if (sock->type != eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::RecvMsg] "
- " Not a datagram socket", s_ID(sock, w)));
- assert(0);
- return eIO_InvalidArg;
- }
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::RecvMsg] "
- " Invalid socket", s_ID(sock, w)));
- return eIO_Closed;
- }
- s_WipeRBuf(sock);
- if ( msglen )
- *msglen = 0;
- if ( sender_addr )
- *sender_addr = 0;
- if ( sender_port )
- *sender_port = 0;
- x_msgsize = (msgsize && msgsize < ((1 << 16) - 1))
- ? msgsize : ((1 << 16) - 1);
- if ( !(x_msg = (x_msgsize <= buflen
- ? buf : (x_msgsize <= sizeof(w)
- ? w : malloc(x_msgsize)))) ) {
- return eIO_Unknown;
- }
- for (;;) { /* auto-resume if either blocked or interrupted (optional) */
- int x_errno;
- int x_read;
- struct sockaddr_in addr;
- #if defined(HAVE_SOCKLEN_T)
- typedef socklen_t SOCK_socklen_t;
- #elif defined(NCBI_OS_MAC)
- typedef UInt32 SOCK_socklen_t;
- #else
- typedef int SOCK_socklen_t;
- #endif /*HAVE_SOCKLEN_T*/
- SOCK_socklen_t addrlen = (SOCK_socklen_t) sizeof(addr);
- #ifdef HAVE_SIN_LEN
- addr.sin_len = addrlen;
- #endif
- x_read = recvfrom(sock->sock, x_msg, x_msgsize, 0,
- (struct sockaddr*) &addr, &addrlen);
- if (x_read >= 0) {
- /* got a message */
- sock->r_status = status = eIO_Success;
- if ( x_read ) {
- if ( msglen )
- *msglen = x_read;
- if ( sender_addr )
- *sender_addr = addr.sin_addr.s_addr;
- if ( sender_port )
- *sender_port = ntohs(addr.sin_port);
- if ((size_t) x_read > buflen &&
- !BUF_Write(&sock->r_buf,
- (char*) x_msg + buflen,
- (size_t)x_read - buflen)) {
- sock->r_status = eIO_Unknown;
- }
- if (buflen && x_msgsize > buflen)
- memcpy(buf, x_msg, buflen);
- }
- /* statistics & logging */
- if (sock->log == eOn || (sock->log == eDefault && s_Log == eOn)){
- s_DoLog(sock, eIO_Read, x_msg, (size_t) x_read,
- (struct sockaddr*) &addr);
- }
- sock->n_read += x_read;
- sock->n_in++;
- break;
- }
- x_errno = SOCK_ERRNO;
- sock->r_status = status = eIO_Unknown;
- if (x_errno != SOCK_EWOULDBLOCK &&
- x_errno != SOCK_EAGAIN &&
- x_errno != SOCK_EINTR) {
- /* catch unknown ERROR */
- CORE_LOGF_ERRNO_EX(eLOG_Trace, x_errno, SOCK_STRERROR(x_errno),
- ("%s[DSOCK::RecvMsg] "
- " Failed recvfrom()", s_ID(sock, w)));
- break;
- }
- if (x_errno == SOCK_EWOULDBLOCK || x_errno == SOCK_EAGAIN) {
- SSOCK_Poll poll;
- poll.sock = sock;
- poll.event = eIO_Read;
- poll.revent = eIO_Open;
- if ((status = s_Select(1, &poll, sock->r_timeout)) != eIO_Success)
- break;
- if (poll.revent == eIO_Close) {
- status = eIO_Closed;
- break;
- }
- assert(poll.event == eIO_Read && poll.revent == eIO_Read);
- continue;
- }
- if (x_errno != SOCK_EINTR)
- break;
- if (sock->i_on_sig == eOn ||
- (sock->i_on_sig == eDefault && s_InterruptOnSignal == eOn)) {
- status = eIO_Interrupt;
- break;
- }
- }
- if (x_msgsize > buflen && x_msg != w)
- free(x_msg);
- return status;
- }
- extern EIO_Status DSOCK_WaitMsg(SOCK sock, const STimeout* timeout)
- {
- char _id[32];
- EIO_Status status;
- SSOCK_Poll poll;
- struct timeval tv;
- if (sock->type != eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::WaitMsg] "
- " Not a datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::WaitMsg] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- poll.sock = sock;
- poll.event = eIO_Read;
- poll.revent = eIO_Open;
- if ((status = s_Select(1, &poll, s_to2tv(timeout, &tv))) != eIO_Success ||
- poll.revent == eIO_Read) {
- return status;
- }
- assert(poll.revent == eIO_Close);
- return eIO_Closed;
- }
- extern EIO_Status DSOCK_WipeMsg(SOCK sock, EIO_Event direction)
- {
- char _id[32];
- EIO_Status status;
- if (sock->type != eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::WipeMsg] "
- " Not a datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::WipeMsg] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- switch (direction) {
- case eIO_Read:
- sock->r_status = status = s_WipeRBuf(sock);
- break;
- case eIO_Write:
- sock->w_status = status = s_WipeWBuf(sock);
- break;
- default:
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::WipeMsg] Invalid direction %u",
- s_ID(sock, _id), (unsigned int) direction));
- assert(0);
- status = eIO_InvalidArg;
- break;
- }
- return status;
- }
- extern EIO_Status DSOCK_SetBroadcast(SOCK sock, int/*bool*/ broadcast)
- {
- char _id[32];
- if (sock->type != eSOCK_Datagram) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::SetBroadcast] "
- " Not a datagram socket", s_ID(sock, _id)));
- assert(0);
- return eIO_InvalidArg;
- }
- if (sock->sock == SOCK_INVALID) {
- CORE_LOGF(eLOG_Error, ("%s[DSOCK::SetBroadcast] "
- " Invalid socket", s_ID(sock, _id)));
- return eIO_Closed;
- }
- #if defined(NCBI_OS_UNIX) || defined(NCBI_OS_MSWIN)
- /* setsockopt() is not implemented for MAC (in MIT socket emulation lib) */
- {{
- # ifdef NCBI_OS_MSWIN
- BOOL bcast = !!broadcast;
- # else
- int bcast = !!broadcast;
- # endif /*NCBI_OS_MSWIN*/
- if (setsockopt(sock->sock, SOL_SOCKET, SO_BROADCAST,
- (const char*) &bcast, sizeof(bcast)) != 0) {
- int x_errno = SOCK_ERRNO;
- CORE_LOGF_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- ("%s[DSOCK::SetBroadcast] "
- " Failed setsockopt(%sBROADCAST)",
- s_ID(sock, _id), bcast ? "" : "NO"));
- return eIO_Unknown;
- }
- }}
- #else
- return eIO_NotSupported;
- #endif /*NCBI_OS_UNIX || NXBI_OS_MSWIN*/
- return eIO_Success;
- }
- extern int/*bool*/ SOCK_IsDatagram(SOCK sock)
- {
- return sock->sock != SOCK_INVALID && sock->type == eSOCK_Datagram;
- }
- extern int/*bool*/ SOCK_IsClientSide(SOCK sock)
- {
- return sock->sock != SOCK_INVALID && sock->type == eSOCK_ClientSide;
- }
- extern int/*bool*/ SOCK_IsServerSide(SOCK sock)
- {
- return sock->sock != SOCK_INVALID && (sock->type & eSOCK_ServerSide);
- }
- extern int SOCK_gethostname(char* name,
- size_t namelen)
- {
- int error = 0;
- /* initialize internals */
- verify(s_Initialized || SOCK_InitializeAPI() == eIO_Success);
- assert(name && namelen > 0);
- name[0] = name[namelen - 1] = ' ';
- if (gethostname(name, (int) namelen) != 0) {
- int x_errno = SOCK_ERRNO;
- CORE_LOG_ERRNO_EX(eLOG_Error, x_errno, SOCK_STRERROR(x_errno),
- "[SOCK_gethostname] Failed gethostname()");
- error = 1;
- } else if ( name[namelen - 1] ) {
- CORE_LOG(eLOG_Error, "[SOCK_gethostname] Buffer too small");
- error = 1;
- }
- if ( !error )
- return 0/*success*/;
- name[0] = ' ';
- return -1/*failed*/;
- }
- extern int SOCK_ntoa(unsigned int host,
- char* buf,
- size_t buflen)
- {
- const unsigned char* b = (const unsigned char*) &host;
- char str[16];
- assert(buf && buflen > 0);
- verify(sprintf(str, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]) > 0);
- assert(strlen(str) < sizeof(str));
- if (strlen(str) >= buflen) {
- buf[0] = ' ';
- return -1/*failed*/;
- }
- strcpy(buf, str);
- return 0/*success*/;
- }
- extern unsigned int SOCK_HostToNetLong(unsigned int value)
- {
- return htonl(value);
- }
- extern unsigned short SOCK_HostToNetShort(unsigned short value)
- {
- return htons(value);
- }
- extern unsigned int SOCK_gethostbyname(const char* hostname)
- {
- unsigned int host;
- char buf[256];
- /* initialize internals */
- verify(s_Initialized || SOCK_InitializeAPI() == eIO_Success);
- if (!hostname || !*hostname) {
- if (SOCK_gethostname(buf, sizeof(buf)) != 0)
- return 0;
- hostname = buf;
- }
- host = inet_addr(hostname);
- if (host == htonl(INADDR_NONE)) {
- int x_errno;
- #if defined(HAVE_GETADDRINFO)
- struct addrinfo hints, *out = 0;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_INET; /* currently, we only handle IPv4 */
- if ((x_errno = getaddrinfo(hostname, 0, &hints, &out)) == 0 && out) {
- struct sockaddr_in* addr = (struct sockaddr_in *) out->ai_addr;
- assert(addr->sin_family == AF_INET);
- host = addr->sin_addr.s_addr;
- } else {
- if (s_Log == eOn) {
- if (x_errno == EAI_SYSTEM)
- x_errno = SOCK_ERRNO;
- else
- x_errno += EAI_BASE;
- CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
- ("[SOCK_gethostbyname] Failed "
- "getaddrinfo("%.64s")", hostname));
- }
- host = 0;
- }
- if ( out ) {
- freeaddrinfo(out);
- }
- #else /* use some variant of gethostbyname */
- struct hostent* he;
- # if defined(HAVE_GETHOSTBYNAME_R)
- static const char suffix[] = "_r";
- struct hostent x_he;
- char x_buf[1024];
- x_errno = 0;
- # if (HAVE_GETHOSTBYNAME_R == 5)
- he = gethostbyname_r(hostname, &x_he, x_buf, sizeof(x_buf), &x_errno);
- # elif (HAVE_GETHOSTBYNAME_R == 6)
- if (gethostbyname_r(hostname, &x_he, x_buf, sizeof(x_buf),
- &he, &x_errno) != 0) {
- assert(he == 0);
- he = 0;
- }
- # else
- # error "Unknown HAVE_GETHOSTBYNAME_R value"
- # endif /*HAVE_GETHOSTNBYNAME_R == N*/
- # else
- static const char suffix[] = "";
- CORE_LOCK_WRITE;
- he = gethostbyname(hostname);
- # ifdef NCBI_OS_MAC
- x_errno = SOCK_ERRNO;
- # else
- x_errno = h_errno + DNS_BASE;
- # endif /*NCBI_OS_MAC*/
- # endif /*HAVE_GETHOSTBYNAME_R*/
- if (he && he->h_addrtype == AF_INET && he->h_length == sizeof(host)) {
- memcpy(&host, he->h_addr, sizeof(host));
- } else {
- host = 0;
- if ( he )
- x_errno = EINVAL;
- }
- # if !defined(HAVE_GETHOSTBYNAME_R)
- CORE_UNLOCK;
- # endif /*HAVE_GETHOSTBYNAME_R*/
- if (!host && s_Log == eOn) {
- # ifdef NETDB_INTERNAL
- if (x_errno == NETDB_INTERNAL + DNS_BASE)
- x_errno = SOCK_ERRNO;
- # endif /*NETDB_INTERNAL*/
- CORE_LOGF_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
- ("[SOCK_gethostbyname] Failed "
- "gethostbyname%s("%.64s")", suffix, hostname));
- }
- #endif /*HAVE_GETADDR_INFO*/
- }
- return host;
- }
- extern char* SOCK_gethostbyaddr(unsigned int host,
- char* name,
- size_t namelen)
- {
- /* initialize internals */
- verify(s_Initialized || SOCK_InitializeAPI() == eIO_Success);
- assert(name && namelen > 0);
- if ( !host ) {
- host = SOCK_gethostbyname(0);
- }
- if ( host ) {
- int x_errno;
- #if defined(HAVE_GETNAMEINFO)
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET; /* currently, we only handle IPv4 */
- addr.sin_addr.s_addr = host;
- # ifdef HAVE_SIN_LEN
- addr.sin_len = sizeof(addr);
- # endif /*HAVE_SIN_LEN*/
- if ((x_errno = getnameinfo((struct sockaddr*) &addr, sizeof(addr),
- name, namelen, 0, 0, 0)) == 0) {
- return name;
- } else {
- if (s_Log == eOn) {
- char addr[16];
- if (x_errno == EAI_SYSTEM)
- x_errno = SOCK_ERRNO;
- else
- x_errno += EAI_BASE;
- if (SOCK_ntoa(host, addr, sizeof(addr)) != 0)
- strcpy(addr, "<unknown>");
- CORE_LOGF_ERRNO_EX(eLOG_Warning,x_errno,SOCK_STRERROR(x_errno),
- ("[SOCK_gethostbyaddr] Failed "
- "getnameinfo(%s)", addr));
- }
- name[0] = ' ';
- return 0;
- }
- #else /* use some variant of gethostbyaddr */
- struct hostent* he;
- # if defined(HAVE_GETHOSTBYADDR_R)
- static const char suffix[] = "_r";
- struct hostent x_he;
- char x_buf[1024];
- x_errno = 0;
- # if (HAVE_GETHOSTBYADDR_R == 7)
- he = gethostbyaddr_r((char*) &host, sizeof(host), AF_INET, &x_he,
- x_buf, sizeof(x_buf), &x_errno);
- # elif (HAVE_GETHOSTBYADDR_R == 8)
- if (gethostbyaddr_r((char*) &host, sizeof(host), AF_INET, &x_he,
- x_buf, sizeof(x_buf), &he, &x_errno) != 0) {
- assert(he == 0);
- he = 0;
- }
- # else
- # error "Unknown HAVE_GETHOSTBYADDR_R value"
- # endif /*HAVE_GETHOSTBYADDR_R == N*/
- # else /*HAVE_GETHOSTBYADDR_R*/
- static const char suffix[] = "";
- CORE_LOCK_WRITE;
- he = gethostbyaddr((char*) &host, sizeof(host), AF_INET);
- # ifdef NCBI_OS_MAC
- x_errno = SOCK_ERRNO;
- # else
- x_errno = h_errno + DNS_BASE;
- # endif /*NCBI_OS_MAC*/
- # endif /*HAVE_GETHOSTBYADDR_R*/
- if (!he || strlen(he->h_name) >= namelen) {
- if (he || SOCK_ntoa(host, name, namelen) != 0) {
- x_errno = ERANGE;
- name[0] = ' ';
- name = 0;
- }
- } else {
- strcpy(name, he->h_name);
- }
- # ifndef HAVE_GETHOSTBYADDR_R
- CORE_UNLOCK;
- # endif /*HAVE_GETHOSTBYADDR_R*/
- if (!name && s_Log == eOn) {
- char addr[16];
- # ifdef NETDB_INTERNAL
- if (x_errno == NETDB_INTERNAL + DNS_BASE)
- x_errno = SOCK_ERRNO;
- # endif /*NETDB_INTERNAL*/
- if (SOCK_ntoa(host, addr, sizeof(addr)) != 0)
- strcpy(addr, "<unknown>");
- CORE_LOG_ERRNO_EX(eLOG_Warning, x_errno, SOCK_STRERROR(x_errno),
- ("[SOCK_gethostbyaddr] Failed "
- "gethostbyaddr%s(%s)", suffix, addr));
- }
- return name;
- #endif /*HAVE_GETNAMEINFO*/
- }
- name[0] = ' ';
- return 0;
- }
- /*
- * ===========================================================================
- * $Log: ncbi_socket.c,v $
- * Revision 1000.4 2004/06/01 18:45:25 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.145
- *
- * Revision 6.145 2004/05/05 11:31:16 ivanov
- * Fixed compile errors
- *
- * Revision 6.144 2004/05/04 19:51:27 lavr
- * More elaborate diagnostics and better event dispatching
- *
- * Revision 6.143 2003/11/25 15:08:40 lavr
- * DSOCK_Connect(): fix diag messages
- *
- * Revision 6.142 2003/11/24 19:21:42 lavr
- * SOCK_SetSelectInternalRestartTimeout() to accept ptr to STimeout
- *
- * Revision 6.141 2003/11/18 20:19:48 lavr
- * +SOCK_SetSelectInternalRestartTimeout() and restart impl. in s_Select()
- *
- * Revision 6.140 2003/11/14 13:05:23 lavr
- * Eliminate race on socket file descriptors in s_Select() when socket aborted
- *
- * Revision 6.138 2003/11/12 17:49:42 lavr
- * Implement close w/o destruction (SOCK_CloseEx()) and make
- * corresponding provisions throughout the file.
- * More consistent return status in SOCK and DSOCK API calls.
- *
- * Revision 6.137 2003/10/27 16:45:46 ivanov
- * Use workaround for unnamed peer's UNIX sockets on DARWIN also.
- *
- * Revision 6.136 2003/10/24 17:39:43 lavr
- * Fix '==' => '!=' bug in s_Select() introduced by previous commit
- *
- * Revision 6.135 2003/10/24 16:52:08 lavr
- * GetTimeout(eIO_ReadWrite): return the lesser of eIO_Read and eIO_Write
- * s_Select(): first check RW bits then E (otherwise, problems on Solaris)
- *
- * Revision 6.134 2003/10/23 12:15:07 lavr
- * Socket feature setters made returning old feature values
- *
- * Revision 6.133 2003/10/14 14:40:44 lavr
- * SOCK_gethostbyname(): fix to obtain local host name in case of empty input
- *
- * Revision 6.132 2003/10/02 16:30:40 lavr
- * s_IsConnected(): Cast buf arg to (void*) in getsockopt()
- *
- * Revision 6.131 2003/10/02 16:04:42 lavr
- * Fix conditional compilation of s_IsConnected() on MS-Windows
- *
- * Revision 6.130 2003/10/02 14:51:22 lavr
- * Better processing of delayed connections
- *
- * Revision 6.129 2003/09/23 21:10:42 lavr
- * s_Select(): Do not check for read in listening socks if write-only requested
- *
- * Revision 6.128 2003/09/05 19:29:50 ivanov
- * SOCK_CreateOnTopEx(): Workaround for unnamed peer's UNIX sockets on IRIX
- *
- * Revision 6.127 2003/09/02 20:59:21 lavr
- * -<connect/ncbi_buffer.h> [expilictly]
- *
- * Revision 6.126 2003/08/25 14:51:13 lavr
- * Change log: typos fixed
- *
- * Revision 6.125 2003/08/25 14:40:05 lavr
- * Sync listening sockets with their SOCK counterparts and implement uniform
- * polling mechanism on sockets of different nature [listening vs connecting]
- *
- * Revision 6.124 2003/08/19 19:45:54 ivanov
- * SOCK_CreateOnTopEx(): Workaround for unnamed peer's UNIX sockets on BSD
- *
- * Revision 6.123 2003/08/18 20:01:13 lavr
- * Retry 'connect()' syscall if interrupted and allowed to restart
- *
- * Revision 6.122 2003/07/24 15:34:29 lavr
- * Fix socket name discovery procedure for UNIX On-Top SOCKs
- *
- * Revision 6.121 2003/07/23 20:31:01 lavr
- * SOCK_CreateOnTopEx(): Do not check for returned peer's address size
- *
- * Revision 6.120 2003/07/18 20:05:49 lavr
- * Fix log message of the previous check-in
- *
- * Revision 6.119 2003/07/18 20:04:49 lavr
- * Close all preprocessor conditionals with #endif's showing the conditions
- *
- * Revision 6.118 2003/07/17 18:28:50 lavr
- * On I/O errors in connected socket: modify only direction affected, not both
- *
- * Revision 6.117 2003/07/15 18:09:07 lavr
- * Fix MS-Win compilation
- *
- * Revision 6.116 2003/07/15 16:50:20 lavr
- * Allow to build on-top SOCKs from UNIX socket fds (on UNIX only)
- * +SOCK_GetPeerAddressString()
- *
- * Revision 6.115 2003/06/09 19:47:52 lavr
- * Few changes to relocate some arg checks and asserts
- *
- * Revision 6.114 2003/06/04 20:59:14 lavr
- * s_Read() not to call s_Select() if read timeout is {0, 0}
- *
- * Revision 6.113 2003/05/31 05:17:32 lavr
- * Swap bitfields and enums in chain assignments
- *
- * Revision 6.112 2003/05/21 17:53:40 lavr
- * Add logs for broken connections; update both R and W status on them
- *
- * Revision 6.111 2003/05/21 04:00:12 lavr
- * Latch connection refusals in SOCK state properly
- *
- * Revision 6.110 2003/05/20 21:20:41 lavr
- * Special treatment of size==0 in SOCK_Write()
- *
- * Revision 6.109 2003/05/20 16:47:56 lavr
- * More accurate checks for pending connections/data
- *
- * Revision 6.108 2003/05/19 21:04:37 lavr
- * Fix omission to make listening sockets "connected"
- *
- * Revision 6.107 2003/05/19 18:47:42 lavr
- * Fix MSVC compilation errors
- *
- * Revision 6.106 2003/05/19 16:51:33 lavr
- * +SOCK_SetReuseAddress[API]() - both experimental!
- * Fix for bitfield signedness in some compilers (including MSVC).
- * More development in I/O tolerance to {0,0}-timeout.
- *
- * Revision 6.105 2003/05/14 15:48:54 lavr
- * Typo fix in s_Shutdown() for MSVC (x_how should be used instead of how)
- *
- * Revision 6.104 2003/05/14 14:51:27 lavr
- * BUGFIX: Connection stall in s_Connect()
- *
- * Revision 6.103 2003/05/14 13:19:18 lavr
- * Define SOCK_SHUTDOWN_RDWR for MSVC compilation
- *
- * Revision 6.102 2003/05/14 05:24:36 lavr
- * FIX: Yet another MSVC compilation fix
- *
- * Revision 6.101 2003/05/14 04:30:58 lavr
- * FIX: MSVC compilation of s_Shutdown()
- *
- * Revision 6.100 2003/05/14 04:28:01 lavr
- * BUGFIX: s_LogData -> s_Log
- *
- * Revision 6.99 2003/05/14 03:50:25 lavr
- * Revamped to allow pending connect and initial data output
- *
- * Revision 6.98 2003/05/05 20:24:13 lavr
- * Added EOF-on-read as a trace event to log when verbose mode is on
- *
- * Revision 6.97 2003/05/05 11:41:09 rsmith
- * added defines and declarations to allow cross compilation Mac->Win32
- * using Metrowerks Codewarrior.
- *
- * Revision 6.96 2003/04/30 17:00:18 lavr
- * Added on-stack buffers for small datagrams; few name collisions resolved
- *
- * Revision 6.95 2003/04/25 15:21:26 lavr
- * Explicit cast of calloc()'s result
- *
- * Revision 6.94 2003/04/14 15:14:20 lavr
- * Define SOCK_socklen_t for Mac's recvfrom() specially
- *
- * Revision 6.93 2003/04/11 20:59:06 lavr
- * Aux type SOCK_socklen_t defined centrally
- *
- * Revision 6.92 2003/04/04 21:00:37 lavr
- * +SOCK_CreateOnTop()
- *
- * Revision 6.91 2003/04/04 20:44:35 rsmith
- * do not include arpa/inet.h on CW with MSL.
- *
- * Revision 6.90 2003/04/03 14:16:18 rsmith
- * combine pp symbols NCBI_COMPILER_METROWERKS & _MSL_USING_MW_C_HEADERS into
- * NCBI_COMPILER_MW_MSL
- *
- * Revision 6.89 2003/04/02 16:21:34 rsmith
- * replace _MWERKS_ with NCBI_COMPILER_METROWERKS
- *
- * Revision 6.88 2003/04/02 13:26:07 rsmith
- * include ncbi_mslextras.h when compiling with MSL libs in Codewarrior.
- *
- * Revision 6.87 2003/03/25 22:18:06 lavr
- * shutdown(): Do not warn on ENOTCONN on SGI and OSF1 (in addition to Linux)
- *
- * Revision 6.86 2003/02/28 14:50:18 lavr
- * Add one more explicit cast to "unsigned" in s_DoLogData()
- *
- * Revision 6.85 2003/02/24 21:13:23 lavr
- * More comments added; fix for read-ahead on shut-down-for-write socket
- *
- * Revision 6.84 2003/02/20 17:52:30 lavr
- * Resolve dead-lock condition in s_SelectStallsafe()
- *
- * Revision 6.83 2003/02/04 22:03:54 lavr
- * Workaround for ENOTCONN in shutdown() on Linux; few more fixes
- *
- * Revision 6.82 2003/01/17 16:56:59 lavr
- * Always clear all pending data when reconnecting
- *
- * Revision 6.81 2003/01/17 15:56:05 lavr
- * Keep as much status as possible in failed pending connect
- *
- * Revision 6.80 2003/01/17 15:11:36 lavr
- * Update stat counters in s_Close() instead of s_Connect()
- *
- * Revision 6.79 2003/01/17 01:23:31 lavr
- * Better tracing and message counting
- *
- * Revision 6.78 2003/01/16 19:45:18 lavr
- * Minor patching and cleaning
- *
- * Revision 6.77 2003/01/16 16:32:34 lavr
- * Better logging; few minor patches in datagram socket API functions
- *
- * Revision 6.76 2003/01/15 19:52:47 lavr
- * Datagram sockets added
- *
- * Revision 6.75 2002/12/06 16:38:35 lavr
- * Fix for undefined h_errno on MacOS 9
- *
- * Revision 6.74 2002/12/06 15:06:54 lavr
- * Add missing x_errno definition in s_Connect() for non-Unix platforms
- *
- * Revision 6.73 2002/12/05 21:44:12 lavr
- * Implement SOCK_STRERROR() and do more accurate error logging
- *
- * Revision 6.72 2002/12/05 16:31:14 lavr
- * Define SOCK_Create() as a call
- *
- * Revision 6.71 2002/12/04 21:01:05 lavr
- * -CORE_LOG[F]_SYS_ERRNO()
- *
- * Revision 6.70 2002/12/04 16:55:02 lavr
- * Implement logging on connect and close
- *
- * Revision 6.69 2002/11/08 17:18:18 lavr
- * Minor change: spare -1 in >= by replacing it with >
- *
- * Revision 6.68 2002/11/01 20:12:55 lavr
- * Reimplement SOCK_gethostname() - was somewhat potentally buggy
- *
- * Revision 6.67 2002/10/29 22:20:52 lavr
- * Use proper indentation of preproc. macros; note post-accept() socket state
- *
- * Revision 6.66 2002/10/28 15:45:58 lavr
- * Use "ncbi_ansi_ext.h" privately and use strncpy0()
- *
- * Revision 6.65 2002/10/11 19:50:55 lavr
- * Few renames of internal functions (s_NCBI_Recv, s_Recv, etc)
- * Interface change: SOCK_gethostbyaddr() returns dotted IP address
- * when failed to convert given address into FQDN, it also now accepts
- * 0 to return the name (or dotted IP) of the local host
- *
- * Revision 6.64 2002/09/13 19:26:46 lavr
- * Few style-conforming changes
- *
- * Revision 6.63 2002/09/06 15:45:03 lavr
- * Return eIO_InvalidArg instead of generic eIO_Unknown where appropriate
- *
- * Revision 6.62 2002/09/04 15:11:00 lavr
- * Print ERRNO with failed connection attempt
- *
- * Revision 6.61 2002/08/28 15:59:24 lavr
- * Removed few redundant checks in s_SelectStallsafe()
- *
- * Revision 6.60 2002/08/27 03:16:15 lavr
- * Rename SOCK_htonl -> SOCK_HostToNetLong, SOCK_htons -> SOCK_HostToNetShort
- *
- * Revision 6.59 2002/08/15 18:46:52 lavr
- * s_Select(): do not return immediately if given all NULL sockets in "polls"
- *
- * Revision 6.58 2002/08/13 19:51:44 lavr
- * Fix letter case in s_SetNonblock() call
- *
- * Revision 6.57 2002/08/13 19:39:04 lavr
- * Set accepted socket in non-blocking mode after accept (not inherited)
- *
- * Revision 6.56 2002/08/13 19:29:30 lavr
- * Implement interrupted I/O
- *
- * Revision 6.55 2002/08/12 15:06:38 lavr
- * Implementation of plain and persistent SOCK_Write()
- *
- * Revision 6.54 2002/08/07 16:36:45 lavr
- * Added SOCK_SetInterruptOnSignal[API] calls and support placeholders
- * Renamed SOCK_GetAddress() -> SOCK_GetPeerAddress() and enum
- * ENH_ByteOrder employed in the latter call as the last arg
- * All-UNIX-specific kludge to check connected status on non-blocking socket
- * Added more checks against SOCK_INVALID and more error log messages
- *
- * Revision 6.53 2002/07/18 20:19:58 lebedev
- * NCBI_OS_MAC: unistd.h added
- *
- * Revision 6.52 2002/07/15 19:32:03 lavr
- * Do not intercept SIGPIPE in the case of an installed signal handler
- *
- * Revision 6.51 2002/07/01 20:52:23 lavr
- * Error (trace) printouts added in s_Select() and s_NCBI_Recv()
- *
- * Revision 6.50 2002/06/17 18:28:52 lavr
- * +BeOS specifics (by Vladimir Ivanov)
- *
- * Revision 6.49 2002/06/10 21:14:22 ucko
- * [SOCK_gethostbyaddr] When using getnameinfo, properly initialize the
- * sockaddr_in; in particular, set sin_len when present.
- * Also set sin_len in other functions that build a struct sockaddr_in.
- *
- * Revision 6.48 2002/06/10 19:52:45 lavr
- * Additional failsafe check whether the socket actually connected (Solaris)
- *
- * Revision 6.47 2002/05/13 19:49:22 ucko
- * Indent with spaces rather than tabs
- *
- * Revision 6.46 2002/05/13 19:08:11 ucko
- * Use get{addr,name}info in favor of gethostby{name,addr}(_r) when available
- *
- * Revision 6.45 2002/05/06 19:19:43 lavr
- * Remove unnecessary inits of fields returned from s_Select()
- *
- * Revision 6.44 2002/04/26 16:41:16 lavr
- * Redesign of waiting mechanism, and implementation of SOCK_Poll()
- *
- * Revision 6.43 2002/04/22 20:53:16 lavr
- * +SOCK_htons(); Set close timeout only when the socket was not yet shut down
- *
- * Revision 6.42 2002/04/17 20:05:05 lavr
- * Cosmetic changes
- *
- * Revision 6.41 2002/03/22 19:52:19 lavr
- * Do not include <stdio.h>: included from ncbi_util.h or ncbi_priv.h
- *
- * Revision 6.40 2002/02/11 20:36:44 lavr
- * Use "ncbi_config.h"
- *
- * Revision 6.39 2002/01/28 20:29:52 lavr
- * Distinguish between EOF and severe read error
- * Return eIO_Success if waiting for read in a stream with EOF already seen
- *
- * Revision 6.38 2001/12/03 21:35:32 vakatov
- * + SOCK_IsServerSide()
- * SOCK_Reconnect() - check against reconnect of server-side socket to its peer
- *
- * Revision 6.37 2001/11/07 19:00:11 vakatov
- * LSOCK_Accept() -- minor adjustments
- *
- * Revision 6.36 2001/08/31 16:00:58 vakatov
- * [MSWIN] "setsockopt()" -- Start using SO_REUSEADDR on MS-Win.
- * [MAC] "setsockopt()" -- Do not use it on MAC whatsoever (as it is not
- * implemented in the M.I.T. socket emulation lib).
- *
- * Revision 6.35 2001/08/29 17:32:56 juran
- * Define POSIX macros missing from Universal Interfaces 3.4
- * in terms of the 'proper' constants.
- * Complain about unsupported platforms at compile-time, not runtime.
- *
- * Revision 6.34 2001/07/11 16:16:39 vakatov
- * Fixed comments for HAVE_GETHOSTBYNAME_R, HAVE_GETHOSTBYADDR_R; other
- * minor (style and messages) fixes
- *
- * Revision 6.33 2001/07/11 00:54:35 vakatov
- * SOCK_gethostbyname() and SOCK_gethostbyaddr() -- now can work with
- * gethostbyname_r() with 6 args and gethostbyaddr_r() with 8 args
- * (in addition to those with 5 and 7 args, repectively).
- * [NCBI_OS_IRIX] s_Select() -- no final ASSERT() if built on IRIX.
- * SOCK_gethostbyaddr() -- added missing CORE_UNLOCK.
- *
- * Revision 6.32 2001/06/20 21:26:18 vakatov
- * As per A.Grichenko/A.Lavrentiev report:
- * SOCK_Shutdown() -- typo fixed (use "how" rather than "x_how").
- * SOCK_Shutdown(READ) -- do not call system shutdown if EOF was hit.
- * Whenever shutdown on both READ and WRITE: do the WRITE shutdown first.
- *
- * Revision 6.31 2001/06/04 21:03:08 vakatov
- * + HAVE_SOCKLEN_T
- *
- * Revision 6.30 2001/05/31 15:42:10 lavr
- * INADDR_* constants are all and always in host byte order -
- * this was mistakenly forgotten, and now fixed by use of htonl().
- *
- * Revision 6.29 2001/05/23 21:03:35 vakatov
- * s_SelectStallsafe() -- fix for the interpretation of "default" R-on-W mode
- * (by A.Lavrentiev)
- *
- * Revision 6.28 2001/05/21 15:10:32 ivanov
- * Added (with Denis Vakatov) automatic read on write data from the socket
- * (stall protection).
- * Added functions SOCK_SetReadOnWriteAPI(), SOCK_SetReadOnWrite()
- * and internal function s_SelectStallsafe().
- *
- * Revision 6.27 2001/04/25 19:16:01 juran
- * Set non-blocking mode on Mac OS. (from pjc)
- *
- * Revision 6.26 2001/04/24 21:03:42 vakatov
- * s_NCBI_Recv() -- restore "r_status" to eIO_Success on success.
- * SOCK_Wait(READ) -- return eIO_Success if data pending in the buffer.
- * (w/A.Lavrentiev)
- *
- * Revision 6.25 2001/04/23 22:22:08 vakatov
- * SOCK_Read() -- special treatment for "buf" == NULL
- *
- * Revision 6.24 2001/04/04 14:58:59 vakatov
- * Cleaned up after R6.23 (and get rid of the C++ style comments)
- *
- * Revision 6.23 2001/04/03 20:30:15 juran
- * Changes to work with OT sockets.
- * Not all of pjc's changes are here -- I will test them shortly.
- *
- * Revision 6.22 2001/03/29 21:15:36 lavr
- * More accurate length calculation in 'SOCK_gethostbyaddr'
- *
- * Revision 6.21 2001/03/22 17:43:54 vakatov
- * Typo fixed in the SOCK_AllowSigPipeAPI() proto
- *
- * Revision 6.20 2001/03/22 17:40:36 vakatov
- * + SOCK_AllowSigPipeAPI()
- *
- * Revision 6.19 2001/03/06 23:54:20 lavr
- * Renamed: SOCK_gethostaddr -> SOCK_gethostbyname
- * Added: SOCK_gethostbyaddr
- *
- * Revision 6.18 2001/03/02 20:10:29 lavr
- * Typos fixed
- *
- * Revision 6.17 2001/02/28 00:55:38 lavr
- * SOCK_gethostaddr: InitAPI added, SOCK_gethostname used instead of
- * gethostname
- *
- * Revision 6.16 2001/01/26 23:50:32 vakatov
- * s_NCBI_Recv() -- added check for ENOTCONN to catch EOF (mostly for Mac)
- *
- * Revision 6.15 2001/01/25 17:10:41 lavr
- * The following policy applied: on either read or write,
- * n_read and n_written returned to indicate actual number of passed
- * bytes, regardless of error status. eIO_Success means that the
- * operation went through smoothly, while any other status has to
- * be analyzed. Anyway, the number of passed bytes prior the error
- * occurred is returned in n_read and n_written respectively.
- *
- * Revision 6.14 2001/01/23 23:19:34 lavr
- * Typo fixed in comment
- *
- * Revision 6.13 2000/12/28 21:26:27 lavr
- * Cosmetic fix to get rid of "converting -1 to unsigned" warning
- *
- * Revision 6.12 2000/12/26 21:40:03 lavr
- * SOCK_Read modified to handle properly the case of 0 byte reading
- *
- * Revision 6.11 2000/12/05 23:27:09 lavr
- * Added SOCK_gethostaddr
- *
- * Revision 6.10 2000/12/04 17:34:19 beloslyu
- * the order of include files is important, especially on other Unixes!
- * Look the man on inet_ntoa
- *
- * Revision 6.9 2000/11/22 19:29:16 vakatov
- * SOCK_Create() -- pre-set the sock handle to SOCK_INVALID before connect
- *
- * Revision 6.8 2000/11/15 18:51:21 vakatov
- * Add SOCK_Shutdown() and SOCK_Status(). Remove SOCK_Eof().
- * Add more checking and diagnostics.
- * [NOTE: not tested on Mac]
- *
- * Revision 6.7 2000/06/23 19:34:44 vakatov
- * Added means to log binary data
- *
- * Revision 6.6 2000/05/30 23:31:44 vakatov
- * SOCK_host2inaddr() renamed to SOCK_ntoa(), the home-made out-of-scratch
- * implementation to work properly with GCC on IRIX64 platforms
- *
- * Revision 6.5 2000/03/24 23:12:08 vakatov
- * Starting the development quasi-branch to implement CONN API.
- * All development is performed in the NCBI C++ tree only, while
- * the NCBI C tree still contains "frozen" (see the last revision) code.
- *
- * Revision 6.4 2000/02/23 22:34:35 vakatov
- * Can work both "standalone" and as a part of NCBI C++ or C toolkits
- *
- * Revision 6.3 1999/10/19 22:21:48 vakatov
- * Put the call to "gethostbyname()" into a CRITICAL_SECTION
- *
- * Revision 6.2 1999/10/19 16:16:01 vakatov
- * Try the NCBI C and C++ headers only if NCBI_OS_{UNIX, MSWIN, MAC} is
- * not #define'd
- *
- * Revision 6.1 1999/10/18 15:36:38 vakatov
- * Initial revision (derived from the former "ncbisock.[ch]")
- *
- * ===========================================================================
- */