TLS: flush buffer before destroy

Also disable test-https-large-response.js. Covered by
test/simple/test-tls-throttle.js
This commit is contained in:
Ryan Dahl
2011-02-02 15:26:28 -08:00
parent e6f14d6df5
commit 41b4ec7952
3 changed files with 111 additions and 18 deletions

View File

@@ -3,7 +3,7 @@ var util = require('util');
var net = require('net');
var events = require('events');
var stream = require('stream');
var END_OF_FILE = 42;
var assert = require('assert').ok;
var debug;
@@ -38,6 +38,10 @@ util.inherits(CryptoStream, stream.Stream);
CryptoStream.prototype.write = function(data /* , encoding, cb */) {
if (!this.writable) {
throw new Error('CryptoStream is not writable');
}
var encoding, cb;
// parse arguments
@@ -135,31 +139,27 @@ CryptoStream.prototype.getCipher = function(err) {
CryptoStream.prototype.end = function(d) {
if (!this.writable) {
throw new Error('CryptoStream is not writable');
}
if (this.pair._done) return;
if (d) {
this.write(d);
this.pair._cycle();
}
// Sending EOF
debug('cleartext end');
this.pair._ssl.shutdown();
this._pending.push(END_OF_FILE);
this._pendingCallbacks.push(null);
this.writable = false;
this.pair._cycle();
this.pair._destroy();
};
CryptoStream.prototype.destroySoon = function(err) {
if (this.pair._done) return;
this.pair._cycle();
if (this._pending.length) {
this.__destroyOnDrain = true;
} else {
this.end();
}
return this.end();
};
@@ -168,6 +168,7 @@ CryptoStream.prototype.destroy = function(err) {
this.pair._destroy();
};
CryptoStream.prototype.fd = -1;
CryptoStream.prototype.__defineGetter__('readyState',
net.Socket.prototype.__lookupGetter__('readyState'));
@@ -212,7 +213,12 @@ CryptoStream.prototype._push = function() {
assert(bytesRead >= 0);
// Bail out if we didn't read any data.
if (bytesRead == 0) return;
if (bytesRead == 0) {
if (this._pendingBytes() == 0 && this._destroyAfterPush) {
this.destroy();
}
return;
}
var chunk = pool.slice(0, bytesRead);
@@ -252,6 +258,22 @@ CryptoStream.prototype._pull = function() {
assert(this._pending.length === this._pendingCallbacks.length);
if (tmp === END_OF_FILE) {
// Sending EOF
debug('end');
this.pair._ssl.shutdown();
// TODO check if we get EAGAIN From shutdown, would have to do it
// again. should unshift END_OF_FILE back onto pending and wait for
// next cycle.
this.pair.encrypted._destroyAfterPush = true;
this.pair._cycle();
//this.pair._destroy();
return;
}
var rv = this._puller(tmp);
if (this.pair._ssl && this.pair._ssl.error) {
@@ -290,7 +312,11 @@ util.inherits(CleartextStream, CryptoStream);
CleartextStream.prototype._pendingBytes = function() {
return this.pair._ssl._clearPending();
if (this.pair._ssl) {
return this.pair._ssl.clearPending();
} else {
return 0;
}
};
@@ -314,7 +340,11 @@ util.inherits(EncryptedStream, CryptoStream);
EncryptedStream.prototype._pendingBytes = function() {
return this.pair._ssl._endPending();
if (this.pair._ssl) {
return this.pair._ssl.encPending();
} else {
return 0;
}
};

View File

@@ -0,0 +1,63 @@
// Server sends a large string. Client counts bytes and pauses every few
// seconds. Makes sure that pause and resume work properly.
var common = require('../common');
var assert = require('assert');
var tls = require('tls');
var fs = require('fs');
var body = '';
process.stdout.write('build body...');
for (var i = 0; i < 10*1024*1024; i++) {
body += 'hello world\n';
}
process.stdout.write('done\n');
var options = {
key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem')
};
var connections = 0;
var server = tls.Server(options, function(socket) {
socket.end(body);
connections++;
});
var recvCount = 0;
server.listen(common.PORT, function() {
var client = tls.connect(common.PORT);
client.on('data', function(d) {
process.stdout.write('.');
recvCount += d.length;
/*
client.pause();
process.nextTick(function () {
client.resume();
});
*/
});
client.on('close', function() {
debugger;
console.log('close');
server.close();
});
});
process.on('exit', function() {
assert.equal(1, connections);
console.log('body.length: %d', body.length);
console.log(' recvCount: %d', recvCount);
assert.equal(body.length, recvCount);
});