THRIFT-2369 Add ssl support for nodejs implementation
Patch: Pierre Lamot
diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js
index 8bcc9df..fb9215f 100644
--- a/lib/nodejs/lib/thrift/connection.js
+++ b/lib/nodejs/lib/thrift/connection.js
@@ -19,6 +19,7 @@
 var util = require('util'),
     EventEmitter = require("events").EventEmitter,
     net = require('net'),
+    tls = require('tls'),
     ttransport = require('./transport'),
     tprotocol = require('./protocol');
 
@@ -67,6 +68,24 @@
     self.emit("connect");
   });
 
+  this.connection.addListener("secureConnect", function() {
+    self.connected = true;
+
+    this.setTimeout(self.options.timeout || 0);
+    this.setNoDelay();
+    this.frameLeft = 0;
+    this.framePos = 0;
+    this.frame = null;
+    self.initialize_retry_vars();
+
+    self.offline_queue.forEach(function(data) {
+      self.connection.write(data);
+    });
+
+    self.emit("connect");
+  });
+
+
   this.connection.addListener("error", function(err) {
     // Only emit the error if no-one else is listening on the connection
     // or if someone is listening on us
@@ -207,6 +226,14 @@
   return connection;
 }
 
+exports.createSSLConnection = function(host, port, options) {
+  var stream = tls.connect(port, host, options);
+  var connection = new Connection(stream, options);
+  connection.host = host;
+  connection.port = port;
+
+  return connection;
+}
 
 
 exports.createClient = function(cls, connection) {
@@ -298,7 +325,7 @@
 
 };
 
-util.inherits(StdIOConnection, EventEmitter);     
+util.inherits(StdIOConnection, EventEmitter);
 
 StdIOConnection.prototype.end = function() {
   this.connection.end();
diff --git a/lib/nodejs/lib/thrift/index.js b/lib/nodejs/lib/thrift/index.js
index 4992bed..9846d3d 100644
--- a/lib/nodejs/lib/thrift/index.js
+++ b/lib/nodejs/lib/thrift/index.js
@@ -22,14 +22,18 @@
 exports.Connection = connection.Connection;
 exports.createClient = connection.createClient;
 exports.createConnection = connection.createConnection;
+exports.createSSLConnection = connection.createSSLConnection;
 exports.createStdIOClient = connection.createStdIOClient;
 exports.createStdIOConnection = connection.createStdIOConnection;
 
 var server = require('./server')
 exports.createServer = server.createServer;
+exports.createSSLServer = server.createSSLServer;
 exports.createHttpServer = server.createHttpServer;
+exports.createHttpsServer = server.createHttpsServer;
 exports.httpMiddleware = server.httpMiddleware;
 exports.createMultiplexServer = server.createMultiplexServer;
+exports.createMultiplexSSLServer = server.createMultiplexSSLServer;
 
 var static_server = require('./static_server')
 exports.createStaticHttpThriftServer = static_server.createStaticHttpThriftServer;
@@ -42,7 +46,7 @@
 exports.MultiplexedProcessor = mprocessor.MultiplexedProcessor
 
 /*
- * Export transport and protocol so they can be used outside of a 
+ * Export transport and protocol so they can be used outside of a
  * cassandra/server context
  */
 exports.TFramedTransport = require('./transport').TFramedTransport;
diff --git a/lib/nodejs/lib/thrift/server.js b/lib/nodejs/lib/thrift/server.js
index 24ec980..398d398 100644
--- a/lib/nodejs/lib/thrift/server.js
+++ b/lib/nodejs/lib/thrift/server.js
@@ -18,6 +18,8 @@
  */
 var net = require('net');
 var http = require('http');
+var https = require('https');
+var tls = require('tls');
 var url = require("url");
 var path = require("path");
 var fs = require("fs");
@@ -52,7 +54,7 @@
       }
       catch (err) {
         if (err instanceof ttransport.InputBufferUnderrunError) {
-          //The last data in the buffer was not a complete message, wait for the rest 
+          //The last data in the buffer was not a complete message, wait for the rest
           transportWithData.rollbackPosition();
         }
         else if (err.message === "Invalid type: undefined") {
@@ -60,10 +62,10 @@
           //This trap is a bit hackish
           //The next step to improve the node behavior here is to have
           //  the compiler generated process method throw a more explicit
-          //  error when the network buffer is empty (regardles of the 
+          //  error when the network buffer is empty (regardles of the
           //  protocol/transport stack in use) and replace this heuristic.
           //  Also transports should probably not force upper layers to
-          //  manage their buffer positions (i.e. rollbackPosition() and 
+          //  manage their buffer positions (i.e. rollbackPosition() and
           //  commitPosition() should be eliminated in lieu of a transport
           //  encapsulated buffer management strategy.)
           transportWithData.rollbackPosition();
@@ -82,6 +84,63 @@
   });
 };
 
