tls: more accurate wrapping of connecting socket
authorFedor Indutny <fedor.indutny@gmail.com>
Tue, 5 Nov 2013 14:14:28 +0000 (18:14 +0400)
committerFedor Indutny <fedor.indutny@gmail.com>
Tue, 5 Nov 2013 14:14:28 +0000 (18:14 +0400)
When socket, passed in `tls.connect()` `options` argument is not yet
connected to the server, `_handle` gets assigned to a `net.Socket`,
instead of `TLSSocket`.

When socket is connecting to the remote server (i.e. not yet connected,
but already past dns resolve phase), derive `_connecting` property from
it, because otherwise `afterConnect()` will throw an assertion.

fix #6443

lib/_tls_wrap.js
test/simple/test-tls-connect-given-socket.js

index 3bfe989..dbf55ce 100644 (file)
@@ -158,6 +158,10 @@ function TLSSocket(socket, options) {
     writable: socket.writable
   });
 
+  // To prevent assertion in afterConnect()
+  if (socket)
+    this._connecting = socket._connecting;
+
   this._tlsOptions = options;
   this._secureEstablished = false;
   this._controlReleased = false;
@@ -716,10 +720,21 @@ exports.connect = function(/* [port, host], options, cb */) {
     result = socket;
   }
 
-  if (socket._handle)
+  if (socket._handle && !socket._connecting) {
     onHandle();
-  else
+  } else {
+    // Not even started connecting yet (or probably resolving dns address),
+    // catch socket errors and assign handle.
+    if (!legacy && options.socket) {
+      options.socket.once('connect', function() {
+        assert(options.socket._handle);
+        socket._handle = options.socket._handle;
+        socket._handle.owner = socket;
+        socket.emit('connect');
+      });
+    }
     socket.once('connect', onHandle);
+  }
 
   if (cb)
     result.once('secureConnect', cb);
index 5cb6299..649ef82 100644 (file)
@@ -26,8 +26,8 @@ var net = require('net');
 var fs = require('fs');
 var path = require('path');
 
-var serverConnected = false;
-var clientConnected = false;
+var serverConnected = 0;
+var clientConnected = 0;
 
 var options = {
   key: fs.readFileSync(path.join(common.fixturesDir, 'test_key.pem')),
@@ -35,31 +35,39 @@ var options = {
 };
 
 var server = tls.createServer(options, function(socket) {
-  serverConnected = true;
+  serverConnected++;
   socket.end('Hello');
 }).listen(common.PORT, function() {
-  var socket = net.connect({
-    port: common.PORT,
-    rejectUnauthorized: false
-  }, function() {
+  var waiting = 2;
+  function establish(socket) {
     var client = tls.connect({
       rejectUnauthorized: false,
       socket: socket
     }, function() {
-      clientConnected = true;
+      clientConnected++;
       var data = '';
       client.on('data', function(chunk) {
         data += chunk.toString();
       });
       client.on('end', function() {
         assert.equal(data, 'Hello');
-        server.close();
+        if (--waiting === 0)
+          server.close();
       });
     });
+  }
+
+  // Already connected socket
+  var connected = net.connect(common.PORT, function() {
+    establish(connected);
   });
+
+  // Connecting socket
+  var connecting = net.connect(common.PORT);
+  establish(connecting);
 });
 
 process.on('exit', function() {
-  assert(serverConnected);
-  assert(clientConnected);
+  assert.equal(serverConnected, 2);
+  assert.equal(clientConnected, 2);
 });