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