Upgrade libuv to 0bf38570e8c7837bd830388f7b57f138aebb3395
authorRyan Dahl <ry@tinyclouds.org>
Wed, 6 Jul 2011 19:13:45 +0000 (12:13 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Wed, 6 Jul 2011 19:13:45 +0000 (12:13 -0700)
12 files changed:
deps/uv/c-ares/ares.h
deps/uv/c-ares/ares_setup.h
deps/uv/c-ares/config-win32.h
deps/uv/config-mingw.mk
deps/uv/config-unix.mk
deps/uv/test/echo-server.c
deps/uv/test/test-list.h
deps/uv/test/test-ping-pong.c
deps/uv/uv-unix.c
deps/uv/uv-unix.h
deps/uv/uv-win.c
deps/uv/uv.h

index 45ca564..a8d3815 100644 (file)
@@ -96,9 +96,9 @@ typedef int ares_socklen_t;
 #  include <sys/socket.h>
 #  include <tcp.h>
 #elif defined(WIN32)
-#  include <windows.h>
 #  include <winsock2.h>
 #  include <ws2tcpip.h>
+#  include <windows.h>
 #else
 #  include <sys/socket.h>
 #  include <netinet/in.h>
index 8dbb933..b405aae 100644 (file)
  */
 
 #ifdef HAVE_WINDOWS_H
-#  include <windows.h>
 #  ifdef HAVE_WINSOCK2_H
 #    include <winsock2.h>
 #    ifdef HAVE_WS2TCPIP_H
 #      include <winsock.h>
 #    endif
 #  endif
+#  include <windows.h>
 #endif
 
 /*
index 898ba90..13c5de5 100644 (file)
@@ -51,9 +51,6 @@
 #define HAVE_UNISTD_H 1
 #endif
 
-/* Define if you have the <windows.h> header file.  */
-#define HAVE_WINDOWS_H 1
-
 /* Define if you have the <winsock.h> header file.  */
 #define HAVE_WINSOCK_H 1
 
index f3804d8..f1f1ce9 100644 (file)
@@ -24,7 +24,7 @@ CC = $(PREFIX)gcc
 AR = $(PREFIX)ar
 E=.exe
 
-CFLAGS=-g --std=gnu89 -Wno-variadic-macros -D_WIN32_WINNT=0x0501 -Ic-ares/config_win32
+CFLAGS=-g --std=gnu89 -D_WIN32_WINNT=0x0501 -Ic-ares/config_win32
 LINKFLAGS=-lm
 
 CARES_OBJS += c-ares/windows_port.o
index 0946dce..4e503b3 100644 (file)
@@ -21,7 +21,7 @@
 CC = $(PREFIX)gcc
 AR = $(PREFIX)ar
 E=
-CFLAGS=--std=gnu89 -Wno-variadic-macros -g
+CFLAGS=--std=gnu89 -g
 LINKFLAGS=-lm
 
 CPPFLAGS += -D_LARGEFILE_SOURCE
index 1243a9a..ab5491c 100644 (file)
@@ -34,6 +34,9 @@ typedef struct {
 static int server_closed;
 static uv_tcp_t server;
 
+static int server6_closed;
+static uv_tcp_t server6;
+
 
 static void after_write(uv_req_t* req, int status);
 static void after_read(uv_stream_t*, ssize_t nread, uv_buf_t buf);
@@ -97,6 +100,8 @@ static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
       if (buf.base[i] == 'Q') {
         uv_close((uv_handle_t*)&server, on_server_close);
         server_closed = 1;
+        uv_close((uv_handle_t*)&server6, on_server_close);
+        server6_closed = 1;
       }
     }
   }
@@ -129,6 +134,9 @@ static void on_connection(uv_handle_t* server, int status) {
   uv_tcp_t* handle;
   int r;
 
+  if (status != 0) {
+    fprintf(stderr, "Connect error %d\n", uv_last_error());
+  }
   ASSERT(status == 0);
 
   handle = (uv_tcp_t*) malloc(sizeof *handle);
@@ -136,6 +144,9 @@ static void on_connection(uv_handle_t* server, int status) {
 
   uv_tcp_init(handle);
 
+  /* associate server with stream */
+  handle->data = server;
+
   r = uv_accept(server, (uv_stream_t*)handle);
   ASSERT(r == 0);
 
@@ -145,12 +156,13 @@ static void on_connection(uv_handle_t* server, int status) {
 
 
 static void on_server_close(uv_handle_t* handle) {
-  ASSERT(handle == (uv_handle_t*)&server);
+  ASSERT(handle == (uv_handle_t*)&server || handle == (uv_handle_t*)&server6);
 }
 
 
 static int echo_start(int port) {
   struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
+  struct sockaddr_in6 addr6 = uv_ip6_addr("::1", port);
   int r;
 
   r = uv_tcp_init(&server);
@@ -174,6 +186,27 @@ static int echo_start(int port) {
     return 1;
   }
 
+  r = uv_tcp_init(&server6);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Socket creation error\n");
+    return 1;
+  }
+
+  r = uv_tcp_bind6(&server6, addr6);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Bind6 error\n");
+    return 1;
+  }
+
+  r = uv_tcp_listen(&server6, 128, on_connection);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Listen error\n");
+    return 1;
+  }
+
   return 0;
 }
 