+exports.createMultiplexSSLServer = function(processor, options) {
+
+  var transport = (options && options.transport) ? options.transport : ttransport.TBufferedTransport;
+  var protocol = (options && options.protocol) ? options.protocol : TBinaryProtocol;
+
+  return tls.createServer(options, function(stream) {
+    var self = this;
+    stream.on('data', transport.receiver(function(transportWithData) {
+      var input = new protocol(transportWithData);
+      var output = new protocol(new transport(undefined, function(buf) {
+        try {
+            stream.write(buf);
+        } catch (err) {
+            self.emit('error', err);
+            stream.end();
+        }
+      }));
+
+      try {
+        do {
+          processStatus = processor.process(input, output);
+          transportWithData.commitPosition();
+        } while (true);
+      }
+      catch (err) {
+        if (err instanceof ttransport.InputBufferUnderrunError) {
+          //The last data in the buffer was not a complete message, wait for the rest
+          transportWithData.rollbackPosition();
+        }
+        else if (err.message === "Invalid type: undefined") {
+          //No more data in the buffer
+          //This trap is a bit hackish
+          //The next step to improve the node behavior here is to have
+          //  the compiler generated process method throw a more explicit
+          //  error when the network buffer is empty (regardles of the
+          //  protocol/transport stack in use) and replace this heuristic.
+          //  Also transports should probably not force upper layers to
+          //  manage their buffer positions (i.e. rollbackPosition() and
+          //  commitPosition() should be eliminated in lieu of a transport
+          //  encapsulated buffer management strategy.)
+          transportWithData.rollbackPosition();
+        }
+        else {
+          //Unexpected error
+          self.emit('error', err);
+          stream.end();
+        }
+      }
+    }));
+
+    stream.on('end', function() {
+      stream.end();
+    });
+  });
+};
+
+
 function httpRequestHandler(cls, handler, options) {
   if (cls.Processor) {
     cls = cls.Processor;
@@ -122,9 +181,14 @@
 exports.httpMiddleware = httpRequestHandler;
 
 exports.createHttpServer = function(cls, handler, options) {
-  return http.createServer(httpRequestHandler(cls, handler, options));
+    return http.createServer(options, httpRequestHandler(cls, handler, options));
 };
 
+exports.createHttpsServer = function(cls, handler, options) {
+    return https.createServer(options, httpRequestHandler(cls, handler, options));
+};
+
+
 exports.createServer = function(cls, handler, options) {
   if (cls.Processor) {
     cls = cls.Processor;
@@ -133,3 +197,12 @@
 
   return exports.createMultiplexServer(processor,options);
 };
+
+exports.createSSLServer = function(cls, handler, options) {
+  if (cls.Processor) {
+    cls = cls.Processor;
+  }
+  var processor = new cls(handler);
+
+  return exports.createMultiplexSSLServer(processor,options);
+};
diff --git a/lib/nodejs/test/certificates.README b/lib/nodejs/test/certificates.README
new file mode 100644
index 0000000..06c507e
--- /dev/null
+++ b/lib/nodejs/test/certificates.README
@@ -0,0 +1,7 @@
+server.crt AND server.key ARE PROVIDED FOR TEST PURPOSE AND SHOULD *NEVER* BE USED IN PRODUCTION
+
+
+Origin of the test key and cert is the folder test/keys of Apache Thrift source code distribution
+
+We need copies for npm deployment
+
diff --git a/lib/nodejs/test/client.js b/lib/nodejs/test/client.js
index 90d7467..43d88f0 100644
--- a/lib/nodejs/test/client.js
+++ b/lib/nodejs/test/client.js
@@ -21,6 +21,7 @@
 //"ThriftTest" suite. This client will test any protocol/transport
 //combination specified on the command line.
 
+var fs = require('fs');
 var assert = require('assert');
 var thrift = require('thrift');
 var ThriftTransports = require('thrift/transport');
@@ -33,6 +34,7 @@
 program
   .option('-p, --protocol <protocol>', 'Set thrift protocol (binary|json) [protocol]')
   .option('-t, --transport <transport>', 'Set thrift transport (buffered|framed) [transport]')
+  .option('--ssl', 'use SSL transport')
   .parse(process.argv);
 
 var protocol = undefined;
@@ -56,10 +58,19 @@
   transport = ThriftTransports.TBufferedTransport;
 }
 
-var connection = thrift.createConnection('localhost', 9090, {
+var options = {
   transport: transport,
   protocol: protocol
-});
+};
+
+var connection = undefined;
+
+if (program.ssl) {
+  options.rejectUnauthorized = false;
+  connection = thrift.createSSLConnection('localhost', 9090, options);
+} else {
+  connection = thrift.createConnection('localhost', 9090, options);
+}
 
 var client = thrift.createClient(ThriftTest, connection);
 
diff --git a/lib/nodejs/test/multiplex_client.js b/lib/nodejs/test/multiplex_client.js
index 6cf6975..9ef716b 100644
--- a/lib/nodejs/test/multiplex_client.js
+++ b/lib/nodejs/test/multiplex_client.js
@@ -30,6 +30,7 @@
 program
   .option('-p, --protocol <protocol>', 'Set thift protocol (binary|json) [protocol]')
   .option('-t, --transport <transport>', 'Set thift transport (buffered|framed) [transport]')
+  .option('--ssl', 'use ssl transport')
   .parse(process.argv);
 
 var protocol = undefined;
@@ -53,10 +54,18 @@
   transport = ThriftTransports.TBufferedTransport;
 }
 
-var connection = thrift.createConnection('localhost', 9090, {
+var options = {
   transport: transport,
   protocol: protocol
-});
+};
+
+var connection = undefined;
+if (program.ssl) {
+  options.rejectUnauthorized = false
+  connection = thrift.createSSLConnection('localhost', 9090, options);
+} else {
+  connection = thrift.createConnection('localhost', 9090, options);
+}
 
 var mp = new thrift.Multiplexer();
 
diff --git a/lib/nodejs/test/multiplex_server.js b/lib/nodejs/test/multiplex_server.js
index a2a1709..a2ea535 100644
--- a/lib/nodejs/test/multiplex_server.js
+++ b/lib/nodejs/test/multiplex_server.js
@@ -25,11 +25,15 @@
   SecondService = require('./gen-nodejs/SecondService'),
   ttypes = require('./gen-nodejs/ThriftTest_types');
 
+var fs = require("fs");
+var path = require("path");
+
 var program = require('commander');
 
 program
   .option('-p, --protocol <protocol>', 'Set thift protocol (binary|json) [protocol]')
   .option('-t, --transport <transport>', 'Set thift transport (buffered|framed) [transport]')
+  .option('--ssl', 'use ssl transport')
   .parse(process.argv);
 
 var protocol = undefined;
@@ -72,9 +76,19 @@
   "SecondService",
   new SecondService.Processor(SecondServiceHandler));
 
