Commit cd3467bb authored by Nick Mathewson's avatar Nick Mathewson 🦀
Browse files

Attempt to make sockets code work right on windows.


svn:r398
parent 88edae94
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#include "orconfig.h"
#include "fakepoll.h"

#ifdef USE_FAKE_POLL
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
@@ -30,6 +31,9 @@ poll(struct pollfd *ufds, unsigned int nfds, int timeout)
{
	unsigned int idx, maxfd, fd;
	int r;
#ifdef MS_WINDOWS
        int any_fds_set = 0;
#endif
	fd_set readfds, writefds, exceptfds;
#ifdef USING_FAKE_TIMEVAL
#undef timeval
@@ -46,15 +50,26 @@ poll(struct pollfd *ufds, unsigned int nfds, int timeout)
	maxfd = -1;
	for (idx = 0; idx < nfds; ++idx) {
		fd = ufds[idx].fd;
		if (fd > maxfd && ufds[idx].events)
                if (ufds[idx].events) {
                        if (fd > maxfd) 
                                maxfd = fd;
		if (ufds[idx].events & (POLLIN))
#ifdef MS_WINDOWS
                        any_fds_set = 1;
#endif
                }
		if (ufds[idx].events & POLLIN)
			FD_SET(fd, &readfds);
		if (ufds[idx].events & POLLOUT)
			FD_SET(fd, &writefds);
		if (ufds[idx].events & (POLLERR))
		if (ufds[idx].events & POLLERR)
			FD_SET(fd, &exceptfds);
	}
#ifdef MS_WINDOWS
        if (!any_fds_set) {
                usleep(timeout);
                return 0;
        }
#endif
	r = select(maxfd+1, &readfds, &writefds, &exceptfds, 
		   timeout == -1 ? NULL : &_timeout);
	if (r <= 0)
+21 −8
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

#include "../or/or.h"

#ifdef _MSC_VER
#ifdef MS_WINDOWS
#include <io.h>
#include <limits.h>
#include <process.h>
@@ -90,7 +90,7 @@ void tv_addms(struct timeval *a, long ms) {

void set_socket_nonblocking(int socket)
{
#ifdef _MSC_VER
#ifdef MS_WINDOWS
	/* Yes means no and no means yes.  Do you not want to be nonblocking? */
	int nonblocking = 0;
	ioctlsocket(socket, FIONBIO, (unsigned long*) &nonblocking);
@@ -101,7 +101,7 @@ void set_socket_nonblocking(int socket)

int spawn_func(int (*func)(void *), void *data)
{
#ifdef _MSC_VER
#ifdef MS_WINDOWS
  int rv;
  rv = _beginthread(func, 0, data);
  if (rv == (unsigned long) -1)
@@ -125,7 +125,7 @@ int spawn_func(int (*func)(void *), void *data)

void spawn_exit()
{
#ifdef _MSC_VER
#ifdef MS_WINDOWS
  _endthread();
#else
  exit(0);
@@ -137,7 +137,7 @@ void spawn_exit()
int
tor_socketpair(int family, int type, int protocol, int fd[2])
{
#ifdef HAVE_SOCKETPAIR_XXX
#ifdef HAVE_SOCKETPAIR_XXXX
    /* For testing purposes, we never fall back to real socketpairs. */
    return socketpair(family, type, protocol, fd);
#else
@@ -153,7 +153,7 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
        || family != AF_UNIX
#endif
        ) {
#ifdef _MSC_VER
#ifdef MS_WINDOWS
        errno = WSAEAFNOSUPPORT;
#else
        errno = EAFNOSUPPORT;
@@ -213,7 +213,7 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
    return 0;

  abort_tidy_up_and_fail:
#ifdef _MSC_VER
#ifdef MS_WINDOWS
  errno = WSAECONNABORTED;
#else
  errno = ECONNABORTED; /* I hope this is portable and appropriate.  */
@@ -232,3 +232,16 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
    }
#endif
}

#ifdef MS_WINDOWS
int correct_socket_errno(int s)
{
  int r, optval, optvallen=sizeof(optval);
  assert(errno == WSAEWOULDBLOCK);
  if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen))
    return errno;
  if (optval)
    return optval;
  return WSAEWOULDBLOCK;
}
#endif
+27 −1
Original line number Diff line number Diff line
@@ -13,6 +13,12 @@
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#if _MSC_VER > 1300
#include <winsock2.h>
#include <ws2tcpip.h>
#elif defined(_MSC_VER)
#include <winsock.h>
#endif
#ifndef HAVE_GETTIMEOFDAY
#ifdef HAVE_FTIME
#define USING_FAKE_TIMEVAL
@@ -23,7 +29,7 @@
#endif
#endif

#ifdef _MSC_VER
#ifdef MS_WINDOWS
/* Windows names string functions funnily. */
#define strncasecmp strnicmp
#define strcasecmp stricmp
@@ -55,4 +61,24 @@ void spawn_exit();

int tor_socketpair(int family, int type, int protocol, int fd[2]);

/* For stupid historical reasons, windows sockets have an independent set of 
 * errnos which they use as the fancy strikes them.
 */
#ifdef MS_WINDOWS
#define ERRNO_EAGAIN(e)           ((e) == EAGAIN || \
                                   (e) == WSAEWOULDBLOCK || \
                                   (e) == EWOULDBLOCK)
#define ERRNO_EINPROGRESS(e)      ((e) == EINPROGRESS || \
                                   (e) == WSAEINPROGRESS)
