Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/nsprpub/pr/src/md/windows/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 20 kB image not shown  

Quelle  w95sock.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/* Win95 Sockets module
 *
 */


#if defined(_WIN64)
#  include <winsock2.h>
#endif
#include "primpl.h"

#define READ_FD 1
#define WRITE_FD 2
#define CONNECT_FD 3

static PRInt32 socket_io_wait(PROsfd osfd, PRInt32 fd_type,
                              PRIntervalTime timeout);

/* --- SOCKET IO --------------------------------------------------------- */

static PRBool socketFixInet6RcvBuf = PR_FALSE;

void _PR_MD_InitSockets(void) {
  OSVERSIONINFO osvi;

  memset(&osvi, 0, sizeof(osvi));
  osvi.dwOSVersionInfoSize = sizeof(osvi);
  GetVersionEx(&osvi);

  if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) {
    /* if Windows XP (32-bit) */
    socketFixInet6RcvBuf = PR_TRUE;
  }
}

void _PR_MD_CleanupSockets(void) { socketFixInet6RcvBuf = PR_FALSE; }

PROsfd _PR_MD_SOCKET(int af, int type, int flags) {
  SOCKET sock;
  u_long one = 1;

  sock = socket(af, type, flags);

  if (sock == INVALID_SOCKET) {
    _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError());
    return (PROsfd)sock;
  }

  /*
  ** Make the socket Non-Blocking
  */

  if (ioctlsocket(sock, FIONBIO, &one) != 0) {
    PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError());
    closesocket(sock);
    return -1;
  }

  if (af == AF_INET6 && socketFixInet6RcvBuf) {
    int bufsize;
    int len = sizeof(bufsize);
    int rv;

    /* Windows XP 32-bit returns an error on getpeername() for AF_INET6
     * sockets if the receive buffer size is greater than 65535 before
     * the connection is initiated. The default receive buffer size may
     * be 128000 so fix it here to always be <= 65535. See bug 513659
     * and IBM DB2 support technote "Receive/Send IPv6 Socket Size
     * Problem in Windows XP SP2 & SP3".
     */

    rv = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, &len);
    if (rv == 0 && bufsize > 65535) {
      bufsize = 65535;
      setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, len);
    }
  }

  return (PROsfd)sock;
}

/*
** _MD_CloseSocket() -- Close a socket
**
*/

PRInt32 _MD_CloseSocket(PROsfd osfd) {
  PRInt32 rv;

  rv = closesocket((SOCKET)osfd);
  if (rv < 0) {
    _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError());
  }

  return rv;
}

PRInt32 _MD_SocketAvailable(PRFileDesc* fd) {
  PRInt32 result;

  if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError());
    return -1;
  }
  return result;
}

PROsfd _MD_Accept(PRFileDesc* fd, PRNetAddr* raddr, PRUint32* rlen,
                  PRIntervalTime timeout) {
  PROsfd osfd = fd->secret->md.osfd;
  SOCKET sock;
  PRInt32 rv, err;

  while ((sock = accept(osfd, (struct sockaddr*)raddr, rlen)) == -1) {
    err = WSAGetLastError();
    if ((err == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) {
      if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) {
        break;
      }
    } else {
      _PR_MD_MAP_ACCEPT_ERROR(err);
      break;
    }
  }
  return (sock);
/* end _MD_accept() */

PRInt32 _PR_MD_CONNECT(PRFileDesc* fd, const PRNetAddr* addr, PRUint32 addrlen,
                       PRIntervalTime timeout) {
  PROsfd osfd = fd->secret->md.osfd;
  PRInt32 rv;
  int err;

  if ((rv = connect(osfd, (struct sockaddr*)addr, addrlen)) == -1) {
    err = WSAGetLastError();
    if ((!fd->secret->nonblocking) && (err == WSAEWOULDBLOCK)) {
      rv = socket_io_wait(osfd, CONNECT_FD, timeout);
      if (rv < 0) {
        return (-1);
      } else {
        PR_ASSERT(rv > 0);
        /* it's connected */
        return (0);
      }
    }
    _PR_MD_MAP_CONNECT_ERROR(err);
  }
  return rv;
}

PRInt32 _PR_MD_BIND(PRFileDesc* fd, const PRNetAddr* addr, PRUint32 addrlen) {
  PRInt32 rv;

  rv =
      bind(fd->secret->md.osfd, (const struct sockaddr*)&(addr->inet), addrlen);

  if (rv == SOCKET_ERROR) {
    _PR_MD_MAP_BIND_ERROR(WSAGetLastError());
    return -1;
  }

  return 0;
}

PRInt32 _PR_MD_LISTEN(PRFileDesc* fd, PRIntn backlog) {
  PRInt32 rv;

  rv = listen(fd->secret->md.osfd, backlog);

  if (rv == SOCKET_ERROR) {
    _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError());
    return -1;
  }

  return 0;
}

