tls: process accumulated input
When creating TLSSocket on top of the regular socket that already contains some received data, `_tls_wrap.js` should try to write all that data to the internal `SSL*` instance. fix #6940
This commit is contained in:
parent
56ebf308dc
commit
c79c304ead
@ -178,15 +178,18 @@ function TLSSocket(socket, options) {
|
||||
|
||||
this.on('error', this._tlsError);
|
||||
|
||||
if (!this._handle)
|
||||
this.once('connect', this._init.bind(this));
|
||||
else
|
||||
this._init();
|
||||
if (!this._handle) {
|
||||
this.once('connect', function() {
|
||||
this._init(null);
|
||||
});
|
||||
} else {
|
||||
this._init(socket);
|
||||
}
|
||||
}
|
||||
util.inherits(TLSSocket, net.Socket);
|
||||
exports.TLSSocket = TLSSocket;
|
||||
|
||||
TLSSocket.prototype._init = function() {
|
||||
TLSSocket.prototype._init = function(socket) {
|
||||
assert(this._handle);
|
||||
|
||||
// lib/net.js expect this value to be non-zero if write hasn't been flushed
|
||||
@ -265,6 +268,13 @@ TLSSocket.prototype._init = function() {
|
||||
|
||||
if (options.handshakeTimeout > 0)
|
||||
this.setTimeout(options.handshakeTimeout, this._handleTimeout);
|
||||
|
||||
// Socket already has some buffered data - emulate receiving it
|
||||
if (socket && socket._readableState.length) {
|
||||
var buf;
|
||||
while ((buf = socket.read()) !== null)
|
||||
this.ssl.receive(buf);
|
||||
}
|
||||
};
|
||||
|
||||
TLSSocket.prototype.renegotiate = function(options, callback) {
|
||||
|
@ -195,6 +195,31 @@ void TLSCallbacks::Wrap(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
|
||||
void TLSCallbacks::Receive(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope handle_scope(args.GetIsolate());
|
||||
|
||||
TLSCallbacks* wrap = Unwrap<TLSCallbacks>(args.This());
|
||||
|
||||
CHECK(Buffer::HasInstance(args[0]));
|
||||
char* data = Buffer::Data(args[0]);
|
||||
size_t len = Buffer::Length(args[0]);
|
||||
|
||||
uv_buf_t buf;
|
||||
uv_stream_t* stream = wrap->wrap()->stream();
|
||||
|
||||
// Copy given buffer entirely or partiall if handle becomes closed
|
||||
while (len > 0 && !uv_is_closing((uv_handle_t*) stream)) {
|
||||
wrap->DoAlloc(reinterpret_cast<uv_handle_t*>(stream), len, &buf);
|
||||
size_t copy = buf.len > len ? len : buf.len;
|
||||
memcpy(buf.base, data, copy);
|
||||
wrap->DoRead(stream, buf.len, &buf, UV_UNKNOWN_HANDLE);
|
||||
|
||||
data += copy;
|
||||
len -= copy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TLSCallbacks::Start(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
@ -700,6 +725,7 @@ void TLSCallbacks::Initialize(Handle<Object> target,
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "TLSWrap"));
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "receive", Receive);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "start", Start);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "setVerifyMode", SetVerifyMode);
|
||||
NODE_SET_PROTOTYPE_METHOD(t,
|
||||
|
@ -110,6 +110,7 @@ class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
|
||||
static void OnClientHelloParseEnd(void* arg);
|
||||
|
||||
static void Wrap(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Receive(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetVerifyMode(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void EnableSessionCallbacks(
|
||||
|
72
test/simple/test-tls-delayed-attach.js
Normal file
72
test/simple/test-tls-delayed-attach.js
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
if (!process.versions.openssl) {
|
||||
console.error('Skipping because node compiled without OpenSSL.');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
var net = require('net');
|
||||
var tls = require('tls');
|
||||
var crypto = require('crypto');
|
||||
|
||||
var common = require('../common');
|
||||
|
||||
var sent = 'hello world';
|
||||
var received = '';
|
||||
var ended = 0;
|
||||
|
||||
var options = {
|
||||
key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
|
||||
cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
|
||||
};
|
||||
|
||||
var server = net.createServer(function(c) {
|
||||
setTimeout(function() {
|
||||
var s = new tls.TLSSocket(c, {
|
||||
isServer: true,
|
||||
credentials: crypto.createCredentials(options)
|
||||
});
|
||||
|
||||
s.on('data', function(chunk) {
|
||||
received += chunk;
|
||||
});
|
||||
|
||||
s.on('end', function() {
|
||||
ended++;
|
||||
server.close();
|
||||
s.destroy();
|
||||
});
|
||||
}, 200);
|
||||
}).listen(common.PORT, function() {
|
||||
var c = tls.connect(common.PORT, {
|
||||
rejectUnauthorized: false
|
||||
}, function() {
|
||||
c.end(sent);
|
||||
});
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(received, sent);
|
||||
assert.equal(ended, 1);
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user