index ddedfa1..190574a 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 TEST_DECLARE   (ping_pong)
+TEST_DECLARE   (ping_pong_v6)
 TEST_DECLARE   (delayed_accept)
 TEST_DECLARE   (tcp_writealot)
 TEST_DECLARE   (bind_error_addrinuse)
@@ -60,6 +61,9 @@ TASK_LIST_START
   TEST_ENTRY  (ping_pong)
   TEST_HELPER (ping_pong, echo_server)
 
+  TEST_ENTRY  (ping_pong_v6)
+  TEST_HELPER (ping_pong_v6, echo_server)
+
   TEST_ENTRY  (delayed_accept)
 
   TEST_ENTRY  (tcp_writealot)
index 1858adc..14208e7 100644 (file)
@@ -175,3 +175,40 @@ TEST_IMPL(ping_pong) {
 
   return 0;
 }
+
+
+/* same ping-pong test, but using IPv6 connection */
+static void pinger_v6_new() {
+  int r;
+  struct sockaddr_in6 server_addr = uv_ip6_addr("::1", TEST_PORT);
+  pinger_t *pinger;
+
+  pinger = (pinger_t*)malloc(sizeof(*pinger));
+  pinger->state = 0;
+  pinger->pongs = 0;
+
+  /* Try to connec to the server and do NUM_PINGS ping-pongs. */
+  r = uv_tcp_init(&pinger->tcp);
+  pinger->tcp.data = pinger;
+  ASSERT(!r);
+
+  /* We are never doing multiple reads/connects at a time anyway. */
+  /* so these handles can be pre-initialized. */
+  uv_req_init(&pinger->connect_req, (uv_handle_t*)(&pinger->tcp),
+      pinger_on_connect);
+
+  r = uv_tcp_connect6(&pinger->connect_req, server_addr);
+  ASSERT(!r);
+}
+
+
+TEST_IMPL(ping_pong_v6) {
+  uv_init();
+
+  pinger_v6_new();
+  uv_run();
+
+  ASSERT(completed_pingers == 1);
+
+  return 0;
+}
index db3ce11..c9b6628 100644 (file)
@@ -659,7 +659,9 @@ static uv_req_t* uv__write(uv_tcp_t* tcp) {
 
           /* Pop the req off tcp->write_queue. */
           ngx_queue_remove(&req->queue);
-          free(req->bufs); /* FIXME: we should not be allocing for each read */
+          if (req->bufs != req->bufsml) {
+            free(req->bufs);
+          }
           req->bufs = NULL;
 
           /* Add it to the write_completed_queue where it will have its
@@ -943,6 +945,13 @@ int uv_tcp_connect(uv_req_t* req, struct sockaddr_in addr) {
 }
 
 
+/* TODO: Implement IPv6 Connect for UNIX */
+int uv_tcp_connect6(uv_req_t* req, struct sockaddr_in6 addr) {
+  uv_err_new_artificial((uv_handle_t*)req->handle, UV_EAFNOSUPPORT);
+  return -1;
+}
+
+
 static size_t uv__buf_count(uv_buf_t bufs[], int bufcnt) {
   size_t total = 0;
   int i;
@@ -966,11 +975,19 @@ int uv_write(uv_req_t* req, uv_buf_t bufs[], int bufcnt) {
   ngx_queue_init(&req->queue);
   req->type = UV_WRITE;
 
-  /* TODO: Don't malloc for each write... */
-  req->bufs = malloc(sizeof(uv_buf_t) * bufcnt);
+
+  if (bufcnt < UV_REQ_BUFSML_SIZE) {
+    req->bufs = req->bufsml;
+  }
+  else {
+    req->bufs = malloc(sizeof(uv_buf_t) * bufcnt);
+  }
+
   memcpy(req->bufs, bufs, bufcnt * sizeof(uv_buf_t));
   req->bufcnt = bufcnt;
 
+  // fprintf(stderr, "cnt: %d bufs: %p bufsml: %p\n", bufcnt, req->bufs, req->bufsml);
+
   req->write_index = 0;
   tcp->write_queue_size += uv__buf_count(bufs, bufcnt);
 
index 576598a..f6c5134 100644 (file)
@@ -39,13 +39,15 @@ typedef struct {
   size_t len;
 } uv_buf_t;
 
+#define UV_REQ_BUFSML_SIZE (4)
 
 #define UV_REQ_PRIVATE_FIELDS \
   int write_index; \
   ev_timer timer; \
   ngx_queue_t queue; \
   uv_buf_t* bufs; \
-  int bufcnt;
+  int bufcnt; \
+  uv_buf_t bufsml[UV_REQ_BUFSML_SIZE];
 
 
 /* TODO: union or classes please! */
index 6171979..e6b8492 100644 (file)
@@ -139,6 +139,12 @@ static LPFN_ACCEPTEX                pAcceptEx;
 static LPFN_GETACCEPTEXSOCKADDRS    pGetAcceptExSockAddrs;
 static LPFN_DISCONNECTEX            pDisconnectEx;
 static LPFN_TRANSMITFILE            pTransmitFile;
+/* need IPv6 versions of winsock extension functions */
+static LPFN_CONNECTEX               pConnectEx6;
+static LPFN_ACCEPTEX                pAcceptEx6;
+static LPFN_GETACCEPTEXSOCKADDRS    pGetAcceptExSockAddrs6;
+static LPFN_DISCONNECTEX            pDisconnectEx6;
+static LPFN_TRANSMITFILE            pTransmitFile6;
 
 
 /*
@@ -157,6 +163,7 @@ static LPFN_TRANSMITFILE            pTransmitFile;
 #define UV_HANDLE_SHUT             0x0200
 #define UV_HANDLE_ENDGAME_QUEUED   0x0400
 #define UV_HANDLE_BIND_ERROR       0x1000
+#define UV_HANDLE_IPV6             0x2000
 
 /*
  * Private uv_req flags.
@@ -208,6 +215,7 @@ static int uv_refs_ = 0;
 
 /* Ip address used to bind to any port at any interface */
 static struct sockaddr_in uv_addr_ip4_any_;
+static struct sockaddr_in6 uv_addr_ip6_any_;
 
 
 /* A zero-size buffer for use by uv_read */
@@ -417,6 +425,7 @@ void uv_init() {
   int errorno;
   LARGE_INTEGER timer_frequency;
   SOCKET dummy;
+  SOCKET dummy6;
 
   /* Initialize winsock */
   errorno = WSAStartup(MAKEWORD(2, 2), &wsa_data);
@@ -426,6 +435,7 @@ void uv_init() {
 
   /* Set implicit binding address used by connectEx */
   uv_addr_ip4_any_ = uv_ip4_addr("0.0.0.0", 0);
+  uv_addr_ip6_any_ = uv_ip6_addr("::1", 0);
 
   /* Retrieve the needed winsock extension function pointers. */
   dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
@@ -453,6 +463,33 @@ void uv_init() {
     uv_fatal_error(WSAGetLastError(), "closesocket");
   }
 
+/* need IPv6 versions of winsock extension functions */
+  dummy6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
+  if (dummy == INVALID_SOCKET) {
+    uv_fatal_error(WSAGetLastError(), "socket");
+  }
+
+  uv_get_extension_function(dummy6,
+                            wsaid_connectex,
+                            (void**)&pConnectEx6);
+  uv_get_extension_function(dummy6,
+                            wsaid_acceptex,
+                            (void**)&pAcceptEx6);
+  uv_get_extension_function(dummy6,
+                            wsaid_getacceptexsockaddrs,
+                            (void**)&pGetAcceptExSockAddrs6);
+  uv_get_extension_function(dummy6,
+                            wsaid_disconnectex,
+                            (void**)&pDisconnectEx6);
+  uv_get_extension_function(dummy6,
+                            wsaid_transmitfile,
+                            (void**)&pTransmitFile6);
+
+  if (closesocket(dummy6) == SOCKET_ERROR) {
+    uv_fatal_error(WSAGetLastError(), "closesocket");
+  }
+
+
   /* Create an I/O completion port */
   uv_iocp_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
   if (uv_iocp_ == NULL) {
@@ -815,7 +852,7 @@ int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
     uv_set_sys_error(WSAEFAULT);
     return -1;
   }
-
+  handle->flags |= UV_HANDLE_IPV6;
   return uv__bind(handle, AF_INET6, (struct sockaddr*)&addr, sizeof(struct sockaddr_in6));
 }
 
@@ -825,6 +862,8 @@ static void uv_queue_accept(uv_tcp_t* handle) {
   BOOL success;
   DWORD bytes;
   SOCKET accept_socket;
+  short family;
+  LPFN_ACCEPTEX pAcceptExFamily;
 
   assert(handle->flags & UV_HANDLE_LISTENING);
   assert(handle->accept_socket == INVALID_SOCKET);
@@ -835,8 +874,17 @@ static void uv_queue_accept(uv_tcp_t* handle) {
   req->type = UV_ACCEPT;
   req->flags |= UV_REQ_PENDING;
 
+  /* choose family and extension function */
+  if ((handle->flags & UV_HANDLE_IPV6) != 0) {
+    family = AF_INET6;
+    pAcceptExFamily = pAcceptEx6;
+  } else {
+    family = AF_INET;
+    pAcceptExFamily = pAcceptEx;
+  }
+
   /* Open a socket for the accepted connection. */
-  accept_socket = socket(AF_INET, SOCK_STREAM, 0);
+  accept_socket = socket(family, SOCK_STREAM, 0);
   if (accept_socket == INVALID_SOCKET) {
     req->error = uv_new_sys_error(WSAGetLastError());
     uv_insert_pending_req(req);
@@ -846,14 +894,14 @@ static void uv_queue_accept(uv_tcp_t* handle) {
   /* Prepare the overlapped structure. */
   memset(&(req->overlapped), 0, sizeof(req->overlapped));
 
-  success = pAcceptEx(handle->socket,
-                      accept_socket,
-                      (void*)&handle->accept_buffer,
-                      0,
-                      sizeof(struct sockaddr_storage),
-                      sizeof(struct sockaddr_storage),
-                      &bytes,
-                      &req->overlapped);
+  success = pAcceptExFamily(handle->socket,
+                          accept_socket,
+                          (void*)&handle->accept_buffer,
+                          0,
+                          sizeof(struct sockaddr_storage),
+                          sizeof(struct sockaddr_storage),
+                          &bytes,
+                          &req->overlapped);
 
   if (!success && WSAGetLastError() != ERROR_IO_PENDING) {
     /* Make this req pending reporting an error. */
@@ -1045,6 +1093,51 @@ int uv_tcp_connect(uv_req_t* req, struct sockaddr_in addr) {
 }
 
 
+int uv_tcp_connect6(uv_req_t* req, struct sockaddr_in6 addr) {
+  int addrsize = sizeof(struct sockaddr_in6);
+  BOOL success;
+  DWORD bytes;
+  uv_tcp_t* handle = (uv_tcp_t*)req->handle;
+
+  assert(!(req->flags & UV_REQ_PENDING));
+
+  if (handle->flags & UV_HANDLE_BIND_ERROR) {
+    uv_last_error_ = handle->error;
+    return -1;
+  }
+
+  if (addr.sin6_family != AF_INET6) {
+    uv_set_sys_error(WSAEFAULT);
+    return -1;
+  }
+
+  if (!(handle->flags & UV_HANDLE_BOUND) &&
+      uv_tcp_bind6(handle, uv_addr_ip6_any_) < 0)
+    return -1;
+
+  memset(&req->overlapped, 0, sizeof(req->overlapped));
+  req->type = UV_CONNECT;
+
+  success = pConnectEx6(handle->socket,
+                       (struct sockaddr*)&addr,
+                       addrsize,
+                       NULL,
+                       0,
+                       &bytes,
+                       &req->overlapped);
+
+  if (!success && WSAGetLastError() != ERROR_IO_PENDING) {
+    uv_set_sys_error(WSAGetLastError());
+    return -1;
+  }
+
+  req->flags |= UV_REQ_PENDING;
+  handle->reqs_pending++;
+
+  return 0;
+}
+
+
 static size_t uv_count_bufs(uv_buf_t bufs[], int count) {
   size_t bytes = 0;
   int i;
index e7df5b6..bd84c51 100644 (file)
@@ -282,6 +282,7 @@ int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in);
 int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6);
 
 int uv_tcp_connect(uv_req_t* req, struct sockaddr_in);
+int uv_tcp_connect6(uv_req_t* req, struct sockaddr_in6);
 
 int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb);