summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/_tls_wrap.js5
-rw-r--r--src/tls_wrap.cc24
-rw-r--r--src/tls_wrap.h1
-rw-r--r--test/parallel/test-tls-buffersize.js43
4 files changed, 68 insertions, 5 deletions
diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js
index b5ac8a5c9b..d7e349b239 100644
--- a/lib/_tls_wrap.js
+++ b/lib/_tls_wrap.js
@@ -455,9 +455,8 @@ TLSSocket.prototype._init = function(socket, wrap) {
var ssl = this._handle;
// lib/net.js expect this value to be non-zero if write hasn't been flushed
- // immediately
- // TODO(indutny): revise this solution, it might be 1 before handshake and
- // represent real writeQueueSize during regular writes.
+ // immediately. After the handshake is done this will represent the actual
+ // write queue size
ssl.writeQueueSize = 1;
this.server = options.server;
diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc
index 738bd04071..0da332f16e 100644
--- a/src/tls_wrap.cc
+++ b/src/tls_wrap.cc
@@ -42,6 +42,7 @@ using v8::Exception;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
+using v8::Integer;
using v8::Local;
using v8::Object;
using v8::String;
@@ -297,6 +298,7 @@ void TLSWrap::EncOut() {
// No data to write
if (BIO_pending(enc_out_) == 0) {
+ UpdateWriteQueueSize();
if (clear_in_->Length() == 0)
InvokeQueued(0);
return;
@@ -551,6 +553,18 @@ bool TLSWrap::IsClosing() {
}
+uint32_t TLSWrap::UpdateWriteQueueSize(uint32_t write_queue_size) {
+ HandleScope scope(env()->isolate());
+ if (write_queue_size == 0)
+ write_queue_size = BIO_pending(enc_out_);
+ object()->Set(env()->context(),
+ env()->write_queue_size_string(),
+ Integer::NewFromUnsigned(env()->isolate(),
+ write_queue_size)).FromJust();
+ return write_queue_size;
+}
+
+
int TLSWrap::ReadStart() {
return stream_->ReadStart();
}
@@ -591,8 +605,12 @@ int TLSWrap::DoWrite(WriteWrap* w,
ClearOut();
// However, if there is any data that should be written to the socket,
// the callback should not be invoked immediately
- if (BIO_pending(enc_out_) == 0)
+ if (BIO_pending(enc_out_) == 0) {
+ // net.js expects writeQueueSize to be > 0 if the write isn't
+ // immediately flushed
+ UpdateWriteQueueSize(1);
return stream_->DoWrite(w, bufs, count, send_handle);
+ }
}
// Queue callback to execute it on next tick
@@ -642,13 +660,15 @@ int TLSWrap::DoWrite(WriteWrap* w,
// Try writing data immediately
EncOut();
+ UpdateWriteQueueSize();
return 0;
}
void TLSWrap::OnAfterWriteImpl(WriteWrap* w, void* ctx) {
- // Intentionally empty
+ TLSWrap* wrap = static_cast<TLSWrap*>(ctx);
+ wrap->UpdateWriteQueueSize();
}
diff --git a/src/tls_wrap.h b/src/tls_wrap.h
index fe3abe04f5..8d75d6fcc9 100644
--- a/src/tls_wrap.h
+++ b/src/tls_wrap.h
@@ -132,6 +132,7 @@ class TLSWrap : public AsyncWrap,
AsyncWrap* GetAsyncWrap() override;
bool IsIPCPipe() override;
+ uint32_t UpdateWriteQueueSize(uint32_t write_queue_size = 0);
// Resource implementation
static void OnAfterWriteImpl(WriteWrap* w, void* ctx);
diff --git a/test/parallel/test-tls-buffersize.js b/test/parallel/test-tls-buffersize.js
new file mode 100644
index 0000000000..49848cd865
--- /dev/null
+++ b/test/parallel/test-tls-buffersize.js
@@ -0,0 +1,43 @@
+'use strict';
+const common = require('../common');
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+const assert = require('assert');
+const fixtures = require('../common/fixtures');
+const tls = require('tls');
+
+const iter = 10;
+const overhead = 30;
+
+const server = tls.createServer({
+ key: fixtures.readKey('agent2-key.pem'),
+ cert: fixtures.readKey('agent2-cert.pem')
+}, common.mustCall((socket) => {
+ socket.on('readable', common.mustCallAtLeast(() => {
+ socket.read();
+ }, 1));
+
+ socket.on('end', common.mustCall(() => {
+ server.close();
+ }));
+}));
+
+server.listen(0, common.mustCall(() => {
+ const client = tls.connect({
+ port: server.address().port,
+ rejectUnauthorized: false
+ }, common.mustCall(() => {
+ assert.strictEqual(client.bufferSize, 0);
+
+ for (let i = 1; i < iter; i++) {
+ client.write('a');
+ assert.strictEqual(client.bufferSize, i + overhead);
+ }
+
+ client.on('finish', common.mustCall(() => {
+ assert.strictEqual(client.bufferSize, 0);
+ }));
+
+ client.end();
+ }));
+}));