Skip to content

Instantly share code, notes, and snippets.

@csosborn
Created June 24, 2011 15:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save csosborn/1045054 to your computer and use it in GitHub Desktop.
Save csosborn/1045054 to your computer and use it in GitHub Desktop.
demonstration of stream-related bug in tls.js
/*
Demonstration of apparent bug in tls.js. When piping a readable file stream into a writable
TLS stream (an https ClientRequest) the TLS stream write() method returns false, causing
the readable stream to pause, then never emits a drain event. The readable stream thus
remains paused and the transfer hangs.
*/
var https = require('https');
var http = require('http');
var fs = require('fs');
// create a blob of data to send over tls
// write it to a file so we can make a readStream out of it
var testblob = new Buffer(500000);
var tlsOpts = {
key: "-----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDx3wdzpq2rvwm3Ucun1qAD/ClB+wW+RhR1nVix286QvaNqePAd\nCAwwLL82NqXcVQRbQ4s95splQnwvjgkFdKVXFTjPKKJI5aV3wSRN61EBVPdYpCre\n535yfG/uDysZFCnVQdnCZ1tnXAR8BirxCNjHqbVyIyBGjsNoNCEPb2R35QIDAQAB\nAoGBAJNem9C4ftrFNGtQ2DB0Udz7uDuucepkErUy4MbFsc947GfENjDKJXr42Kx0\nkYx09ImS1vUpeKpH3xiuhwqe7tm4FsCBg4TYqQle14oxxm7TNeBwwGC3OB7hiokb\naAjbPZ1hAuNs6ms3Ybvvj6Lmxzx42m8O5DXCG2/f+KMvaNUhAkEA/ekrOsWkNoW9\n2n3m+msdVuxeek4B87EoTOtzCXb1dybIZUVv4J48VAiM43hhZHWZck2boD/hhwjC\nM5NWd4oY6QJBAPPcgBVNdNZSZ8hR4ogI4nzwWrQhl9MRbqqtfOn2TK/tjMv10ALg\nlPmn3SaPSNRPKD2hoLbFuHFERlcS79pbCZ0CQQChX3PuIna/gDitiJ8oQLOg7xEM\nwk9TRiDK4kl2lnhjhe6PDpaQN4E4F0cTuwqLAoLHtrNWIcOAQvzKMrYdu1MhAkBm\nEt3qDMnjDAs05lGT72QeN90/mPAcASf5eTTYGahv21cb6IBxM+AnwAPpqAAsHhYR\n9h13Y7uYbaOjvuF23LRhAkBoI9eaSMn+l81WXOVUHnzh3ZwB4GuTyxMXXNOhuiFd\n0z4LKAMh99Z4xQmqSoEkXsfM4KPpfhYjF/bwIcP5gOei\n-----END RSA PRIVATE KEY-----\n",
cert: "-----BEGIN CERTIFICATE-----\nMIIDXDCCAsWgAwIBAgIJAKL0UG+mRkSPMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNV\nBAYTAlVLMRQwEgYDVQQIEwtBY2tuYWNrIEx0ZDETMBEGA1UEBxMKUmh5cyBKb25l\nczEQMA4GA1UEChMHbm9kZS5qczEdMBsGA1UECxMUVGVzdCBUTFMgQ2VydGlmaWNh\ndGUxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0wOTExMTEwOTUyMjJaFw0yOTExMDYw\nOTUyMjJaMH0xCzAJBgNVBAYTAlVLMRQwEgYDVQQIEwtBY2tuYWNrIEx0ZDETMBEG\nA1UEBxMKUmh5cyBKb25lczEQMA4GA1UEChMHbm9kZS5qczEdMBsGA1UECxMUVGVz\ndCBUTFMgQ2VydGlmaWNhdGUxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG\n9w0BAQEFAAOBjQAwgYkCgYEA8d8Hc6atq78Jt1HLp9agA/wpQfsFvkYUdZ1YsdvO\nkL2janjwHQgMMCy/Njal3FUEW0OLPebKZUJ8L44JBXSlVxU4zyiiSOWld8EkTetR\nAVT3WKQq3ud+cnxv7g8rGRQp1UHZwmdbZ1wEfAYq8QjYx6m1ciMgRo7DaDQhD29k\nd+UCAwEAAaOB4zCB4DAdBgNVHQ4EFgQUL9miTJn+HKNuTmx/oMWlZP9cd4QwgbAG\nA1UdIwSBqDCBpYAUL9miTJn+HKNuTmx/oMWlZP9cd4ShgYGkfzB9MQswCQYDVQQG\nEwJVSzEUMBIGA1UECBMLQWNrbmFjayBMdGQxEzARBgNVBAcTClJoeXMgSm9uZXMx\nEDAOBgNVBAoTB25vZGUuanMxHTAbBgNVBAsTFFRlc3QgVExTIENlcnRpZmljYXRl\nMRIwEAYDVQQDEwlsb2NhbGhvc3SCCQCi9FBvpkZEjzAMBgNVHRMEBTADAQH/MA0G\nCSqGSIb3DQEBBQUAA4GBADRXXA2xSUK5W1i3oLYWW6NEDVWkTQ9RveplyeS9MOkP\ne7yPcpz0+O0ZDDrxR9chAiZ7fmdBBX1Tr+pIuCrG/Ud49SBqeS5aMJGVwiSd7o1n\ndhU2Sz3Q60DwJEL1VenQHiVYlWWtqXBThe9ggqRPnCfsCRTP8qifKkjk45zWPcpN\n-----END CERTIFICATE-----\n"
};
port = 12122;
// open a tls server that will receive the data blob and report
// on the progress of the transfer
server = https.createServer(tlsOpts, function (req, res) {
res.writeHead(200);
var total = 0;
req.on('data', function(chunk) {
total += chunk.length;
var progress = Math.floor(total / testblob.length * 100) + '%';
console.log('SERVER: ' + progress);
res.write(progress);
});
req.on('end', function() {
console.log('SERVER: done!');
res.end();
});
});
server.listen(port, function() {
console.log('SERVER: listening on %s...', port);
// POST the data blob to the server
var reqopts = {
host: 'localhost',
port: port,
path: '/',
method: 'POST'
};
var req = https.request(reqopts, function(res) {
console.log('CLIENT: got response');
res.on('data', function(chunk) {
console.log('CLIENT: server says %s', chunk);
});
res.on('end', function(chunk) {
console.log('CLIENT: server says done');
console.log('SUCCESS!');
server.close();
});
});
// listen for an error (although we don't expect one)
req.on('error', function(e) {
console.error(e);
});
// make a readable stream out of our test blob
var testfile = __dirname + '/testfile';
fs.writeFileSync(testfile, testblob);
var fileStream = fs.createReadStream(testfile);
// instrument both streams so we can see what's happening
fileStream.on('data', function(chunk) {
console.log('filestream data event %s', chunk.length);
});
fileStream.realPause = fileStream.pause;
fileStream.pause = function() {
console.log('filestream paused');
this.realPause();
};
fileStream.realResume = fileStream.resume;
fileStream.resume = function() {
console.log('filestream resumed');
this.realResume();
};
req.on('drain', function() {
console.log('request drained');
});
// pipe the file stream into the TLS request
fileStream.pipe(req);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment