From 14b10c40ac113c01d3831266388daf962fe7f02c Mon Sep 17 00:00:00 2001 From: Rafael Henrique Moreira Date: Sat, 25 May 2013 04:01:25 +0000 Subject: [PATCH 1/8] doc: remove broken links on community page Links to Node Manual and Node Bits both are broken, so this commit removes them from the community page. --- doc/community/index.html | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/community/index.html b/doc/community/index.html index e47182d59e..efc4308dd1 100644 --- a/doc/community/index.html +++ b/doc/community/index.html @@ -54,14 +54,6 @@ Official API docs detail the node API.

-

- Node Manual offers - stylized API docs, as well as tutorials and live code samples -

-

- Node Bits provides sample - Node.js projects -

docs.nodejitsu.com answers many of the common problems people come across. From 28f4c15eb49e9b7f1a430f39f0f930c38adeff60 Mon Sep 17 00:00:00 2001 From: Rafael Henrique Moreira Date: Sat, 25 May 2013 03:49:49 +0000 Subject: [PATCH 2/8] doc: add link to Brazilian Node community Add a link to the Brazilian community portal. --- doc/community/index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/community/index.html b/doc/community/index.html index efc4308dd1..5451b86141 100644 --- a/doc/community/index.html +++ b/doc/community/index.html @@ -179,9 +179,11 @@ OctoberSkyJs Korea Node.js community
FR . Node.js - Google+ Community of Node.js French users + Google+ Community of Node.js French users
Node.js Türkiye - Node.js in Turkish + Node.js in Turkish
+ NodeBR.com + Brazilian community of Node.js