PRInt32 _PR_MD_RECV(PRFileDesc* fd, void* buf, PRInt32 amount, PRIntn flags,
                    PRIntervalTime timeout) {
  PROsfd osfd = fd->secret->md.osfd;
  PRInt32 rv, err;
  int osflags;

  if (0 == flags) {
    osflags = 0;
  } else {
    PR_ASSERT(PR_MSG_PEEK == flags);
    osflags = MSG_PEEK;
  }
  while ((rv = recv(osfd, buf, amount, osflags)) == -1) {
    if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) &&
        (!fd->secret->nonblocking)) {
      rv = socket_io_wait(osfd, READ_FD, timeout);
      if (rv < 0) {
        return -1;
      }
    } else {
      _PR_MD_MAP_RECV_ERROR(err);
      break;
    }
  } /* end while() */
  return (rv);
}

PRInt32 _PR_MD_SEND(PRFileDesc* fd, const void* buf, PRInt32 amount,
                    PRIntn flags, PRIntervalTime timeout) {
  PROsfd osfd = fd->secret->md.osfd;
  PRInt32 rv, err;
  PRInt32 bytesSent = 0;

  while (bytesSent < amount) {
    while ((rv = send(osfd, buf, amount, 0)) == -1) {
      if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) &&
          (!fd->secret->nonblocking)) {
        rv = socket_io_wait(osfd, WRITE_FD, timeout);
        if (rv < 0) {
          return -1;
        }
      } else {
        _PR_MD_MAP_SEND_ERROR(err);
        return -1;
      }
    }
    bytesSent += rv;
    if (fd->secret->nonblocking) {
      break;
    }
    if (bytesSent < amount) {
      rv = socket_io_wait(osfd, WRITE_FD, timeout);
      if (rv < 0) {
        return -1;
      }
    }
  }
  return bytesSent;
}

PRInt32 _PR_MD_SENDTO(PRFileDesc* fd, const void* buf, PRInt32 amount,
                      PRIntn flags, const PRNetAddr* addr, PRUint32 addrlen,
                      PRIntervalTime timeout) {
  PROsfd osfd = fd->secret->md.osfd;
  PRInt32 rv, err;
  PRInt32 bytesSent = 0;

  do {
    while ((rv = sendto(osfd, buf, amount, 0, (struct sockaddr*)addr,
                        addrlen)) == -1) {
      if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) &&
          (!fd->secret->nonblocking)) {
        rv = socket_io_wait(osfd, WRITE_FD, timeout);
        if (rv < 0) {
          return -1;
        }
      } else {
        _PR_MD_MAP_SENDTO_ERROR(err);
        return -1;
      }
    }
    bytesSent += rv;
    if (fd->secret->nonblocking) {
      break;
    }
    if (bytesSent < amount) {
      rv = socket_io_wait(osfd, WRITE_FD, timeout);
      if (rv < 0) {
        return -1;
      }
    }
  } while (bytesSent < amount);
  return bytesSent;
}

#if defined(_WIN64)

static PRCallOnceType _pr_has_connectex_once;
typedef BOOL(PASCAL FAR* _pr_win_connectex_ptr)(
    _In_ SOCKET s, _In_reads_bytes_(namelen) const struct sockaddr FAR* name,
    _In_ int namelen, _In_reads_bytes_opt_(dwSendDataLength) PVOID lpSendBuffer,
    _In_ DWORD dwSendDataLength, _Out_ LPDWORD lpdwBytesSent,
    _Inout_ LPOVERLAPPED lpOverlapped);

#  ifndef WSAID_CONNECTEX
#    define WSAID_CONNECTEX                              \
      {                                                  \
        0x25a207b9, 0xddf3, 0x4660, {                    \
          0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e \
        }                                                \
      }
#  endif
#  ifndef SIO_GET_EXTENSION_FUNCTION_POINTER
#    define SIO_GET_EXTENSION_FUNCTION_POINTER 0xC8000006
#  endif
#  ifndef TCP_FASTOPEN
#    define TCP_FASTOPEN 15
#  endif

#  ifndef SO_UPDATE_CONNECT_CONTEXT
#    define SO_UPDATE_CONNECT_CONTEXT 0x7010
#  endif

static _pr_win_connectex_ptr _pr_win_connectex = NULL;

