Skip to content

Commit 99749dc

Browse files
jBarzMylesBorins
authored andcommittedApr 19, 2017
tls: keep track of stream that is closed
TLSWrap object keeps a pointer reference to the underlying TCPWrap object. This TCPWrap object could be closed and deleted by the event-loop which leaves us with a dangling pointer. So the TLSWrap object needs to track the "close" event on the TCPWrap object. PR-URL: #11776 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Brian White <[email protected]>
1 parent ba91c41 commit 99749dc

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed
 

‎lib/_tls_wrap.js

+6
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,12 @@ TLSSocket.prototype._wrapHandle = function(wrap) {
391391
res = null;
392392
});
393393

394+
if (wrap) {
395+
wrap.on('close', function() {
396+
res.onStreamClose();
397+
});
398+
}
399+
394400
return res;
395401
};
396402

‎src/tls_wrap.cc

+10-1
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ int TLSWrap::GetFD() {
523523

524524

525525
bool TLSWrap::IsAlive() {
526-
return ssl_ != nullptr && stream_->IsAlive();
526+
return ssl_ != nullptr && stream_ != nullptr && stream_->IsAlive();
527527
}
528528

529529

@@ -783,6 +783,14 @@ void TLSWrap::EnableSessionCallbacks(
783783
}
784784

785785

786+
void TLSWrap::OnStreamClose(const FunctionCallbackInfo<Value>& args) {
787+
TLSWrap* wrap;
788+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
789+
790+
wrap->stream_ = nullptr;
791+
}
792+
793+
786794
void TLSWrap::DestroySSL(const FunctionCallbackInfo<Value>& args) {
787795
TLSWrap* wrap;
788796
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
@@ -913,6 +921,7 @@ void TLSWrap::Initialize(Local<Object> target,
913921
env->SetProtoMethod(t, "enableSessionCallbacks", EnableSessionCallbacks);
914922
env->SetProtoMethod(t, "destroySSL", DestroySSL);
915923
env->SetProtoMethod(t, "enableCertCb", EnableCertCb);
924+
env->SetProtoMethod(t, "onStreamClose", OnStreamClose);
916925

917926
StreamBase::AddMethods<TLSWrap>(env, t, StreamBase::kFlagHasWritev);
918927
SSLWrap<TLSWrap>::AddMethods(env, t);

‎src/tls_wrap.h

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class TLSWrap : public AsyncWrap,
135135
static void EnableCertCb(
136136
const v8::FunctionCallbackInfo<v8::Value>& args);
137137
static void DestroySSL(const v8::FunctionCallbackInfo<v8::Value>& args);
138+
static void OnStreamClose(const v8::FunctionCallbackInfo<v8::Value>& args);
138139

139140
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
140141
static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
5+
const tls = require('tls');
6+
const fs = require('fs');
7+
const net = require('net');
8+
9+
const key = fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem');
10+
const cert = fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem');
11+
12+
const T = 100;
13+
14+
// tls server
15+
const tlsServer = tls.createServer({ cert, key }, (socket) => {
16+
setTimeout(() => {
17+
socket.on('error', (error) => {
18+
assert.strictEqual(error.code, 'EINVAL');
19+
tlsServer.close();
20+
netServer.close();
21+
});
22+
socket.write('bar');
23+
}, T * 2);
24+
});
25+
26+
// plain tcp server
27+
const netServer = net.createServer((socket) => {
28+
// if client wants to use tls
29+
tlsServer.emit('connection', socket);
30+
31+
socket.setTimeout(T, () => {
32+
// this breaks if TLSSocket is already managing the socket:
33+
socket.destroy();
34+
});
35+
}).listen(0, common.mustCall(function() {
36+
37+
// connect client
38+
tls.connect({
39+
host: 'localhost',
40+
port: this.address().port,
41+
rejectUnauthorized: false
42+
}).write('foo');
43+
}));

0 commit comments

Comments
 (0)