From fa170dd2b241bc0f22f88071158686075c3b269e Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Tue, 28 May 2013 17:50:38 +0400 Subject: [PATCH 3/8] tls: ignore .shutdown() syscall error Quote from SSL_shutdown man page: The output of SSL_get_error(3) may be misleading, as an erroneous SSL_ERROR_SYSCALL may be flagged even though no error occurred. Also, handle all other errors to prevent assertion in `ClearError()`. --- lib/tls.js | 6 ++++++ src/node_crypto.cc | 45 +++++++++++++++++++++++++++++++++++---------- src/node_crypto.h | 7 ++++++- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/lib/tls.js b/lib/tls.js index 7bf0ca1886..4441bd1d65 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -282,8 +282,14 @@ function onCryptoStreamFinish() { // NOTE: first call checks if client has sent us shutdown, // second call enqueues shutdown into the BIO. if (this.pair.ssl.shutdown() !== 1) { + if (this.pair.ssl && this.pair.ssl.error) + return this.pair.error(); + this.pair.ssl.shutdown(); } + + if (this.pair.ssl && this.pair.ssl.error) + return this.pair.error(); } } else { debug('encrypted.onfinish'); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 93f88202f7..b5b5ae41ba 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -915,7 +915,10 @@ int Connection::HandleBIOError(BIO *bio, const char* func, int rv) { } -int Connection::HandleSSLError(const char* func, int rv, ZeroStatus zs) { +int Connection::HandleSSLError(const char* func, + int rv, + ZeroStatus zs, + SyscallStatus ss) { ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence unused variable warning. @@ -940,6 +943,9 @@ int Connection::HandleSSLError(const char* func, int rv, ZeroStatus zs) { Exception::Error(String::New("ZERO_RETURN"))); return rv; + } else if ((err == SSL_ERROR_SYSCALL) && (ss == kIgnoreSyscall)) { + return 0; + } else { HandleScope scope; BUF_MEM* mem; @@ -1372,17 +1378,26 @@ Handle Connection::ClearOut(const Arguments& args) { if (ss->is_server_) { rv = SSL_accept(ss->ssl_); - ss->HandleSSLError("SSL_accept:ClearOut", rv, kZeroIsAnError); + ss->HandleSSLError("SSL_accept:ClearOut", + rv, + kZeroIsAnError, + kSyscallError); } else { rv = SSL_connect(ss->ssl_); - ss->HandleSSLError("SSL_connect:ClearOut", rv, kZeroIsAnError); + ss->HandleSSLError("SSL_connect:ClearOut", + rv, + kZeroIsAnError, + kSyscallError); } if (rv < 0) return scope.Close(Integer::New(rv)); } int bytes_read = SSL_read(ss->ssl_, buffer_data + off, len); - ss->HandleSSLError("SSL_read:ClearOut", bytes_read, kZeroIsNotAnError); + ss->HandleSSLError("SSL_read:ClearOut", + bytes_read, + kZeroIsNotAnError, + kSyscallError); ss->SetShutdownFlags(); return scope.Close(Integer::New(bytes_read)); @@ -1472,10 +1487,16 @@ Handle Connection::ClearIn(const Arguments& args) { int rv; if (ss->is_server_) { rv = SSL_accept(ss->ssl_); - ss->HandleSSLError("SSL_accept:ClearIn", rv, kZeroIsAnError); + ss->HandleSSLError("SSL_accept:ClearIn", + rv, + kZeroIsAnError, + kSyscallError); } else { rv = SSL_connect(ss->ssl_); - ss->HandleSSLError("SSL_connect:ClearIn", rv, kZeroIsAnError); + ss->HandleSSLError("SSL_connect:ClearIn", + rv, + kZeroIsAnError, + kSyscallError); } if (rv < 0) return scope.Close(Integer::New(rv)); @@ -1485,7 +1506,8 @@ Handle Connection::ClearIn(const Arguments& args) { ss->HandleSSLError("SSL_write:ClearIn", bytes_written, - len == 0 ? kZeroIsNotAnError : kZeroIsAnError); + len == 0 ? kZeroIsNotAnError : kZeroIsAnError, + kSyscallError); ss->SetShutdownFlags(); return scope.Close(Integer::New(bytes_written)); @@ -1725,10 +1747,13 @@ Handle Connection::Start(const Arguments& args) { int rv; if (ss->is_server_) { rv = SSL_accept(ss->ssl_); - ss->HandleSSLError("SSL_accept:Start", rv, kZeroIsAnError); + ss->HandleSSLError("SSL_accept:Start", rv, kZeroIsAnError, kSyscallError); } else { rv = SSL_connect(ss->ssl_); - ss->HandleSSLError("SSL_connect:Start", rv, kZeroIsAnError); + ss->HandleSSLError("SSL_connect:Start", + rv, + kZeroIsAnError, + kSyscallError); } return scope.Close(Integer::New(rv)); @@ -1745,7 +1770,7 @@ Handle Connection::Shutdown(const Arguments& args) { if (ss->ssl_ == NULL) return False(); int rv = SSL_shutdown(ss->ssl_); - ss->HandleSSLError("SSL_shutdown", rv, kZeroIsNotAnError); + ss->HandleSSLError("SSL_shutdown", rv, kZeroIsNotAnError, kIgnoreSyscall); ss->SetShutdownFlags(); return scope.Close(Integer::New(rv)); diff --git a/src/node_crypto.h b/src/node_crypto.h index 80262ba3ab..f1f6334b24 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -218,7 +218,12 @@ class Connection : ObjectWrap { kZeroIsAnError }; - int HandleSSLError(const char* func, int rv, ZeroStatus zs); + enum SyscallStatus { + kIgnoreSyscall, + kSyscallError + }; + + int HandleSSLError(const char* func, int rv, ZeroStatus zs, SyscallStatus ss); void ClearError(); void SetShutdownFlags(); From 4f14221f03516b30ea4fba3117f7f9e169ac82da Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Mon, 27 May 2013 14:44:33 +0400 Subject: [PATCH 4/8] tls: invoke write cb only after opposite read end Stream's `._write()` callback should be invoked only after it's opposite stream has finished processing incoming data, otherwise `finish` event fires too early and connection might be closed while there's some data to send to the client. see #5544 --- lib/tls.js | 96 +++++++++++++++------ test/simple/test-tls-client-destroy-soon.js | 75 ++++++++++++++++ 2 files changed, 144 insertions(+), 27 deletions(-) create mode 100644 test/simple/test-tls-client-destroy-soon.js diff --git a/lib/tls.js b/lib/tls.js index 4441bd1d65..5335a3a2fe 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -254,6 +254,8 @@ function CryptoStream(pair, options) { this._pendingCallback = null; this._doneFlag = false; this._retryAfterPartial = false; + this._halfRead = false; + this._sslOutCb = null; this._resumingSession = false; this._reading = true; this._destroyed = false; @@ -319,6 +321,19 @@ function onCryptoStreamEnd() { } +// NOTE: Called once `this._opposite` is set. +CryptoStream.prototype.init = function init() { + var self = this; + this._opposite.on('sslOutEnd', function() { + if (self._sslOutCb) { + var cb = self._sslOutCb; + self._sslOutCb = null; + cb(null); + } + }); +}; + + CryptoStream.prototype._write = function write(data, encoding, cb) { assert(this._pending === null); @@ -347,28 +362,36 @@ CryptoStream.prototype._write = function write(data, encoding, cb) { return cb(this.pair.error(true)); } + // Whole buffer was written + if (written === data.length) { + if (this === this.pair.cleartext) { + debug('cleartext.write succeed with ' + written + ' bytes'); + } else { + debug('encrypted.write succeed with ' + written + ' bytes'); + } + + // Invoke callback only when all data read from opposite stream + if (this._opposite._halfRead) { + assert(this._sslOutCb === null); + this._sslOutCb = cb; + } else { + cb(null); + } + } + // Force SSL_read call to cycle some states/data inside OpenSSL this.pair.cleartext.read(0); // Cycle encrypted data - if (this.pair.encrypted._internallyPendingBytes()) { + if (this.pair.encrypted._internallyPendingBytes()) this.pair.encrypted.read(0); - } // Get NPN and Server name when ready this.pair.maybeInitFinished(); - // Whole buffer was written if (written === data.length) { - if (this === this.pair.cleartext) { - debug('cleartext.write succeed with ' + data.length + ' bytes'); - } else { - debug('encrypted.write succeed with ' + data.length + ' bytes'); - } - - return cb(null); - } - if (written !== 0 && written !== -1) { + return; + } else if (written !== 0 && written !== -1) { assert(!this._retryAfterPartial); this._retryAfterPartial = true; this._write(data.slice(written), encoding, cb); @@ -470,25 +493,42 @@ CryptoStream.prototype._read = function read(size) { this._opposite._done(); // EOF - return this.push(null); + this.push(null); + } else { + // Bail out + this.push(''); } - - // Bail out - return this.push(''); + } else { + // Give them requested data + if (this.ondata) { + var self = this; + this.ondata(pool, start, start + bytesRead); + + // Consume data automatically + // simple/test-https-drain fails without it + process.nextTick(function() { + self.read(bytesRead); + }); + } + this.push(pool.slice(start, start + bytesRead)); } - // Give them requested data - if (this.ondata) { - var self = this; - this.ondata(pool, start, start + bytesRead); + // Let users know that we've some internal data to read + var halfRead = this._internallyPendingBytes() !== 0; - // Consume data automatically - // simple/test-https-drain fails without it - process.nextTick(function() { - self.read(bytesRead); - }); + // Smart check to avoid invoking 'sslOutEnd' in the most of the cases + if (this._halfRead !== halfRead) { + this._halfRead = halfRead; + + // Notify listeners about internal data end + if (this === this.pair.cleartext) { + debug('cleartext.sslOutEnd'); + } else { + debug('encrypted.sslOutEnd'); + } + + this.emit('sslOutEnd'); } - return this.push(pool.slice(start, start + bytesRead)); }; @@ -600,7 +640,7 @@ CryptoStream.prototype.destroySoon = function(err) { if (this.writable) this.end(); - if (this._writableState.finished) + if (this._writableState.finished && this._opposite._ended) this.destroy(); else this.once('finish', this.destroy); @@ -870,6 +910,8 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized, /* Let streams know about each other */ this.cleartext._opposite = this.encrypted; this.encrypted._opposite = this.cleartext; + this.cleartext.init(); + this.encrypted.init(); process.nextTick(function() { /* The Connection may be destroyed by an abort call */ diff --git a/test/simple/test-tls-client-destroy-soon.js b/test/simple/test-tls-client-destroy-soon.js new file mode 100644 index 0000000000..529b84a734 --- /dev/null +++ b/test/simple/test-tls-client-destroy-soon.js @@ -0,0 +1,75 @@ +// 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. + +// Create an ssl server. First connection, validate that not resume. +// Cache session and close connection. Use session on second connection. +// ASSERT resumption. + +if (!process.versions.openssl) { + console.error('Skipping because node compiled without OpenSSL.'); + process.exit(0); +} + +var common = require('../common'); +var assert = require('assert'); +var tls = require('tls'); +var fs = require('fs'); + +var options = { + key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem') +}; + +var big = new Buffer(2 * 1024 * 1024); +var connections = 0; +var bytesRead = 0; + +big.fill('Y'); + +// create server +var server = tls.createServer(options, function(socket) { + socket.end(big); + socket.destroySoon(); + connections++; +}); + +// start listening +server.listen(common.PORT, function() { + var client = tls.connect({ + port: common.PORT, + rejectUnauthorized: false + }, function() { + client.on('readable', function() { + var d = client.read(); + if (d) + bytesRead += d.length; + }); + + client.on('end', function() { + server.close(); + }); + }); +}); + +process.on('exit', function() { + assert.equal(1, connections); + assert.equal(big.length, bytesRead); +}); From f523f7041dc8c2b3c2e9be35b437ffa486f952a7 Mon Sep 17 00:00:00 2001 From: isaacs Date: Tue, 28 May 2013 12:10:14 -0700 Subject: [PATCH 5/8] uv: Upgrade to v0.10.9 --- deps/uv/ChangeLog | 15 ++++++++++++++- deps/uv/src/unix/core.c | 9 +++++++-- deps/uv/src/unix/stream.c | 25 ++++++++++++++++++------- deps/uv/src/uv-common.h | 3 +++ deps/uv/src/version.c | 2 +- 5 files changed, 43 insertions(+), 11 deletions(-) diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 356a5b10b1..1451180c8c 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,17 @@ -2013.05.25, Version 0.10.8 (Stable) +2013.05.29, Version 0.10.9 (Stable) + +Changes since version 0.10.8: + +* unix: fix stream refcounting buglet (Ben Noordhuis) + +* unix: remove erroneous asserts (Ben Noordhuis) + +* unix: add uv__is_closing() macro (Ben Noordhuis) + +* unix: stop stream POLLOUT watcher on write error (Ben Noordhuis) + + +2013.05.25, Version 0.10.8 (Stable), 0f39be12926fe2d8766a9f025797a473003e6504 Changes since version 0.10.7: diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 7ab9bd6c7d..61d7249301 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -162,7 +162,12 @@ void uv__make_close_pending(uv_handle_t* handle) { static void uv__finish_close(uv_handle_t* handle) { - assert(!uv__is_active(handle)); + /* Note: while the handle is in the UV_CLOSING state now, it's still possible + * for it to be active in the sense that uv__is_active() returns true. + * A good example is when the user calls uv_shutdown(), immediately followed + * by uv_close(). The handle is considered active at this point because the + * completion of the shutdown req is still pending. + */ assert(handle->flags & UV_CLOSING); assert(!(handle->flags & UV_CLOSED)); handle->flags |= UV_CLOSED; @@ -220,7 +225,7 @@ static void uv__run_closing_handles(uv_loop_t* loop) { int uv_is_closing(const uv_handle_t* handle) { - return handle->flags & (UV_CLOSING | UV_CLOSED); + return uv__is_closing(handle); } diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index aeefa2c419..52972d9cef 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -429,6 +429,11 @@ void uv__stream_destroy(uv_stream_t* stream) { } if (stream->shutdown_req) { + /* The UV_ECANCELED error code is a lie, the shutdown(2) syscall is a + * fait accompli at this point. Maybe we should revisit this in v0.11. + * A possible reason for leaving it unchanged is that it informs the + * callee that the handle has been destroyed. + */ uv__req_unregister(stream->loop, stream->shutdown_req); uv__set_artificial_error(stream->loop, UV_ECANCELED); stream->shutdown_req->cb(stream->shutdown_req, -1); @@ -627,8 +632,6 @@ static void uv__drain(uv_stream_t* stream) { uv_shutdown_t* req; assert(ngx_queue_empty(&stream->write_queue)); - assert(stream->write_queue_size == 0); - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); /* Shutdown? */ @@ -722,10 +725,8 @@ start: assert(uv__stream_fd(stream) >= 0); - if (ngx_queue_empty(&stream->write_queue)) { - assert(stream->write_queue_size == 0); + if (ngx_queue_empty(&stream->write_queue)) return; - } q = ngx_queue_head(&stream->write_queue); req = ngx_queue_data(q, uv_write_t, queue); @@ -797,6 +798,9 @@ start: /* Error */ req->error = errno; uv__write_req_finish(req); + uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT); + if (!uv__io_active(&stream->io_watcher, UV__POLLIN)) + uv__handle_stop(stream); return; } else if (stream->flags & UV_STREAM_BLOCKING) { /* If this is a blocking stream, try again. */ @@ -1200,6 +1204,12 @@ int uv_write2(uv_write_t* req, return uv__set_artificial_error(stream->loop, UV_EBADF); } + /* It's legal for write_queue_size > 0 even when the write_queue is empty; + * it means there are error-state requests in the write_completed_queue that + * will touch up write_queue_size later, see also uv__write_req_finish(). + * We chould check that write_queue is empty instead but that implies making + * a write() syscall when we know that the handle is in error mode. + */ empty_queue = (stream->write_queue_size == 0); /* Initialize the req */ @@ -1318,9 +1328,10 @@ int uv_read_stop(uv_stream_t* stream) { stream->shutdown_req != NULL || stream->connect_req != NULL); - uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); - uv__handle_stop(stream); stream->flags &= ~UV_STREAM_READING; + uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN); + if (!uv__io_active(&stream->io_watcher, UV__POLLOUT)) + uv__handle_stop(stream); #if defined(__APPLE__) /* Notify select() thread about state change */ diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index 80c9c7193f..bbf2485929 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -149,6 +149,9 @@ void uv__fs_poll_close(uv_fs_poll_t* handle); #define uv__is_active(h) \ (((h)->flags & UV__HANDLE_ACTIVE) != 0) +#define uv__is_closing(h) \ + (((h)->flags & (UV_CLOSING | UV_CLOSED)) != 0) + #define uv__handle_start(h) \ do { \ assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index 98765533db..9bf92fdd02 100644 --- a/deps/uv/src/version.c +++ b/deps/uv/src/version.c @@ -34,7 +34,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 10 -#define UV_VERSION_PATCH 8 +#define UV_VERSION_PATCH 9 #define UV_VERSION_IS_RELEASE 1 From 30cb9fec918112b07b695e4830b8aa0b43fa3ac5 Mon Sep 17 00:00:00 2001 From: "Daniel G. Taylor" Date: Wed, 15 May 2013 13:14:20 -0600 Subject: [PATCH 6/8] tls: Add `secureProtocol` docs Add `secureProtocol` parameter docs to the tls.connect method. --- doc/api/tls.markdown | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/api/tls.markdown b/doc/api/tls.markdown index f89de22059..b9d22d0135 100644 --- a/doc/api/tls.markdown +++ b/doc/api/tls.markdown @@ -274,6 +274,10 @@ Creates a new client connection to the given `port` and `host` (old API) or - `servername`: Servername for SNI (Server Name Indication) TLS extension. + - `secureProtocol`: The SSL method to use, e.g. `SSLv3_method` to force + SSL version 3. The possible values depend on your installation of + OpenSSL and are defined in the constant [SSL_METHODS][]. + The `callback` parameter will be added as a listener for the ['secureConnect'][] event. @@ -560,4 +564,5 @@ The numeric representation of the remote port. For example, `443`. ['secureConnect']: #tls_event_secureconnect [secureConnection]: #tls_event_secureconnection [Stream]: stream.html#stream_stream +[SSL_METHODS]: http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS [tls.Server]: #tls_class_tls_server From 675e85813f2c2083f9b401fadbf1b56c144c986b Mon Sep 17 00:00:00 2001 From: "Daniel G. Taylor" Date: Wed, 15 May 2013 13:16:09 -0600 Subject: [PATCH 7/8] https: Add `secureProtocol` docs Add `secureProtocol` parameter docs to the https.request method. --- doc/api/https.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/api/https.markdown b/doc/api/https.markdown index 9efe2065ea..8f608b1a7a 100644 --- a/doc/api/https.markdown +++ b/doc/api/https.markdown @@ -126,6 +126,9 @@ The following options from [tls.connect()][] can also be specified. However, a the list of supplied CAs. An `'error'` event is emitted if verification fails. Verification happens at the connection level, *before* the HTTP request is sent. Default `true`. +- `secureProtocol`: The SSL method to use, e.g. `SSLv3_method` to force + SSL version 3. The possible values depend on your installation of + OpenSSL and are defined in the constant [SSL_METHODS][]. In order to specify these options, use a custom `Agent`. @@ -207,3 +210,4 @@ Global instance of [https.Agent][] for all HTTPS client requests. [https.request()]: #https_https_request_options_callback [tls.connect()]: tls.html#tls_tls_connect_options_callback [tls.createServer()]: tls.html#tls_tls_createserver_options_secureconnectionlistener +[SSL_METHODS]: http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS From 9826b1549396ed05011d523ab5bf7a344b8cb8b6 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 29 May 2013 16:35:00 +0200 Subject: [PATCH 8/8] doc: sending dgram handles only works on unix --- doc/api/child_process.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/child_process.markdown b/doc/api/child_process.markdown index 85c9c8b8d4..4dfa7d8c6c 100644 --- a/doc/api/child_process.markdown +++ b/doc/api/child_process.markdown @@ -225,7 +225,7 @@ that some connections will be handled by the parent and some by the child. For `dgram` servers the workflow is exactly the same. Here you listen on a `message` event instead of `connection` and use `server.bind` instead of -`server.listen`. +`server.listen`. (Currently only supported on UNIX platforms.) #### Example: sending socket object