-var server = thrift.createMultiplexServer(processor, {
-  protocol: protocol,
-  transport: transport
-});
+var options = {
+  transport: transport,
+  protocol: protocol
+};
+
+var server = undefined;
+if (program.ssl) {
+  //ssl options
+  options.key = fs.readFileSync(path.resolve(__dirname, 'server.key'));
+  options.cert = fs.readFileSync(path.resolve(__dirname, 'server.crt'));
+  server = thrift.createMultiplexSSLServer(processor, options);
+} else {
+  server = thrift.createMultiplexServer(processor, options);
+}
 
 server.listen(9090);
diff --git a/lib/nodejs/test/server.crt b/lib/nodejs/test/server.crt
new file mode 100644
index 0000000..75f0649
--- /dev/null
+++ b/lib/nodejs/test/server.crt
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIJAKC40O9aq1qjMA0GCSqGSIb3DQEBBQUAMIGvMQswCQYD
+VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs
+MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV
+BAsMDUFwYWNoZSBUaHJpZnQxEDAOBgNVBAMMB3NzbHRlc3QxJDAiBgkqhkiG9w0B
+CQEWFWRldkB0aHJpZnQuYXBhY2hlLm9yZzAeFw0xNDAyMDkxNzAwNTZaFw0yMjA0
+MjgxNzAwNTZaMIGvMQswCQYDVQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDAS
+BgNVBAcMC0ZvcmVzdCBIaWxsMScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJl
+IEZvdW5kYXRpb24xFjAUBgNVBAsMDUFwYWNoZSBUaHJpZnQxEDAOBgNVBAMMB3Nz
+bHRlc3QxJDAiBgkqhkiG9w0BCQEWFWRldkB0aHJpZnQuYXBhY2hlLm9yZzCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMuczDt5da6M0g9+trj5Df4/Xz1e
+Y4tf6Ch4g6PSWgKTdrnZpXixtdoYSmXe9NIlEepKr7TFrqUmk7pgxkLGj+probIB
+I0vK9GYWMxc8D2meD6IZZkDx/4cS575tpKL2QmjmlqVSWZE38R0YuPo4xjlNWc7+
+CvK5d6dmCgypvKye0Qmi8Oo1TzKH30L3DEIxn2V6sERfXhV3AIuh28qn5ymhR42i
+/acTriF4hV/7GgcmiBnAiPeMXn47ZdCRaVv01DAicl/ImGSFo+9A3DBLzP8h+9Qv
+FqiAOp7gSlfLBjzW1xKi6K+91wtenaz6DmSHtGyVMsQnXiKiyi+QE5xpH6ECAwEA
+AaNQME4wHQYDVR0OBBYEFIuvCIHtKsVW63iINRpCpWFSy566MB8GA1UdIwQYMBaA
+FIuvCIHtKsVW63iINRpCpWFSy566MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF
+BQADggEBAFVYAfs+ZgE/fsSrsARZ3eZ94IC5E6qRH7P2yOyO96YTxlLRIniYqCYL
+l7SM4JYj8k6/QjfxjeqTU4XX0W2ZXNY1+sfU1lATuzHbeY6tzxZytUu3lmYOOfHv
+UyyLBAbrAkXZy+CKiD833eBBUtPxNd46nJ5KQPIN6FqKRB5EpW6eSXRohCoSmy8I
+4QVI3xGNeNgZznGM58nhLD+8VQ2j3/SEnukGxSV67uoNyeyZ60QKYg+TLdSEtb4G
+hxzOTOH+b324Fw1gipTfnrJImz1qmFAtOPS7IJGwQjjS/nfAmV+P4gXj2tU0VHCR
+UcI8VRqdK4GFbnGapPpHWx7nQOSMHtE=
+-----END CERTIFICATE-----
diff --git a/lib/nodejs/test/server.js b/lib/nodejs/test/server.js
index da9a4d6..69519ab 100644
--- a/lib/nodejs/test/server.js
+++ b/lib/nodejs/test/server.js
@@ -22,6 +22,8 @@
 //    TFramedTransport
 //    TSocket
 
