Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First pass through swapping between TLS and non TLS server impl #66

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
20 changes: 20 additions & 0 deletions examples/tcp-tls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
var hl7 = require('../lib');

// openssl genrsa -out ../test/test-key.pem 1024
// openssl req -new -key ../test/test-key.pem -out csr.pem -subj '/CN=test.localhost/O=Test/C=XX'
// openssl x509 -req -in csr.pem -signkey ../test/test-key.pem -out ../test/test-cert.pem
// rm csr.pem

////////////////////SERVER///////////////////
var app = hl7.tcp();
app.use(function(req, res, next) {
console.log('Message Recieved From ' + req.facility);
console.log('Message Event: ' + req.event);
console.log('Message Type: ' + req.type);
next();
});

app.start(7778,undefined,{key:'../test/test-key.pem',cert:'../test/test-cert.pem'});
console.log('TLS tcp interface listening on ' + 7778);
////////////////////SERVER///////////////////

55 changes: 52 additions & 3 deletions lib/client/tcp-client.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var Parser = require('../hl7/parser.js');
var net = require('net')
var tls = require('tls')

var VT = String.fromCharCode(0x0b);
var FS = String.fromCharCode(0x1c);
Expand All @@ -18,17 +19,42 @@ function TcpClient() {
this.port = this.options.port;
this.callback = this.options.callback;
this.keepalive = this.options.keepalive;
this.key = this.options.key;
this.cert = this.options.cert;
this.tls = this.options.tls;
this.ca = this.options.ca;
this.rejectUnauthorized = this.options.rejectUnauthorized;
this.checkServerIdentity = this.options.checkServerIdentity;

this.responseBuffer = "";
this.awaitingResponse = false;
this.parser = new Parser({ segmentSeperator: '\r' });

this.timeout = this.options.timeout;
}

