joyent/node — pull request #4756 by isaacs (2013-02-11 23:55:28+00:00)
Title: TLS Fast Writing

I found some odd behavior when writing a TLS throughput benchmark. Given a script like this:

```javascript
var server = tls.createServer(options, function(conn) {
conn.on('data', function(chunk) {
console.error('got chunk', chunk.length);
});
}).listen(PORT, function() {
var opt = {port:PORT, rejectUnauthorized: false };
var conn = tls.connect(opt, function() {
conn.on('drain', write);
write();
});

function write() {
while (false !== conn.write(chunk));
}
});
```

it would never actually allow the server to receive the chunk. The client cryptostream would just keep returning `true` from every write, and buffering more and more data up behind the TCP socket.

The reasons for this are twofold:

1. We're treating `read(0)` as a "trigger a _read()/readable-event" type of API. While this is valuable, especially for oddball streams like TLS, it was doing it too aggressively. With this change, if there is already enough data in the buffer, then `read(0)` will just immediately emit 'readable' rather than doing another call to _read.
2. The TLS pipes the encrypted CryptoStream onto the socket. However, this means that `socket.on('drain')` will attempt to read some more from the encrypted side, but it needs to also cycle the cleartext side, so that we handle cases where this "wrote too much, read(0) stopped doing anything" scenario is encountered.

Review, please: @indutny