+var fs = require('fs');
+var path = require('path');
 var thrift = require('thrift');
 var ThriftTransports = require('thrift/transport');
 var ThriftProtocols = require('thrift/protocol');
@@ -34,6 +36,7 @@
 program
   .option('-p, --protocol <protocol>', 'Set thift protocol (binary|json) [protocol]')
   .option('-t, --transport <transport>', 'Set thift transport (buffered|framed) [transport]')
+  .option('--ssl', 'use ssl transport')
   .parse(process.argv);
 
 var protocol = undefined;
@@ -57,7 +60,18 @@
   transport = ThriftTransports.TBufferedTransport;
 }
 
-thrift.createServer(ThriftTest, ThriftTestHandler, {
+var options = {
   protocol: protocol,
   transport: transport
-}).listen(9090);
+};
+
+if (program.ssl) {
+  //ssl options
+  options.key = fs.readFileSync(path.resolve(__dirname, 'server.key'));
+  options.cert = fs.readFileSync(path.resolve(__dirname, 'server.crt'));
+  thrift.createSSLServer(ThriftTest, ThriftTestHandler, options).listen(9090);
+
+} else {
+  //default
+  thrift.createServer(ThriftTest, ThriftTestHandler, options).listen(9090);
+}
diff --git a/lib/nodejs/test/server.key b/lib/nodejs/test/server.key
new file mode 100644
index 0000000..6356e30
--- /dev/null
+++ b/lib/nodejs/test/server.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLnMw7eXWujNIP
+fra4+Q3+P189XmOLX+goeIOj0loCk3a52aV4sbXaGEpl3vTSJRHqSq+0xa6lJpO6
+YMZCxo/qa6GyASNLyvRmFjMXPA9png+iGWZA8f+HEue+baSi9kJo5palUlmRN/Ed
+GLj6OMY5TVnO/gryuXenZgoMqbysntEJovDqNU8yh99C9wxCMZ9lerBEX14VdwCL
+odvKp+cpoUeNov2nE64heIVf+xoHJogZwIj3jF5+O2XQkWlb9NQwInJfyJhkhaPv
+QNwwS8z/IfvULxaogDqe4EpXywY81tcSouivvdcLXp2s+g5kh7RslTLEJ14iosov
+kBOcaR+hAgMBAAECggEAS70Fk1H43nbvZGgkG+Y4uExmZvOHX77LItLBVNzYMoEb
+9sHo9V5VYM0MT5yBwPGdGmOxvDKUZkZVSUzaMtidi/uBaC9YK8dQ5fB4DLqAmS78
+bbW4/YuHG32CyqkKRrwHs/GiM9jQDF6cx8/8bsdTpNkLAR4qgGNRCOnB7zfsQOEg
+eAcJjsJxJc/w0LpWBVCPWxMKZ/M6An7tnp/rxcCuC50FnUYwn2imDRiCZHooGyO8
+qEt8kOT/0n550nPWMvjmgqkcALYhPF2gna5JlsoYau+lEFNj9KY+r3vDy+rhhnKV
+2RbUFs6315tkEcnmWwxYiwphBaUZLmnqMpgosI/xiQKBgQDzigau5QadqaADAQf4
+TbeouODC7o/K2eTQGAhH8TdEazumZdxFWcT+RpGOKxgzJ+dZ6T8+bt8WtNMx72yH
+yJ2wnBnqSvgCUPEelsabbzi8a8blKlz3cnXCgaa545LCTx4yam59LQnFHdoAAHtI
+ZMlfcbuCZ7IplATqEF3KvYdz2wKBgQDWB8vKfzUJiGPlElR9ylw3iK7Jvxm26z9a
+oR4D8YEP0+80S8wz4pnht8JSU4X1n4w4Spa0Z1m0KknkhakbOBKiVU1/OFmF+7uz
+iZfPqko/K18e+w3JhTKHLQOYZXKohE7vLXATaKF52FBCjWlpjo2sYL64kqoEnQiw
+IC4HVcqRMwKBgQCp+O9pKVdQuo5/Cj0xw6wnCcF0y2N4RFM6GUvOSkA0dFMRc44k
+qN6gSUhVXSZqrbL+QZhuTptNEa9E7sFkk1Pba1d6+g/WLf/bRYgf+6QxfVc3ojV4
+Tl55/lsK6hYHn4iHz1iF7OUguhDoZ22jvRP+lTY1cYIbGr/DTODpGxZqeQKBgFw+
+4/CUvvEq3ZMfQVct3mz49gxx1s1lutp+0ob0kaGWwGQTvyElqxkDsDb3VKc2aqLg
+Uu/SE3F5QHvDt8zJcA6TIWGRkdQTWSTaSpnwVSvAr7CUl66hP9PO7NvD7ZT/4V1o
+ggN7dw0i1AS7GhGqpRkEYW7/l1OBsvrmA7CZo0LNAoGBAMeOaIc/F+dVwXYpLfUZ
+1ILANiTL9qSBJi3UWaTyFReXLU5TJ38q63z+RCzi73le6Odd7C4YXe8W/+qgAViM
+XOnL6DS8gZqQu9bHDWU8PQksmmwV1WWB6H7z5oKCwBxlGxNUSJPwsumry535vBQy
+qIoi2mRSBEtQLeh4aEYGyJEp
+-----END PRIVATE KEY-----
diff --git a/lib/nodejs/test/testAll.sh b/lib/nodejs/test/testAll.sh
index 3e64393..cdd0c79 100755
--- a/lib/nodejs/test/testAll.sh
+++ b/lib/nodejs/test/testAll.sh
@@ -25,24 +25,24 @@
 
 testClientServer()
 {
-  echo "   Testing Client/Server with protocol $1 and transport $2";
+  echo "   Testing Client/Server with protocol $1 and transport $2 $3";
   RET=0
-  node ${DIR}/server.js -p $1 -t $2 &
+  node ${DIR}/server.js -p $1 -t $2 $3 &
   SERVERPID=$!
   sleep 1
-  node ${DIR}/client.js -p $1 -t $2 || RET=1
+  node ${DIR}/client.js -p $1 -t $2 $3 || RET=1
   kill -9 $SERVERPID || RET=1
   return $RET
 }
 
 testMultiplexedClientServer()
 {
-  echo "   Testing Multiplexed Client/Server with protocol $1 and transport $2";
+  echo "   Testing Multiplexed Client/Server with protocol $1 and transport $2 $3";
   RET=0
-  node ${DIR}/multiplex_server.js -p $1 -t $2 &
+  node ${DIR}/multiplex_server.js -p $1 -t $2 $3 &
   SERVERPID=$!
   sleep 1
-  node ${DIR}/multiplex_client.js -p $1 -t $2 || RET=1
+  node ${DIR}/multiplex_client.js -p $1 -t $2 $3 || RET=1
   kill -9 $SERVERPID || RET=1 #f
   return $RET
 }