TcpClient.prototype.connect = function(callback) {
var self = this;
self.client = net.connect({host: self.host, port: self.port}, function() {

const cb = function() {
self.client.on('data', function(data) {
self.responseBuffer += data.toString();
if (self.responseBuffer.substring(self.responseBuffer.length - 2, self.responseBuffer.length) == FS + CR) {

/*
'Sometimes' the responseBuffer contains things like FS or CR, and so
self.responseBuffer.substring() stops copying early, and the compare to FS+CR fails
So try a real parse, see if it's a response.
*/
var _parsed = false;
var _ackish = false;
try{
const ackish = self.parser.parse(self.responseBuffer.substring(1, self.responseBuffer.length - 1));
_parsed = true;
}catch(e){
console.log('ackish',e)
}

if (self.responseBuffer.substring(self.responseBuffer.length - 2, self.responseBuffer.length) == FS + CR || _parsed) {
var ack = self.parser.parse(self.responseBuffer.substring(1, self.responseBuffer.length - 2));
self.callback(null, ack);
self.responseBuffer = "";
Expand All @@ -39,10 +65,33 @@ TcpClient.prototype.connect = function(callback) {
}
});
callback();
});
}

if( (self.key && self.cert) || self.tls ){
var opts = {host: self.host, port: self.port} // FUTURE client certificate support via .key/.cert
if( self.ca ){
opts.ca = self.ca;
}
if( typeof self.rejectUnauthorized != 'undefined' ){ // can be true or false, if false still add to opts
opts.rejectUnauthorized = self.rejectUnauthorized;
}
if( self.checkServerIdentity ){
opts.checkServerIdentity = self.checkServerIdentity;
}
self.client = tls.connect(opts, cb);
if( self.timeout ){
self.client.setTimeout( self.timeout )
}
}else{
self.client = net.connect({host: self.host, port: self.port}, cb);
}

self.client.on('error', function(err) {
callback(err);
})
self.client.on('timeout', function(err) {
callback('timeout');
})
}

TcpClient.prototype.send = function(msg, callback) {
Expand Down
18 changes: 15 additions & 3 deletions lib/server/tcp-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ var EventEmitter = require('events').EventEmitter;
var Message = require('../hl7/message');
var moment = require('moment');
var net = require('net');
var tls = require('tls');
var fs = require('fs');
var Parser = require('../hl7/parser');
var util = require('util');

Expand Down Expand Up @@ -52,9 +54,9 @@ function Res(socket, ack) {
TcpServer.prototype.start = function(port, encoding, options) {
var self = this;
options = options || {}
this.server = net.createServer(function(socket) {
var message = "";

const cb = function(socket) {
var message = "";
socket.on('data', function(data) {
try {
message += data.toString();
Expand All @@ -76,7 +78,17 @@ TcpServer.prototype.start = function(port, encoding, options) {
message = "";
self.handler(err);
})
});
}

if( options.key && options.cert ){
this.server = tls.createServer({
key : fs.readFileSync(options.key),
cert : fs.readFileSync(options.cert)
}, cb );
}else{
this.server = net.createServer( cb );
}

this.server.listen(port);
}

Expand Down
13 changes: 13 additions & 0 deletions test/test-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB7DCCAVUCFB6xGp/ZQKVbdy8cCDPgaRhzBT3nMA0GCSqGSIb3DQEBCwUAMDUx
FzAVBgNVBAMMDnRlc3QubG9jYWxob3N0MQ0wCwYDVQQKDARUZXN0MQswCQYDVQQG
EwJYWDAeFw0yMTA4MjUxMDU0MzhaFw0yMTA5MjQxMDU0MzhaMDUxFzAVBgNVBAMM
DnRlc3QubG9jYWxob3N0MQ0wCwYDVQQKDARUZXN0MQswCQYDVQQGEwJYWDCBnzAN
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApWwraVQpDueC1vTc5GnS4YMaibpuCWnq
UioCGEgkS7C6PDqWcOv/isFb0fC4NIzoMfC4PM/Mne2OSVb/9g72Wh8+qFht/qTI
9l7ZwBORxt2f/w4RvL06KFZV+bU4CFqdYE5arSLvRTfgXVKt84KNjeLU2nxdAHDF
aNaAMbBprNsCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCDN28IkRMSCWZmR8YpEtwd
Zwu5pUuG0btRIAE8ysR7hxRoDsfOsOAedg2f+nJFeva47vIf+J3lCx7gcmhVMB/j
R+eQ7PpZY+Sg7E4/h1JNnlrXGlrEpbk+QzzPyNmz9VWsl+kWQH7nqo/xHeF1r7PG
8UvN1jIGGF4TZgqYHoP61Q==
-----END CERTIFICATE-----
15 changes: 15 additions & 0 deletions test/test-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQClbCtpVCkO54LW9NzkadLhgxqJum4JaepSKgIYSCRLsLo8OpZw
6/+KwVvR8Lg0jOgx8Lg8z8yd7Y5JVv/2DvZaHz6oWG3+pMj2XtnAE5HG3Z//DhG8
vTooVlX5tTgIWp1gTlqtIu9FN+BdUq3zgo2N4tTafF0AcMVo1oAxsGms2wIDAQAB
AoGAPyko/iN7NcyhgW+m87OQKDjFpja/kuqU5GBTwm+xJBFLWnnIPT9up80iQOuX
ecEfWwodXmK9LsOoY0pLmuilmLAv5p4Ae0WBWFLx4KETicRft250VMwP2siAjRzZ
YHu0c+fU8LVvPJXOyFtyzWOcAGcD+03KmKPm3Iz5y/ER1fkCQQDW5jbspXyYEJ4x
2NFbDqFxrk62n/ysUkLpeZLBPLWwnoQGTZCcHnjIrIuUuX8LMFYEiHmVGDLuKqQ/
AEmkHAPnAkEAxQ+APwNfPDGmd69T1IL+i9vMIEiPMMR4INLkQ3AM7ngzANPTKMQx
vLned2xw4aAQlS0pZ59rwHa7LmrvQHNw7QJBAIn+4x4rVkq/wRX5SNbUGk/Jwrn7
GmH9oQIUE20K8xEreVQi0s2ts5oJUsh6JV6l91aJ3KklFO9jan0aTi+X3dkCQC6Y
I7LCkVoiQ0I5apDtCFL5faKEhZb6XY0lUGPBss0QDr87Vspk2X3OVRPXyDkRJ9qd
+xRNVaUEbe3jyv5qTWECQDNhiAZaz0DCSPLwEmsl8kD+MWbd/roEi1NdKnw3po0j
2LnwkpFOWo23tREndDim8zBrNxzX17iXLmjemcb5gKw=
-----END RSA PRIVATE KEY-----
37 changes: 37 additions & 0 deletions test/test-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,42 @@ describe('TcpServer', function() {
tcpServer.stop()
});
});

describe('TLS support', function() {
it('should start and stop TLS enabled tcp server listenting on specified port', function(done) {
var parser = new hl7.Parser();
var adt = parser.parse(fs.readFileSync('test/samples/adt.hl7').toString());

tcpServer = server.createTcpServer(function(err, req, res) {
});

tcpServer.start(8686,undefined,{key:'test/test-key.pem',cert:'test/test-cert.pem'});

tcpServer.stop();

done();
});
it('should respond to messages sent over TLS', function(done) {
var parser = new hl7.Parser();
var adt = parser.parse(fs.readFileSync('test/samples/adt.hl7').toString());

tcpServer = server.createTcpServer(function(err, req, res) {
res.end();
});

tcpServer.start(8686,undefined,{key:'test/test-key.pem',cert:'test/test-cert.pem'});

setTimeout(function() {
var tcpClient = server.createTcpClient({ host: '127.0.0.1', port: 8686, tls: true });

tcpClient.send(adt, function(ack) {
done();
});
}, 1000);

tcpServer.stop();
});

})
});