Created
June 24, 2011 15:43
-
-
Save csosborn/1045054 to your computer and use it in GitHub Desktop.
demonstration of stream-related bug in tls.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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