static PRStatus PR_CALLBACK _pr_set_connectex(void) {
  _pr_win_connectex = NULL;
  SOCKET sock;
  PRInt32 dwBytes;
  int rc;

  /* Dummy socket needed for WSAIoctl */
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock == INVALID_SOCKET) {
    return PR_SUCCESS;
  }

  GUID guid = WSAID_CONNECTEX;
  rc = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
                &_pr_win_connectex, sizeof(_pr_win_connectex), &dwBytes, NULL,
                NULL);
  if (rc != 0) {
    _pr_win_connectex = NULL;
    return PR_SUCCESS;
  }

  rc = closesocket(sock);
  return PR_SUCCESS;
}

PRInt32 _PR_MD_TCPSENDTO(PRFileDesc* fd, const void* buf, PRInt32 amount,
                         PRIntn flags, const PRNetAddr* addr, PRUint32 addrlen,
                         PRIntervalTime timeout) {
  if (!_fd_waiting_for_overlapped_done_lock) {
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
  }

  if (PR_CallOnce(&_pr_has_connectex_once, _pr_set_connectex) != PR_SUCCESS) {
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
  }

  if (_pr_win_connectex == NULL) {
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    return PR_FAILURE;
  }

  PROsfd osfd = fd->secret->md.osfd;
  PRInt32 rv, err;
  PRInt32 bytesSent = 0;
  DWORD rvSent;

  BOOL option = 1;
  rv = setsockopt((SOCKET)osfd, IPPROTO_TCP, TCP_FASTOPEN, (char*)&option,
                  sizeof(option));
  if (rv != 0) {
    err = WSAGetLastError();
    PR_LOG(_pr_io_lm, PR_LOG_MIN,
           ("_PR_MD_TCPSENDTO error set opt TCP_FASTOPEN failed %d\n", err));
    if (err == WSAENOPROTOOPT) {
      PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
    } else {
      _PR_MD_MAP_SETSOCKOPT_ERROR(err);
    }
    return -1;
  }

  /* ConnectEx requires the socket to be initially bound. We will use
   * INADDR_ANY. */

  PRNetAddr bindAddr;
  memset(&bindAddr, 0, sizeof(bindAddr));
  bindAddr.raw.family = addr->raw.family;

  rv = bind((SOCKET)osfd, (const struct sockaddr*)&(bindAddr.inet),
            PR_NETADDR_SIZE(&bindAddr));
  if (rv != 0) {
    err = WSAGetLastError();
    PR_LOG(_pr_io_lm, PR_LOG_MIN,
           ("_PR_MD_TCPSENDTO error bind failed %d\n", err));
    _PR_MD_MAP_SETSOCKOPT_ERROR(err);
    return -1;
  }

  PR_LOG(_pr_io_lm, PR_LOG_MIN,
         ("_PR_MD_TCPSENDTO calling _pr_win_connectex %d %p\n", amount,
          (char*)buf));

  rvSent = 0;
  memset(&fd->secret->ol, 0, sizeof(fd->secret->ol));
  /* ConnectEx return TRUE on a success and FALSE on an error. */
  if (_pr_win_connectex((SOCKET)osfd, (struct sockaddr*)addr, addrlen, buf,
                        amount, &rvSent, &fd->secret->ol) == TRUE) {
    /* When ConnectEx is used, all previously set socket options and
     * property are not enabled and to enable them
     * SO_UPDATE_CONNECT_CONTEXT option need to be set. */

    rv = setsockopt((SOCKET)osfd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL,
                    0);
    if (rv != 0) {
      err = WSAGetLastError();
      PR_LOG(_pr_io_lm, PR_LOG_MIN,
             ("_PR_MD_TCPSENDTO setting SO_UPDATE_CONNECT_CONTEXT failed %d\n",
              err));
      _PR_MD_MAP_SETSOCKOPT_ERROR(err);
      return -1;
    }
    /* We imitate Linux here. SendTo will return number of bytes send but
     * it can not return connection success at the same time, so we return
     * number of bytes send and "connection success" will be return on the
     * connectcontinue. */

    fd->secret->alreadyConnected = PR_TRUE;
    return rvSent;
  } else {
    err = WSAGetLastError();
    PR_LOG(_pr_io_lm, PR_LOG_MIN,
           ("_PR_MD_TCPSENDTO error _pr_win_connectex failed %d\n", err));
    if (err != ERROR_IO_PENDING) {
      _PR_MD_MAP_CONNECT_ERROR(err);
      return -1;
    } else if (fd->secret->nonblocking) {
      /* Remember that overlapped structure is set. We will need to get
       * the final result of ConnectEx call. */

      fd->secret->overlappedActive = PR_TRUE;

      /* ConnectEx will copy supplied data to a internal buffer and send
       * them during Fast Open or after connect. Therefore we can assumed
       * this data already send. */

      if (amount > 0) {
        return amount;
      }

      _PR_MD_MAP_CONNECT_ERROR(WSAEWOULDBLOCK);
      return -1;
    }
    // err is ERROR_IO_PENDING and socket is blocking, so query
    // GetOverlappedResult.
    err = ERROR_IO_INCOMPLETE;
    while (err == ERROR_IO_INCOMPLETE) {
      rv = socket_io_wait(osfd, WRITE_FD, timeout);
      if (rv < 0) {
        return -1;
      }
      rv = GetOverlappedResult((HANDLE)osfd, &fd->secret->ol, &rvSent, FALSE);
      if (rv == TRUE) {
        return rvSent;
      } else {
        err = WSAGetLastError();
        if (err != ERROR_IO_INCOMPLETE) {
          _PR_MD_MAP_CONNECT_ERROR(err);
          return -1;
        }
      }
    }
  }
  return -1;
}
#endif

PRInt32 _PR_MD_RECVFROM(PRFileDesc* fd, void* buf, PRInt32 amount, PRIntn flags,
                        PRNetAddr* addr, PRUint32* addrlen,
                        PRIntervalTime timeout) {
  PROsfd osfd = fd->secret->md.osfd;
  PRInt32 rv, err;

  while ((rv = recvfrom(osfd, buf, amount, 0, (struct sockaddr*)addr,
                        addrlen)) == -1) {
    if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) &&
        (!fd->secret->nonblocking)) {
      rv = socket_io_wait(osfd, READ_FD, timeout);
      if (rv < 0) {
        return -1;
      }
    } else {
      _PR_MD_MAP_RECVFROM_ERROR(err);
      break;
    }
  }
  return (rv);
}

PRInt32 _PR_MD_WRITEV(PRFileDesc* fd, const PRIOVec* iov, PRInt32 iov_size,
                      PRIntervalTime timeout) {
  int index;
  int sent = 0;
  int rv;

  for (index = 0; index < iov_size; index++) {
    rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout);
    if (rv > 0) {
      sent += rv;
    }
    if (rv != iov[index].iov_len) {
      if (rv < 0) {
        if (fd->secret->nonblocking &&
            (PR_GetError() == PR_WOULD_BLOCK_ERROR) && (sent > 0)) {
          return sent;
        } else {
          return -1;
        }
      }
      /* Only a nonblocking socket can have partial sends */
      PR_ASSERT(fd->secret->nonblocking);
      return sent;
    }
  }
  return sent;
}

PRInt32 _PR_MD_SHUTDOWN(PRFileDesc* fd, PRIntn how) {
  PRInt32 rv;

  rv = shutdown(fd->secret->md.osfd, how);
  if (rv < 0) {
    _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError());
  }
  return rv;
}

PRStatus _PR_MD_GETSOCKNAME(PRFileDesc* fd, PRNetAddr* addr, PRUint32* len) {
  PRInt32 rv;

  rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr*)addr, len);
  if (rv == 0) {
    return PR_SUCCESS;
  } else {
    _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError());
    return PR_FAILURE;
  }
}

PRStatus _PR_MD_GETPEERNAME(PRFileDesc* fd, PRNetAddr* addr, PRUint32* len) {
  PRInt32 rv;

  rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr*)addr, len);
  if (rv == 0) {
    return PR_SUCCESS;
  } else {
    _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError());
    return PR_FAILURE;
  }
}

PRStatus _PR_MD_GETSOCKOPT(PRFileDesc* fd, PRInt32 level, PRInt32 optname,
                           char* optval, PRInt32* optlen) {
  PRInt32 rv;

  rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
  if (rv == 0) {
    return PR_SUCCESS;
  } else {
    _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
    return PR_FAILURE;
  }
}

PRStatus _PR_MD_SETSOCKOPT(PRFileDesc* fd, PRInt32 level, PRInt32 optname,
                           const char* optval, PRInt32 optlen) {
  PRInt32 rv;

  rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen);
  if (rv == 0) {
    return PR_SUCCESS;
  } else {
    _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError());
    return PR_FAILURE;
  }
}

void _MD_MakeNonblock(PRFileDesc* f) { return/* do nothing */ }

/*
 * socket_io_wait --
 *
 * Wait for socket i/o, periodically checking for interrupt.
 *
 * This function returns 1 on success.  On failure, it returns
 * -1 and sets the error codes.  It never returns 0.
 */

#define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5