@@ -65,9 +65,15 @@
 testClientServer binary framed || TESTOK=1
 testClientServer json framed || TESTOK=1
 
+#tests for multiplexed services
 testMultiplexedClientServer binary buffered || TESTOK=1
 testMultiplexedClientServer json buffered || TESTOK=1
 testMultiplexedClientServer binary framed || TESTOK=1
 testMultiplexedClientServer json framed || TESTOK=1
 
+#test ssl connection
+testClientServer binary framed --ssl || TESTOK=1
+testMultiplexedClientServer binary framed --ssl || TESTOK=1
+
+
 exit $TESTOK
diff --git a/test/test.sh b/test/test.sh
index 8a74697..09c6ad1 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -103,7 +103,7 @@
 
 nodejs_protocols="binary json"
 nodejs_transports="buffered framed"
-nodejs_sockets="ip"
+nodejs_sockets="ip ip-ssl"
 
 ant -f ../lib/java/build.xml compile-test 1>/dev/null
 
@@ -181,8 +181,12 @@
 for proto in $(intersection "${nodejs_protocols}" "${cpp_protocols}"); do
   for trans in $(intersection "${nodejs_transports}" "${cpp_transports}"); do
     for sock in $(intersection "${nodejs_sockets}" "${cpp_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
       do_test "nodejs-cpp" "${proto}" "${trans}-ip" \
-              "nodejs ${NODE_TEST_DIR}/client.js -p ${proto} -t ${trans}" \
+              "nodejs ${NODE_TEST_DIR}/client.js -p ${proto} -t ${trans} ${extraparam}" \
               "cpp/TestServer --protocol=${proto} --transport=${trans} ${extraparam}" \
               "10" "10"
     done
@@ -193,9 +197,13 @@
 for proto in $(intersection "${nodejs_protocols}" "${cpp_protocols}"); do
   for trans in $(intersection "${nodejs_transports}" "${cpp_transports}"); do
     for sock in $(intersection "${nodejs_sockets}" "${cpp_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
       do_test "cpp-nodejs" "${proto}" "${trans}-ip" \
-              "cpp/TestClient --protocol=${proto} --transport=${trans}" \
-              "nodejs ${NODE_TEST_DIR}/server.js -p ${proto} -t ${trans}" \
+              "cpp/TestClient --protocol=${proto} --transport=${trans} ${extraparam}" \
+              "nodejs ${NODE_TEST_DIR}/server.js -p ${proto} -t ${trans} ${extraparam}" \
               "10" "10"
     done
   done