#define ERRNO_CONN_EINPROGRESS(e) ((e) == EINPROGRESS || \
                                   (e) == WSAEINPROGRESS || (e) == WSAEINVAL)
int correct_socket_errno(int s);
#else
#define ERRNO_EAGAIN(e)           ((e) == EAGAIN)
#define ERRNO_EINPROGRESS(e)      ((e) == EINPROGRESS)
#define ERRNO_CONN_EINPROGRESS(e) ((e) == EINPROGRESS)
#define correct_socket_errno(s)   (errno)
#endif


#endif
+20 −2
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@ void buf_free(char *buf) {
int read_to_buf(int s, int at_most, char **buf, int *buflen, int *buf_datalen, int *reached_eof) {

  int read_result;
#ifdef MS_WINDOWS
  int e;
#endif

  assert(buf && *buf && buflen && buf_datalen && reached_eof && (s>=0));

@@ -62,9 +65,15 @@ int read_to_buf(int s, int at_most, char **buf, int *buflen, int *buf_datalen, i
//  log_fn(LOG_DEBUG,"reading at most %d bytes.",at_most);
  read_result = read(s, *buf+*buf_datalen, at_most);
  if (read_result < 0) {
    if(errno!=EAGAIN) { /* it's a real error */
    if(!ERRNO_EAGAIN(errno)) { /* it's a real error */
      return -1;
    }
#ifdef MS_WINDOWS
    e = correct_socket_errno(s);
    if(!ERRNO_EAGAIN(errno)) { /* no, it *is* a real error! */
      return -1;
    }
#endif
    return 0;
  } else if (read_result == 0) {
    log_fn(LOG_DEBUG,"Encountered eof");
@@ -84,6 +93,9 @@ int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datale
   * return -1 or how many bytes remain to be flushed */

  int write_result;
#ifdef MS_WINDOWS
  int e;
#endif

  assert(buf && *buf && buflen && buf_flushlen && buf_datalen && (s>=0) && (*buf_flushlen <= *buf_datalen));

@@ -94,9 +106,15 @@ int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datale

  write_result = write(s, *buf, *buf_flushlen);
  if (write_result < 0) {
    if(errno!=EAGAIN) { /* it's a real error */
    if(!ERRNO_EAGAIN(errno)) { /* it's a real error */
      return -1;
    }
#ifdef MS_WINDOWS
    e = correct_socket_errno(s);
    if(!ERRNO_EAGAIN(errno)) { /* no, it *is* a real error! */
      return -1;
    }
#endif
    log_fn(LOG_DEBUG,"write() would block, returning.");
    return 0;
  } else {
+11 −1
Original line number Diff line number Diff line
@@ -188,11 +188,21 @@ int connection_handle_listener_read(connection_t *conn, int new_type, int new_st
  connection_t *newconn;
  struct sockaddr_in remote; /* information about the remote peer when connecting to other routers */
  int remotelen = sizeof(struct sockaddr_in); /* length of the remote address */
#ifdef MS_WINDOWS
  int e;
#endif

  news = accept(conn->s,(struct sockaddr *)&remote,&remotelen);
  if (news == -1) { /* accept() error */
    if(errno==EAGAIN)
    if(ERRNO_EAGAIN(errno)) {
#ifdef MS_WINDOWS
      e = correct_socket_errno(conn->s);
      if (ERRNO_EAGAIN(e))
        return 0;
#else
      return 0; /* he hung up before we could accept(). that's fine. */
#endif
    }
    /* else there was a real error. */
    log_fn(LOG_ERR,"accept() failed. Closing.");
    return -1;
Loading