static PRInt32 socket_io_wait(PROsfd osfd, PRInt32 fd_type,
                              PRIntervalTime timeout) {
  PRInt32 rv = -1;
  struct timeval tv;
  PRThread* me = _PR_MD_CURRENT_THREAD();
  PRIntervalTime elapsed, remaining;
  PRBool wait_for_remaining;
  fd_set rd_wr, ex;
  int err, len;

  switch (timeout) {
    case PR_INTERVAL_NO_WAIT:
      PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
      break;
    case PR_INTERVAL_NO_TIMEOUT:
      /*
       * This is a special case of the 'default' case below.
       * Please see the comments there.
       */

      tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
      tv.tv_usec = 0;
      FD_ZERO(&rd_wr);
      FD_ZERO(&ex);
      do {
        FD_SET(osfd, &rd_wr);
        FD_SET(osfd, &ex);
        switch (fd_type) {
          case READ_FD:
            rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv);
            break;
          case WRITE_FD:
            rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv);
            break;
          case CONNECT_FD:
            rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv);
            break;
          default:
            PR_ASSERT(0);
            break;
        } /* end switch() */
        if (rv == -1) {
          _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
          break;
        }
        if (rv > 0 && fd_type == CONNECT_FD) {
          /*
           * Call Sleep(0) to work around a Winsock timing bug.
           */

          Sleep(0);
          if (FD_ISSET((SOCKET)osfd, &ex)) {
            len = sizeof(err);
            if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) ==
                SOCKET_ERROR) {
              _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
              return -1;
            }
            if (err != 0) {
              _PR_MD_MAP_CONNECT_ERROR(err);
            } else {
              PR_SetError(PR_UNKNOWN_ERROR, 0);
            }
            return -1;
          }
          if (FD_ISSET((SOCKET)osfd, &rd_wr)) {
            /* it's connected */
            return 1;
          }
          PR_ASSERT(0);
        }
        if (_PR_PENDING_INTERRUPT(me)) {
          me->flags &= ~_PR_INTERRUPT;
          PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
          rv = -1;
          break;
        }
      } while (rv == 0);
      break;
    default:
      remaining = timeout;
      FD_ZERO(&rd_wr);
      FD_ZERO(&ex);
      do {
        /*
         * We block in _MD_SELECT for at most
         * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
         * so that there is an upper limit on the delay
         * before the interrupt bit is checked.
         */

        wait_for_remaining = PR_TRUE;
        tv.tv_sec = PR_IntervalToSeconds(remaining);
        if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
          wait_for_remaining = PR_FALSE;
          tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
          tv.tv_usec = 0;
        } else {
          tv.tv_usec = PR_IntervalToMicroseconds(
              remaining - PR_SecondsToInterval(tv.tv_sec));
        }
        FD_SET(osfd, &rd_wr);
        FD_SET(osfd, &ex);
        switch (fd_type) {
          case READ_FD:
            rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv);
            break;
          case WRITE_FD:
            rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv);
            break;
          case CONNECT_FD:
            rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv);
            break;
          default:
            PR_ASSERT(0);
            break;
        } /* end switch() */
        if (rv == -1) {
          _PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
          break;
        }
        if (rv > 0 && fd_type == CONNECT_FD) {
          /*
           * Call Sleep(0) to work around a Winsock timing bug.
           */

          Sleep(0);
          if (FD_ISSET((SOCKET)osfd, &ex)) {
            len = sizeof(err);
            if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) ==
                SOCKET_ERROR) {
              _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError());
              return -1;
            }
            if (err != 0) {
              _PR_MD_MAP_CONNECT_ERROR(err);
            } else {
              PR_SetError(PR_UNKNOWN_ERROR, 0);
            }
            return -1;
          }
          if (FD_ISSET((SOCKET)osfd, &rd_wr)) {
            /* it's connected */
            return 1;
          }
          PR_ASSERT(0);
        }
        if (_PR_PENDING_INTERRUPT(me)) {
          me->flags &= ~_PR_INTERRUPT;
          PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
          rv = -1;
          break;
        }
        /*
         * We loop again if _MD_SELECT timed out and the
         * timeout deadline has not passed yet.
         */

        if (rv == 0) {
          if (wait_for_remaining) {
            elapsed = remaining;
          } else {
            elapsed = PR_SecondsToInterval(tv.tv_sec) +
                      PR_MicrosecondsToInterval(tv.tv_usec);
          }
          if (elapsed >= remaining) {
            PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
            rv = -1;
            break;
          } else {
            remaining = remaining - elapsed;
          }
        }
      } while (rv == 0);
      break;
  }
  return (rv);
/* end socket_io_wait() */

Messung V0.5
C=96 H=91 G=93

¤ Dauer der Verarbeitung: 0.32 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.