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