Merge remote-tracking branch 'origin/v0.8'

Conflicts:
	deps/uv/include/uv.h
	src/node_crypto.cc
This commit is contained in:
Ben Noordhuis 2012-09-04 15:02:20 +02:00
Родитель 19a432260c 9f57e422cf
Коммит 972cdf82f1
16 изменённых файлов: 440 добавлений и 75 удалений

Просмотреть файл

@ -22,11 +22,11 @@ endif
# to check for changes.
.PHONY: node node_g
node: config.gypi
node: config.gypi out/Makefile
$(MAKE) -C out BUILDTYPE=Release V=$(V)
ln -fs out/Release/node node
node_g: config.gypi
node_g: config.gypi out/Makefile
$(MAKE) -C out BUILDTYPE=Debug V=$(V)
ln -fs out/Debug/node node_g

Просмотреть файл

@ -3,7 +3,13 @@ Evented I/O for V8 javascript. [![Build Status](https://secure.travis-ci.org/joy
### To build:
Unix/Macintosh. Requires python 2.6 or 2.7 and GNU make 3.81 or newer:
Prerequisites (Unix only):
* Python 2.6 or 2.7
* GNU Make 3.81 or newer
* libexecinfo (FreeBSD and OpenBSD only)
Unix/Macintosh:
./configure
make

Просмотреть файл

@ -357,7 +357,7 @@ the worker finally die.
Because there might be long living connections, it is useful to implement a timeout.
This example ask the worker to disconnect and after 2 seconds it will destroy the
server. An alternative wound be to execute `worker.destroy()` after 2 seconds, but
server. An alternative would be to execute `worker.destroy()` after 2 seconds, but
that would normally not allow the worker to do any cleanup if needed.
if (cluster.isMaster) {

Просмотреть файл

@ -354,7 +354,7 @@ which has been transmitted are equal or not.
### response.statusCode
When using implicit headers (not calling `response.writeHead()` explicitly), this property
controls the status code that will be send to the client when the headers get
controls the status code that will be sent to the client when the headers get
flushed.
Example:
@ -452,7 +452,7 @@ emit trailers, with a list of the header fields in its value. E.g.,
### response.end([data], [encoding])
This method signals to the server that all of the response headers and body
has been sent; that server should consider this message complete.
have been sent; that server should consider this message complete.
The method, `response.end()`, MUST be called on each
response.

116
doc/blog/release/v0.9.1.md Normal file
Просмотреть файл

@ -0,0 +1,116 @@
version: 0.9.1
title: Version 0.9.1 (Unstable)
category: release
slug: node-v0-9-1-unstable
date: 2012-08-28T22:33:45.659Z
2012.08.28, Version 0.9.1 (Unstable)
* buffer: Add Buffer.isEncoding(enc) to test for valid encoding values (isaacs)
* Raise UV_ECANCELED on premature close. (Ben Noordhuis)
* Remove c-ares from libuv, move to a top-level node dependency (Bert Belder)
* ref/unref for all HandleWraps, timers, servers, and sockets (Timothy J Fontaine)
* addon: remove node-waf, superseded by node-gyp (Ben Noordhuis)
* child_process: emit error on exec failure (Ben Noordhuis)
* cluster: do not use internal server API (Andreas Madsen)
* constants: add O_DIRECT (Ian Babrou)
* crypto: add sync interface to crypto.pbkdf2() (Ben Noordhuis)
* darwin: emulate fdatasync() (Fedor Indutny)
* dgram: make .bind() always asynchronous (Ben Noordhuis)
* events: Make emitter.listeners() side-effect free (isaacs, Joe Andaverde)
* fs: Throw early on invalid encoding args (isaacs)
* fs: fix naming of truncate/ftruncate functions (isaacs)
* http: bubble up parser errors to ClientRequest (Brian White)
* linux: improve cpuinfo parser on ARM and MIPS (Ben Noordhuis)
* net: add support for IPv6 addresses ending in :: (Josh Erickson)
* net: support Server.listen(Pipe) (Andreas Madsen)
* node: don't scan add-on for "init" symbol (Ben Noordhuis)
* remove process.uvCounters() (Ben Noordhuis)
* repl: console writes to repl rather than process stdio (Nathan Rajlich)
* timers: implement setImmediate (Timothy J Fontaine)
* tls: fix segfault in pummel/test-tls-ci-reneg-attack (Ben Noordhuis)
* tools: Move gyp addon tools to node-gyp (Nathan Rajlich)
* unix: preliminary signal handler support (Ben Noordhuis)
* unix: remove dependency on ev_child (Ben Noordhuis)
* unix: work around darwin bug, don't poll() on pipe (Fedor Indutny)
* util: Formally deprecate util.pump() (Ben Noordhuis)
* windows: make active and closing handle state independent (Bert Belder)
* windows: report spawn errors to the exit callback (Bert Belder)
* windows: signal handling support with uv_signal_t (Bert Belder)
Source Code: http://nodejs.org/dist/v0.9.1/node-v0.9.1.tar.gz
Macintosh Installer (Universal): http://nodejs.org/dist/v0.9.1/node-v0.9.1.pkg
Windows Installer: http://nodejs.org/dist/v0.9.1/node-v0.9.1-x86.msi
Windows x64 Installer: http://nodejs.org/dist/v0.9.1/x64/node-v0.9.1-x64.msi
Windows x64 Files: http://nodejs.org/dist/v0.9.1/x64/
Linux 32-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-linux-x86.tar.gz
Linux 64-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-linux-x64.tar.gz
Solaris 32-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-sunos-x86.tar.gz
Solaris 64-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-sunos-x64.tar.gz
Other release files: http://nodejs.org/dist/v0.9.1/
Website: http://nodejs.org/docs/v0.9.1/
Documentation: http://nodejs.org/docs/v0.9.1/api/
Shasums:
```
b86a5b0b2c9a89d08baaeb3d5270a8f247b4ba43 node-v0.9.1-darwin-x64.tar.gz
800af9d15a4b65e624351bb94dedc3b7eb322b86 node-v0.9.1-darwin-x86.tar.gz
a7ea43b0db472ca84dc9838960dae57ff0abaa72 node-v0.9.1-linux-x64.tar.gz
89c4be492a946eefa45aa87d16787875aa0f2dff node-v0.9.1-linux-x86.tar.gz
6495d2814541e945dba5941b8d3facf2a61dc55d node-v0.9.1-sunos-x64.tar.gz
05ea83ba4d648f5b949833bb28d69e6eeebabb78 node-v0.9.1-sunos-x86.tar.gz
3ccf1ac2fea7f2d05bcaed590bc54ee61c982fbb node-v0.9.1-x86.msi
bd0ede40e4681b16088284fe6a18ae3a5c5a3795 node-v0.9.1.tar.gz
159470a999ef23fa940ad3c54265053c3d2a4332 node.exe
02472e388a44b91e2644178a0fe011354fcd361e node.exp
c6d6ce22be4b47ad022d82dd91ebd4c040742fee node.lib
7b4cec8b4106d90a077388fe483fdbb13119dcb1 node.pdb
a5fbf5e22c7623a9206abc6608d084ff53c7c4c9 x64/node-v0.9.1-x64.msi
9755685a9d7bea6dc63d3260829c26c5b0430a7a x64/node.exe
621f177733647848f7f667926fe4f498a1f50c97 x64/node.exp
5877dffbf012c458dab88f3392af59cb33720d2f x64/node.lib
dc513ce5c16771dcfab9c1777d5949252290b412 x64/node.pdb
```

Просмотреть файл

@ -300,6 +300,9 @@ function setupChannel(target, channel) {
} else {
this.buffering = false;
target.disconnect();
channel.onread = nop;
channel.close();
maybeClose(target);
}
};
@ -755,7 +758,7 @@ ChildProcess.prototype.spawn = function(options) {
ipc = createPipe(true);
ipcFd = i;
acc.push({ type: 'pipe', handle: ipc });
acc.push({ type: 'pipe', handle: ipc, ipc: true });
} else if (typeof stdio === 'number' || typeof stdio.fd === 'number') {
acc.push({ type: 'fd', fd: stdio.fd || stdio });
} else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) ||
@ -806,6 +809,11 @@ ChildProcess.prototype.spawn = function(options) {
stdio.forEach(function(stdio, i) {
if (stdio.type === 'ignore') return;
if (stdio.ipc) {
self._closesNeeded++;
return;
}
if (stdio.handle) {
// when i === 0 - we're dealing with stdin
// (which is the only one writable pipe)

Просмотреть файл

@ -106,6 +106,7 @@ function normalizeConnectArgs(args) {
var cb = args[args.length - 1];
return (typeof cb === 'function') ? [options, cb] : [options];
}
exports._normalizeConnectArgs = normalizeConnectArgs;
/* called when creating new Socket, or when re-using a closed Socket */

Просмотреть файл

@ -1217,34 +1217,24 @@ Server.prototype.SNICallback = function(servername) {
// });
//
//
function normalizeConnectArgs(listArgs) {
var args = net._normalizeConnectArgs(listArgs);
var options = args[0];
var cb = args[1];
if (typeof listArgs[1] === 'object') {
options = util._extend(options, listArgs[1]);
} else if (typeof listArgs[2] === 'object') {
options = util._extend(options, listArgs[2]);
}
return (cb) ? [options, cb] : [options];
}
exports.connect = function(/* [port, host], options, cb */) {
var options, port, host, cb;
if (typeof arguments[0] === 'object') {
options = arguments[0];
} else if (typeof arguments[1] === 'object') {
options = arguments[1];
port = arguments[0];
} else if (typeof arguments[2] === 'object') {
options = arguments[2];
port = arguments[0];
host = arguments[1];
} else {
// This is what happens when user passes no `options` argument, we can't
// throw `TypeError` here because it would be incompatible with old API
if (typeof arguments[0] === 'number') {
port = arguments[0];
}
if (typeof arguments[1] === 'string') {
host = arguments[1];
}
}
options = util._extend({ port: port, host: host }, options || {});
if (typeof arguments[arguments.length - 1] === 'function') {
cb = arguments[arguments.length - 1];
}
var args = normalizeConnectArgs(arguments);
var options = args[0];
var cb = args[1];
var socket = options.socket ? options.socket : new net.Stream();
@ -1269,11 +1259,12 @@ exports.connect = function(/* [port, host], options, cb */) {
}
if (!options.socket) {
socket.connect({
var connect_opt = (options.path && !options.port) ? {path: options.path} : {
port: options.port,
host: options.host,
localAddress: options.localAddress
});
};
socket.connect(connect_opt);
}
pair.on('secure', function() {

Просмотреть файл

@ -560,6 +560,10 @@
};
startup.processSignalHandlers = function() {
// Not supported on Windows.
if (process.platform === 'win32')
return;
// Load events module in order to access prototype elements on process like
// process.addListener.
var signalWraps = {};

Просмотреть файл

@ -942,23 +942,20 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
}
p->servername_ = Persistent<String>::New(String::New(servername));
// Call sniCallback_ and use it's return value as context
if (!p->sniCallback_.IsEmpty()) {
// Call the SNI callback and use its return value as context
if (!p->sniObject_.IsEmpty()) {
if (!p->sniContext_.IsEmpty()) {
p->sniContext_.Dispose();
}
// Get callback init args
Local<Value> argv[1] = {*p->servername_};
Local<Function> callback = *p->sniCallback_;
// Call it
//
// XXX There should be an object connected to this that
// we can attach a domain onto.
Local<Value> ret;
ret = Local<Value>::New(MakeCallback(Context::GetCurrent()->Global(),
callback, ARRAY_SIZE(argv), argv));
Local<Value> ret = Local<Value>::New(MakeCallback(p->sniObject_,
"onselect",
ARRAY_SIZE(argv),
argv));
// If ret is SecureContext
if (secure_context_constructor->HasInstance(ret)) {
@ -1778,11 +1775,11 @@ Handle<Value> Connection::SetSNICallback(const Arguments& args) {
}
// Release old handle
if (!ss->sniCallback_.IsEmpty()) {
ss->sniCallback_.Dispose();
if (!ss->sniObject_.IsEmpty()) {
ss->sniObject_.Dispose();
}
ss->sniCallback_ = Persistent<Function>::New(
Local<Function>::Cast(args[0]));
ss->sniObject_ = Persistent<Object>::New(Object::New());
ss->sniObject_->Set(String::New("onselect"), args[0]);
return True();
}
@ -4207,7 +4204,7 @@ struct pbkdf2_req {
size_t iter;
char* key;
size_t keylen;
Persistent<Function> callback;
Persistent<Object> obj;
};
@ -4253,13 +4250,10 @@ void EIO_PBKDF2After(uv_work_t* work_req) {
HandleScope scope;
Local<Value> argv[2];
Persistent<Function> cb = req->callback;
Persistent<Object> obj = req->obj;
EIO_PBKDF2After(req, argv);
// XXX There should be an object connected to this that
// we can attach a domain onto.
MakeCallback(Context::GetCurrent()->Global(), cb, ARRAY_SIZE(argv), argv);
cb.Dispose();
MakeCallback(obj, "ondone", ARRAY_SIZE(argv), argv);
obj.Dispose();
}
@ -4275,7 +4269,6 @@ Handle<Value> PBKDF2(const Arguments& args) {
ssize_t pass_written = -1;
ssize_t salt_written = -1;
ssize_t iter = -1;
Local<Function> callback;
pbkdf2_req* req = NULL;
if (args.Length() != 4 && args.Length() != 5) {
@ -4338,8 +4331,8 @@ Handle<Value> PBKDF2(const Arguments& args) {
req->keylen = keylen;
if (args[4]->IsFunction()) {
callback = Local<Function>::Cast(args[4]);
req->callback = Persistent<Function>::New(callback);
req->obj = Persistent<Object>::New(Object::New());
req->obj->Set(String::New("ondone"), args[4]);
uv_queue_work(uv_default_loop(),
&req->work_req,
EIO_PBKDF2,
@ -4364,7 +4357,7 @@ typedef int (*RandomBytesGenerator)(unsigned char* buf, int size);
struct RandomBytesRequest {
~RandomBytesRequest();
Persistent<Function> callback_;
Persistent<Object> obj_;
unsigned long error_; // openssl error code or zero
uv_work_t work_req_;
size_t size_;
@ -4373,10 +4366,9 @@ struct RandomBytesRequest {
RandomBytesRequest::~RandomBytesRequest() {
if (!callback_.IsEmpty()) {
callback_.Dispose();
callback_.Clear();
}
if (obj_.IsEmpty()) return;
obj_.Dispose();
obj_.Clear();
}
@ -4437,12 +4429,7 @@ void RandomBytesAfter(uv_work_t* work_req) {
HandleScope scope;
Local<Value> argv[2];
RandomBytesCheck(req, argv);
// XXX There should be an object connected to this that
// we can attach a domain onto.
MakeCallback(Context::GetCurrent()->Global(),
req->callback_,
ARRAY_SIZE(argv), argv);
MakeCallback(req->obj_, "ondone", ARRAY_SIZE(argv), argv);
delete req;
}
@ -4467,15 +4454,15 @@ Handle<Value> RandomBytes(const Arguments& args) {
req->size_ = size;
if (args[1]->IsFunction()) {
Local<Function> callback_v = Local<Function>(Function::Cast(*args[1]));
req->callback_ = Persistent<Function>::New(callback_v);
req->obj_ = Persistent<Object>::New(Object::New());
req->obj_->Set(String::New("ondone"), args[1]);
uv_queue_work(uv_default_loop(),
&req->work_req_,
RandomBytesWork<generator>,
RandomBytesAfter<generator>);
return Undefined();
return req->obj_;
}
else {
Local<Value> argv[2];

Просмотреть файл

@ -110,7 +110,7 @@ class Connection : ObjectWrap {
#endif
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
v8::Persistent<v8::Function> sniCallback_;
v8::Persistent<v8::Object> sniObject_;
v8::Persistent<v8::Value> sniContext_;
v8::Persistent<v8::String> servername_;
#endif
@ -185,7 +185,7 @@ class Connection : ObjectWrap {
#endif
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
if (!sniCallback_.IsEmpty()) sniCallback_.Dispose();
if (!sniObject_.IsEmpty()) sniObject_.Dispose();
if (!sniContext_.IsEmpty()) sniContext_.Dispose();
if (!servername_.IsEmpty()) servername_.Dispose();
#endif

3
test/fixtures/child-process-message-and-exit.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
process.send('hello');
process.exit(0);

Просмотреть файл

@ -0,0 +1,106 @@
// 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.
var common = require('../common');
var assert = require('assert');
var spawn = require('child_process').spawn;
var tls = require('tls');
var https = require('https');
var fs = require('fs');
// renegotiation limits to test
var LIMITS = [0, 1, 2, 3, 5, 10, 16];
if (process.platform === 'win32') {
console.log('Skipping test, you probably don\'t have openssl installed.');
process.exit();
}
(function() {
var n = 0;
function next() {
if (n >= LIMITS.length) return;
tls.CLIENT_RENEG_LIMIT = LIMITS[n++];
test(next);
}
next();
})();
function test(next) {
var options = {
cert: fs.readFileSync(common.fixturesDir + '/test_cert.pem'),
key: fs.readFileSync(common.fixturesDir + '/test_key.pem')
};
var seenError = false;
var server = https.createServer(options, function(req, res) {
var conn = req.connection;
conn.on('error', function(err) {
console.error('Caught exception: ' + err);
assert(/TLS session renegotiation attack/.test(err));
conn.destroy();
seenError = true;
});
res.end('ok');
});
server.listen(common.PORT, function() {
var args = ('s_client -connect 127.0.0.1:' + common.PORT).split(' ');
var child = spawn('openssl', args);
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
// count handshakes, start the attack after the initial handshake is done
var handshakes = 0;
var renegs = 0;
child.stderr.on('data', function(data) {
if (seenError) return;
handshakes += (('' + data).match(/verify return:1/g) || []).length;
if (handshakes === 2) spam();
renegs += (('' + data).match(/RENEGOTIATING/g) || []).length;
});
child.on('exit', function() {
assert.equal(renegs, tls.CLIENT_RENEG_LIMIT + 1);
server.close();
process.nextTick(next);
});
var closed = false;
child.stdin.on('error', function(err) {
assert.equal(err.code, 'EPIPE');
closed = true;
});
child.stdin.on('close', function() {
closed = true;
});
// simulate renegotiation attack
function spam() {
if (closed) return;
child.stdin.write('R\n');
setTimeout(spam, 50);
}
});
}

Просмотреть файл

@ -0,0 +1,57 @@
// 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.
var assert = require('assert'),
common = require('../common'),
fork = require('child_process').fork,
fork = require('child_process').fork;
var cp = fork(common.fixturesDir + '/child-process-message-and-exit.js');
var gotMessage = false,
gotExit = false,
gotClose = false;
cp.on('message', function(message) {
assert(!gotMessage);
assert(!gotClose);
assert.strictEqual(message, 'hello');
gotMessage = true;
});
cp.on('exit', function() {
assert(!gotExit);
assert(!gotClose);
gotExit = true;
});
cp.on('close', function() {
assert(gotMessage);
assert(gotExit);
assert(!gotClose);
gotClose = true;
});
process.on('exit', function() {
assert(gotMessage);
assert(gotExit);
assert(gotClose);
});

Просмотреть файл

@ -0,0 +1,37 @@
// 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.
try {
var crypto = require('crypto');
} catch (e) {
console.log('Not compiled with OPENSSL support.');
process.exit();
}
// the missing var keyword is intentional
domain = require('domain');
// should not throw a 'TypeError: undefined is not a function' exception
crypto.randomBytes(8);
crypto.randomBytes(8, function() {});
crypto.pseudoRandomBytes(8);
crypto.pseudoRandomBytes(8, function() {});
crypto.pbkdf2('password', 'salt', 8, 8, function() {});

Просмотреть файл

@ -0,0 +1,49 @@
// 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.
var common = require('../common');
var assert = require('assert');
var tls = require('tls');
var fs = require('fs');
var clientConnected = 0;
var serverConnected = 0;
var options = {
key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem')
};
var server = tls.Server(options, function(socket) {
++serverConnected;
server.close();
});
server.listen(common.PIPE, function() {
var client = tls.connect(common.PIPE, function() {
++clientConnected;
client.end();
});
});
process.on('exit', function() {
assert.equal(clientConnected, 1);
assert.equal(serverConnected, 1);
});