ipv6 node
authorHenry Rawas <henryr@schakra.com>
Wed, 6 Jul 2011 20:34:04 +0000 (13:34 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Thu, 7 Jul 2011 22:51:55 +0000 (15:51 -0700)
lib/net_uv.js
src/tcp_wrap.cc
test/simple/test-net-pingpong.js

index d1f418c..039ff70 100644 (file)
@@ -321,7 +321,7 @@ function afterWrite(status, handle, req, buffer) {
 }
 
 
-function connectip(self, port, ip) {
+function connectip(self, port, ip, addressType) {
   self.remoteAddress = ip;
   self.remotePort = port;
 
@@ -330,7 +330,11 @@ function connectip(self, port, ip) {
 
   assert.ok(self._connecting);
 
-  var connectReq = self._handle.connect(ip, port);
+  if (addressType == 6) {
+    var connectReq = self._handle.connect6(ip, port);
+  } else {
+    var connectReq = self._handle.connect(ip, port);
+  }
 
   if (connectReq) {
     connectReq.oncomplete = afterConnect;
@@ -370,16 +374,12 @@ Socket.prototype.connect = function(port /* [host], [cb] */) {
       } else {
         timers.active(self);
 
-        if (addressType != 4) {
-          throw new Error("ipv6 addresses not yet supported by libuv");
-        }
-
-        connectip(self, port, ip || '127.0.0.1');
+        connectip(self, port, ip || '127.0.0.1', ip ? addressType : 4);
       }
     });
   } else {
     debug("connect: missing host");
-    connectip(self, port, '127.0.0.1');
+    connectip(self, port, '127.0.0.1', 4);
   }
 };
 
@@ -462,12 +462,16 @@ exports.Server = Server;
 function toPort(x) { return (x = Number(x)) >= 0 ? x : false; }
 
 
-function listenip(self, ip, port) {
+function listenip(self, ip, port, addressType) {
   var r = 0;
 
   if (ip && port) {
     debug("bind to " + ip);
-    r = self._handle.bind(ip, port);
+    if (addressType == 6) {
+      r = self._handle.bind6(ip, port);
+    } else {
+      r = self._handle.bind(ip, port);
+    }
   }
 
   if (r) {
@@ -498,7 +502,7 @@ Server.prototype.listen = function() {
   } else if (typeof arguments[1] == 'undefined' ||
              typeof arguments[1] == 'function') {
     // The first argument is the port, no IP given.
-    listenip(self, '0.0.0.0', port);
+    listenip(self, '0.0.0.0', port, 4);
 
   } else {
     // The first argument is the port, the second an IP
@@ -506,10 +510,7 @@ Server.prototype.listen = function() {
       if (err) {
         self.emit('error', err);
       } else {
-        if (addressType != 4) {
-          throw new Error("ipv6 addresses not yet supported by libuv");
-        }
-        listenip(self, ip || '0.0.0.0', port);
+        listenip(self, ip || '0.0.0.0', port, ip ? addressType : 4);
       }
     });
   }
index 2258e53..125b880 100644 (file)
@@ -99,6 +99,8 @@ class TCPWrap {
     NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
     NODE_SET_PROTOTYPE_METHOD(t, "shutdown", Shutdown);
     NODE_SET_PROTOTYPE_METHOD(t, "close", Close);
+    NODE_SET_PROTOTYPE_METHOD(t, "bind6", Bind6);
+    NODE_SET_PROTOTYPE_METHOD(t, "connect6", Connect6);
 
     constructor = Persistent<Function>::New(t->GetFunction());
 
@@ -168,6 +170,23 @@ class TCPWrap {
     return scope.Close(Integer::New(r));
   }
 
+  static Handle<Value> Bind6(const Arguments& args) {
+    HandleScope scope;
+
+    UNWRAP
+
+    String::AsciiValue ip6_address(args[0]->ToString());
+    int port = args[1]->Int32Value();
+
+    struct sockaddr_in6 address = uv_ip6_addr(*ip6_address, port);
+    int r = uv_tcp_bind6(&wrap->handle_, address);
+
+    // Error starting the tcp.
+    if (r) SetErrno(uv_last_error().code);
+
+    return scope.Close(Integer::New(r));
+  }
+
   static Handle<Value> Listen(const Arguments& args) {
     HandleScope scope;
 
@@ -462,6 +481,33 @@ class TCPWrap {
     }
   }
 
+  static Handle<Value> Connect6(const Arguments& args) {
+    HandleScope scope;
+
+    UNWRAP
+
+    String::AsciiValue ip_address(args[0]->ToString());
+    int port = args[1]->Int32Value();
+
+    struct sockaddr_in6 address = uv_ip6_addr(*ip_address, port);
+
+    // I hate when people program C++ like it was C, and yet I do it too.
+    // I'm too lazy to come up with the perfect class hierarchy here. Let's
+    // just do some type munging.
+    ReqWrap* req_wrap = new ReqWrap((uv_handle_t*) &wrap->handle_,
+                                    (void*)AfterConnect);
+
+    int r = uv_tcp_connect6(&req_wrap->req_, address);
+
+    if (r) {
+      SetErrno(uv_last_error().code);
+      delete req_wrap;
+      return scope.Close(v8::Null());
+    } else {
+      return scope.Close(req_wrap->object_);
+    }
+  }
+
   static void AfterShutdown(uv_req_t* req, int status) {
     ReqWrap* req_wrap = (ReqWrap*) req->data;
     TCPWrap* wrap = (TCPWrap*) req->handle->data;
index 6db4861..98136df 100644 (file)
@@ -131,17 +131,17 @@ function pingPongTest(port, host) {
 /* All are run at once, so run on different ports */
 if (!process.useUV) {
   // these tests will not run yet with net_uv TODO: remove when net_uv supports dns
-  pingPongTest(20997, '::1');
   pingPongTest('/tmp/pingpong.sock');
 }
 pingPongTest(20988);
 pingPongTest(20989, 'localhost');
+pingPongTest(20997, '::1');
 
 process.addListener('exit', function () {
   if (!process.useUV) {
     assert.equal(4, tests_run);
   } else {
-    assert.equal(2, tests_run);
+    assert.equal(3, tests_run);
   }
   console.log('done');
 });