From e61ee49c7a2f577eb1338ee35f8768d79010ebc9 Mon Sep 17 00:00:00 2001 From: Chris Dickinson Date: Fri, 17 Apr 2015 14:52:50 -0700 Subject: [PATCH 01/14] Working on v2.0.0 --- src/node_version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/node_version.h b/src/node_version.h index f629c697fdde03..ee885bc947c3ea 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -1,11 +1,11 @@ #ifndef SRC_NODE_VERSION_H_ #define SRC_NODE_VERSION_H_ -#define NODE_MAJOR_VERSION 1 -#define NODE_MINOR_VERSION 8 +#define NODE_MAJOR_VERSION 2 +#define NODE_MINOR_VERSION 0 #define NODE_PATCH_VERSION 0 -#define NODE_VERSION_IS_RELEASE 1 +#define NODE_VERSION_IS_RELEASE 0 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n) From 68707648fddf104cc7d34309d9a8e29a4e1af152 Mon Sep 17 00:00:00 2001 From: Brendan Ashworth Date: Sat, 18 Apr 2015 11:11:52 -0700 Subject: [PATCH 02/14] doc: update CONTRIBUTING.md This commit: - fixes development branch (v1.x -> master) - updates stability index wording - use iojs binary instead of node PR-URL: https://github.com/iojs/io.js/pull/1466 Reviewed-By: Ben Noordhuis --- CONTRIBUTING.md | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dfb68c43c6d566..d2edd60a0ee245 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,13 +34,8 @@ $ git remote add upstream git://github.com/iojs/io.js.git #### Which branch? -Now decide if you want your feature or bug fix to go into the master branch -or the stable branch. As a rule of thumb, bug fixes go into the stable branch -while new features go into the master branch. - -The stable branch is effectively frozen; patches that change the io.js -API/ABI or affect the run-time behavior of applications get rejected. The -current stable branch is set as the default branch on GitHub. +For developing new features and bug fixes, the `master` branch should be pulled +and built upon. #### Respect the stability index @@ -49,7 +44,7 @@ The rules for the master branch are less strict; consult the In a nutshell, modules are at varying levels of API stability. Bug fixes are always welcome but API or behavioral changes to modules at stability level 3 -and up are off-limits. +(Locked) are off-limits. #### Dependencies @@ -71,12 +66,9 @@ does not align with the project team. Create a feature branch and start hacking: ```text -$ git checkout -b my-feature-branch -t origin/v1.x +$ git checkout -b my-feature-branch -t origin/master ``` -(Where `v1.x` is the latest stable branch as of this writing.) - - ### Step 3: Commit Make sure git knows your name and email address: @@ -123,7 +115,7 @@ Use `git rebase` (not `git merge`) to sync your work from time to time. ```text $ git fetch upstream -$ git rebase upstream/v1.x # or upstream/master +$ git rebase upstream/master ``` @@ -147,10 +139,10 @@ can use this syntax to run it exactly as the test harness would: $ python tools/test.py -v --mode=release parallel/test-stream2-transform ``` -You can run tests directly with node: +You can run tests directly with iojs: ```text -$ node ./test/parallel/test-streams2-transform.js +$ iojs ./test/parallel/test-streams2-transform.js ``` From 718059777c6eb41d930db787eec8748ab35f7deb Mon Sep 17 00:00:00 2001 From: Brendan Ashworth Date: Sat, 18 Apr 2015 13:22:34 -0700 Subject: [PATCH 03/14] Revert "http: don't bother making a copy of the options" This reverts commit 06cfff935012ed2826cac56284cea982630cbc27. Reverted because it introduced a regression where (because options were modified in the later functionality) options.host and options.port would be overridden with values provided in other, supported ways. PR-URL: https://github.com/iojs/io.js/pull/1467 Reviewed-By: Ben Noordhuis --- lib/_http_client.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/_http_client.js b/lib/_http_client.js index daa37ef064e3fc..200a08e5d5bf85 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -21,6 +21,8 @@ function ClientRequest(options, cb) { if (typeof options === 'string') { options = url.parse(options); + } else { + options = util._extend({}, options); } var agent = options.agent; From 6bf85bc81e7e61b4126c50d05555d5928343423b Mon Sep 17 00:00:00 2001 From: Brendan Ashworth Date: Sat, 18 Apr 2015 13:26:15 -0700 Subject: [PATCH 04/14] test: add test for 06cfff9 regression This commit adds a test to ensure all options are NOT modified after passing them to http.request. Specifically options.host and options.port are the most prominent that would previously error, but add the other options that have default values. options.host and options.port were overridden for the one-argument net.createConnection(options) call. PR-URL: https://github.com/iojs/io.js/pull/1467 Reviewed-By: Ben Noordhuis --- ...test-http-request-dont-override-options.js | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 test/parallel/test-http-request-dont-override-options.js diff --git a/test/parallel/test-http-request-dont-override-options.js b/test/parallel/test-http-request-dont-override-options.js new file mode 100644 index 00000000000000..66d82caeac930d --- /dev/null +++ b/test/parallel/test-http-request-dont-override-options.js @@ -0,0 +1,45 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +var requests = 0; + +http.createServer(function(req, res) { + res.writeHead(200); + res.end('ok'); + + requests++; +}).listen(common.PORT).unref(); + +var agent = new http.Agent(); +agent.defaultPort = common.PORT; + +// options marked as explicitly undefined for readability +// in this test, they should STAY undefined as options should not +// be mutable / modified +var options = { + host: undefined, + hostname: common.localhostIPv4, + port: undefined, + defaultPort: undefined, + path: undefined, + method: undefined, + agent: agent +}; + +http.request(options, function(res) { + res.resume(); +}).end(); + +process.on('exit', function() { + assert.equal(requests, 1); + + assert.strictEqual(options.host, undefined); + assert.strictEqual(options.hostname, common.localhostIPv4); + assert.strictEqual(options.port, undefined); + assert.strictEqual(options.defaultPort, undefined); + assert.strictEqual(options.path, undefined); + assert.strictEqual(options.method, undefined); +}); From 26327757f8b342eb91df71f1fdf34a855e29aa71 Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Mon, 20 Apr 2015 18:55:04 +1000 Subject: [PATCH 05/14] doc: update AUTHORS list Update AUTHORS list using tools/update-authors.sh PR-URL: https://github.com/iojs/io.js/pull/1476 Reviewed-By: Ben Noordhuis --- AUTHORS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index a46220775054f6..cd2b3aa983003f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -744,5 +744,8 @@ Giovanny Andres Gongora Granada Jeffrey Jagoda Kelsey Breseman Peter Petrov +Andrew Crites +Marat Abdullin +Dan Varga # Generated by tools/update-authors.sh From b16a328edee8a8e9c86b079525ece0579859e426 Mon Sep 17 00:00:00 2001 From: Nick Raienko Date: Wed, 22 Apr 2015 14:27:04 +0300 Subject: [PATCH 06/14] doc: add spaces to child.kill example PR-URL: https://github.com/iojs/io.js/pull/1503 Reviewed-By: Colin Ihrig Reviewed-By: Evan Lucas --- 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 1ca5cd7fbac6ed..315670581bba4f 100644 --- a/doc/api/child_process.markdown +++ b/doc/api/child_process.markdown @@ -192,7 +192,7 @@ be sent `'SIGTERM'`. See `signal(7)` for a list of available signals. grep = spawn('grep', ['ssh']); grep.on('close', function (code, signal) { - console.log('child process terminated due to receipt of signal '+signal); + console.log('child process terminated due to receipt of signal ' + signal); }); // send SIGHUP to process From 22aafa55971ef762863ec8badcd76228581d40c6 Mon Sep 17 00:00:00 2001 From: Jeremiah Senkpiel Date: Wed, 22 Apr 2015 20:46:06 -0400 Subject: [PATCH 07/14] doc: add Fishrock123 to the TC as per https://github.com/iojs/io.js/issues/1502 PR-URL: https://github.com/iojs/io.js/pull/1507 Reviewed-By: Chris Dickinson Reviewed-By: Ben Noordhuis --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 67164f5725de54..ca5ab327b8ba39 100644 --- a/README.md +++ b/README.md @@ -280,7 +280,7 @@ information about the governance of the io.js project, see - Release GPG key: DD8F2338BAE7501E3DD5AC78C273792F7D83545D * **Thorsten Lorenz** ([@thlorenz](https://github.com/thlorenz)) <thlorenz@gmx.de> * **Stephen Belanger** ([@qard](https://github.com/qard)) <admin@stephenbelanger.com> -* **Jeremiah Senkpiel** ([@fishrock123](https://github.com/fishrock123)) <fishrock123@rocketmail.com> +* **Jeremiah Senkpiel** ([@fishrock123](https://github.com/fishrock123)) <fishrock123@rocketmail.com> (Technical Committee) - Release GPG key: FD3A5288F042B6850C66B31F09FE44734EB7990E * **Evan Lucas** ([@evanlucas](https://github.com/evanlucas)) <evanlucas@me.com> * **Brendan Ashworth** ([@brendanashworth](https://github.com/brendanashworth)) <brendan.ashworth@me.com> From a7d74633f20e285395f5e2860bdac56381603476 Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Tue, 21 Apr 2015 18:24:13 -0300 Subject: [PATCH 08/14] tls_wrap: use localhost if options.host is empty tls.connect(options) with no options.host should accept a certificate with CN: 'localhost'. Fix Error: Hostname/IP doesn't match certificate's altnames: "Host: undefined. is not cert's CN: localhost" 'localhost' is not added directly to defaults because that is not always desired (for example, when using options.socket) PR-URL: https://github.com/iojs/io.js/pull/1493 Fixes: https://github.com/iojs/io.js/issues/1489 Reviewed-By: Brendan Ashworth Reviewed-By: Roman Reiss --- lib/_tls_wrap.js | 3 +- test/parallel/test-tls-connect-no-host.js | 34 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-tls-connect-no-host.js diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 3e091b0fc1be0d..c1037a7096a755 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -858,7 +858,8 @@ exports.connect = function(/* [port, host], options, cb */) { var hostname = options.servername || options.host || - options.socket && options.socket._host, + (options.socket && options.socket._host) || + 'localhost', NPN = {}, context = tls.createSecureContext(options); tls.convertNPNProtocols(options.NPNProtocols, NPN); diff --git a/test/parallel/test-tls-connect-no-host.js b/test/parallel/test-tls-connect-no-host.js new file mode 100644 index 00000000000000..41aac1acabd781 --- /dev/null +++ b/test/parallel/test-tls-connect-no-host.js @@ -0,0 +1,34 @@ +var common = require('../common'); + +if (!common.hasCrypto) { + console.log('1..0 # Skipped: missing crypto'); + process.exit(); +} +var tls = require('tls'); + +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); + +var cert = fs.readFileSync(path.join(common.fixturesDir, 'test_cert.pem')); +var key = fs.readFileSync(path.join(common.fixturesDir, 'test_key.pem')); + +// https://github.com/iojs/io.js/issues/1489 +// tls.connect(options) with no options.host should accept a cert with +// CN:'localhost' +tls.createServer({ + key: key, + cert: cert +}).listen(common.PORT); + +var socket = tls.connect({ + port: common.PORT, + ca: cert, + // No host set here. 'localhost' is the default, + // but tls.checkServerIdentity() breaks before the fix with: + // Error: Hostname/IP doesn't match certificate's altnames: + // "Host: undefined. is not cert's CN: localhost" +}, function() { + assert(socket.authorized); + process.exit(); +}); From 7384ca83f97a28b0cecaabe879e9af0fe8631b62 Mon Sep 17 00:00:00 2001 From: Chris Yip Date: Tue, 21 Apr 2015 15:13:27 +0800 Subject: [PATCH 09/14] module: remove '' from Module.globalPaths If `$NODE_PATH` contains trailing separators, `Module.globalPaths` will contains empty strings. When `Module` try to resolve a module's path, `path.resolve('', 'index.js')` will boil down to `$PWD/index.js`, which makes sub modules can access global modules and get unexpected result. PR-URL: https://github.com/iojs/io.js/pull/1488 Reviewed-By: Roman Reiss --- lib/module.js | 4 +++- test/parallel/test-module-globalpaths-nodepath.js | 8 +++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/module.js b/lib/module.js index 02f0ec700f150d..eba3de81713fe8 100644 --- a/lib/module.js +++ b/lib/module.js @@ -489,7 +489,9 @@ Module._initPaths = function() { var nodePath = process.env['NODE_PATH']; if (nodePath) { - paths = nodePath.split(path.delimiter).concat(paths); + paths = nodePath.split(path.delimiter).filter(function(path) { + return !!path; + }).concat(paths); } modulePaths = paths; diff --git a/test/parallel/test-module-globalpaths-nodepath.js b/test/parallel/test-module-globalpaths-nodepath.js index d0261e81f7a802..6cfa17933ce869 100644 --- a/test/parallel/test-module-globalpaths-nodepath.js +++ b/test/parallel/test-module-globalpaths-nodepath.js @@ -6,20 +6,22 @@ var module = require('module'); var isWindows = process.platform === 'win32'; var partA, partB; +var partC = ''; if (isWindows) { partA = 'C:\\Users\\Rocko Artischocko\\AppData\\Roaming\\npm'; partB = 'C:\\Program Files (x86)\\nodejs\\'; - process.env['NODE_PATH'] = partA + ';' + partB; + process.env['NODE_PATH'] = partA + ';' + partB + ';' + partC; } else { partA = '/usr/test/lib/node_modules'; partB = '/usr/test/lib/node'; - process.env['NODE_PATH'] = partA + ':' + partB; + process.env['NODE_PATH'] = partA + ':' + partB + ':' + partC; } module._initPaths(); assert.ok(module.globalPaths.indexOf(partA) !== -1); assert.ok(module.globalPaths.indexOf(partB) !== -1); +assert.ok(module.globalPaths.indexOf(partC) === -1); -assert.ok(Array.isArray(module.globalPaths)); \ No newline at end of file +assert.ok(Array.isArray(module.globalPaths)); From bb254b533b1bfced8e39661485488f4a3f8969cc Mon Sep 17 00:00:00 2001 From: Roman Reiss Date: Thu, 23 Apr 2015 17:22:38 +0200 Subject: [PATCH 10/14] doc: update branch to master Update the remaining markdown files to refer to the master branch. PR-URL: https://github.com/iojs/io.js/pull/1511 Reviewed-By: Jeremiah Senkpiel --- COLLABORATOR_GUIDE.md | 12 ++++++------ WORKING_GROUPS.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index 20949eeefbab5b..792dbf3d4d668a 100644 --- a/COLLABORATOR_GUIDE.md +++ b/COLLABORATOR_GUIDE.md @@ -119,14 +119,14 @@ $ git rebase --abort Checkout proper target branch ```text -$ git checkout v1.x +$ git checkout master ``` Update the tree ```text $ git fetch origin -$ git merge --ff-only origin/v1.x +$ git merge --ff-only origin/master ``` Apply external patches @@ -138,13 +138,13 @@ $ curl -L https://github.com/iojs/io.js/pull/xxx.patch | git am --whitespace=fix Check and re-review the changes ```text -$ git diff origin/v1.x +$ git diff origin/master ``` Check number of commits and commit messages ```text -$ git log origin/v1.x...v1.x +$ git log origin/master...master ``` If there are multiple commits that relate to the same feature or @@ -152,7 +152,7 @@ one with a feature and separate with a test for that feature - you'll need to squash them (or strictly speaking `fixup`). ```text -$ git rebase -i origin/v1.x +$ git rebase -i origin/master ``` This will open a screen like this (in the default shell editor): @@ -210,7 +210,7 @@ line. Time to push it: ```text -$ git push origin v1.x +$ git push origin master ``` ### I just made a mistake diff --git a/WORKING_GROUPS.md b/WORKING_GROUPS.md index 05cb41e5a97a82..c5c7cc1d746a50 100644 --- a/WORKING_GROUPS.md +++ b/WORKING_GROUPS.md @@ -1,7 +1,7 @@ # io.js Working Groups io.js Working Groups are autonomous projects created by the -[Technical Committee (TC)](https://github.com/iojs/io.js/blob/v1.x/GOVERNANCE.md#technical-committee). +[Technical Committee (TC)](https://github.com/iojs/io.js/blob/master/GOVERNANCE.md#technical-committee). Working Groups can be formed at any time but must be ratified by the TC. Once formed the work defined in the Working Group charter is the From 3d3083b91f02ca14acddde97612cec98e97ffe38 Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Thu, 16 Apr 2015 11:29:02 +0800 Subject: [PATCH 11/14] buffer: little improve for Buffer.concat method When buffer list less than 2, no need to calculate the length. The change's benchmark result is here: https://gist.github.com/JacksonTian/2c9e2bdec00018e010e6 It improve 15% ~ 25% speed when list only have one buffer, to other cases no effect. PR-URL: https://github.com/iojs/io.js/pull/1437 Reviewed-By: Trevor Norris Reviewed-By: Brendan Ashworth --- lib/buffer.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 8f4e34d289fc27..dc2b656d7a7a33 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -247,6 +247,11 @@ Buffer.concat = function(list, length) { if (!Array.isArray(list)) throw new TypeError('list argument must be an Array of Buffers.'); + if (list.length === 0) + return new Buffer(0); + else if (list.length === 1) + return list[0]; + if (length === undefined) { length = 0; for (var i = 0; i < list.length; i++) @@ -255,11 +260,6 @@ Buffer.concat = function(list, length) { length = length >>> 0; } - if (list.length === 0) - return new Buffer(0); - else if (list.length === 1) - return list[0]; - var buffer = new Buffer(length); var pos = 0; for (var i = 0; i < list.length; i++) { From 1bef71747678c19c7214048de5b9e3848889248d Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Wed, 22 Apr 2015 16:46:21 -0500 Subject: [PATCH 12/14] net: cleanup connect logic Separates out the lookup logic for net.Socket. In the event the `host` property is an IP address, the lookup is skipped. PR-URL: https://github.com/iojs/io.js/pull/1505 Reviewed-By: Chris Dickinson Reviewed-By: Yosuke Furukawa --- lib/net.js | 119 ++++++++++++---------- test/parallel/test-net-dns-lookup-skip.js | 18 ++++ test/parallel/test-net-dns-lookup.js | 2 +- 3 files changed, 85 insertions(+), 54 deletions(-) create mode 100644 test/parallel/test-net-dns-lookup-skip.js diff --git a/lib/net.js b/lib/net.js index 847e417e67f4ca..ce2033f9daf101 100644 --- a/lib/net.js +++ b/lib/net.js @@ -881,64 +881,77 @@ Socket.prototype.connect = function(options, cb) { connect(self, options.path); } else { - const dns = require('dns'); - var host = options.host || 'localhost'; - var port = 0; - var localAddress = options.localAddress; - var localPort = options.localPort; - var dnsopts = { - family: options.family, - hints: 0 - }; - - if (localAddress && !exports.isIP(localAddress)) - throw new TypeError('localAddress must be a valid IP: ' + localAddress); - - if (localPort && typeof localPort !== 'number') - throw new TypeError('localPort should be a number: ' + localPort); - - port = options.port; - if (typeof port !== 'undefined') { - if (typeof port !== 'number' && typeof port !== 'string') - throw new TypeError('port should be a number or string: ' + port); - if (!isLegalPort(port)) - throw new RangeError('port should be >= 0 and < 65536: ' + port); - } - port |= 0; + lookupAndConnect(self, options); + } + return self; +}; - if (dnsopts.family !== 4 && dnsopts.family !== 6) - dnsopts.hints = dns.ADDRCONFIG | dns.V4MAPPED; - debug('connect: find host ' + host); - debug('connect: dns options ' + dnsopts); - self._host = host; - dns.lookup(host, dnsopts, function(err, ip, addressType) { - self.emit('lookup', err, ip, addressType); +function lookupAndConnect(self, options) { + const dns = require('dns'); + var host = options.host || 'localhost'; + var port = options.port; + var localAddress = options.localAddress; + var localPort = options.localPort; - // It's possible we were destroyed while looking this up. - // XXX it would be great if we could cancel the promise returned by - // the look up. - if (!self._connecting) return; + if (localAddress && !exports.isIP(localAddress)) + throw new TypeError('localAddress must be a valid IP: ' + localAddress); - if (err) { - // net.createConnection() creates a net.Socket object and - // immediately calls net.Socket.connect() on it (that's us). - // There are no event listeners registered yet so defer the - // error event to the next tick. - process.nextTick(connectErrorNT, self, err, options); - } else { - self._unrefTimer(); - connect(self, - ip, - port, - addressType, - localAddress, - localPort); - } - }); + if (localPort && typeof localPort !== 'number') + throw new TypeError('localPort should be a number: ' + localPort); + + if (typeof port !== 'undefined') { + if (typeof port !== 'number' && typeof port !== 'string') + throw new TypeError('port should be a number or string: ' + port); + if (!isLegalPort(port)) + throw new RangeError('port should be >= 0 and < 65536: ' + port); } - return self; -}; + port |= 0; + + // If host is an IP, skip performing a lookup + // TODO(evanlucas) should we hot path this for localhost? + var addressType = exports.isIP(host); + if (addressType) { + connect(self, host, port, addressType, localAddress, localPort); + return; + } + + var dnsopts = { + family: options.family, + hints: 0 + }; + + if (dnsopts.family !== 4 && dnsopts.family !== 6) + dnsopts.hints = dns.ADDRCONFIG | dns.V4MAPPED; + + debug('connect: find host ' + host); + debug('connect: dns options ' + dnsopts); + self._host = host; + dns.lookup(host, dnsopts, function(err, ip, addressType) { + self.emit('lookup', err, ip, addressType); + + // It's possible we were destroyed while looking this up. + // XXX it would be great if we could cancel the promise returned by + // the look up. + if (!self._connecting) return; + + if (err) { + // net.createConnection() creates a net.Socket object and + // immediately calls net.Socket.connect() on it (that's us). + // There are no event listeners registered yet so defer the + // error event to the next tick. + process.nextTick(connectErrorNT, self, err, options); + } else { + self._unrefTimer(); + connect(self, + ip, + port, + addressType, + localAddress, + localPort); + } + }); +} function connectErrorNT(self, err, options) { diff --git a/test/parallel/test-net-dns-lookup-skip.js b/test/parallel/test-net-dns-lookup-skip.js new file mode 100644 index 00000000000000..7a129b979510b7 --- /dev/null +++ b/test/parallel/test-net-dns-lookup-skip.js @@ -0,0 +1,18 @@ +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); + +function check(addressType) { + var server = net.createServer(function(client) { + client.end(); + server.close(); + }); + + var address = addressType === 4 ? '127.0.0.1' : '::1'; + server.listen(common.PORT, address, function() { + net.connect(common.PORT, address).on('lookup', assert.fail); + }); +} + +check(4); +common.hasIPv6 && check(6); diff --git a/test/parallel/test-net-dns-lookup.js b/test/parallel/test-net-dns-lookup.js index e7c058fe144a56..92ba794d74520c 100644 --- a/test/parallel/test-net-dns-lookup.js +++ b/test/parallel/test-net-dns-lookup.js @@ -9,7 +9,7 @@ var server = net.createServer(function(client) { }); server.listen(common.PORT, '127.0.0.1', function() { - net.connect(common.PORT, '127.0.0.1').on('lookup', function(err, ip, type) { + net.connect(common.PORT, 'localhost').on('lookup', function(err, ip, type) { assert.equal(err, null); assert.equal(ip, '127.0.0.1'); assert.equal(type, '4'); From 4abe2fa1cfcc434952570c1c979dd4ce150fba67 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Wed, 22 Apr 2015 17:05:29 -0500 Subject: [PATCH 13/14] net: add lookup option to Socket.prototype.connect Allows customization of the lookup function used when Socket.prototype.connect is called using a hostname. PR-URL: https://github.com/iojs/io.js/pull/1505 Reviewed-By: Chris Dickinson Reviewed-By: Yosuke Furukawa --- doc/api/net.markdown | 2 ++ lib/net.js | 6 +++- test/parallel/test-net-dns-custom-lookup.js | 40 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-net-dns-custom-lookup.js diff --git a/doc/api/net.markdown b/doc/api/net.markdown index e3ce8fb5863aa0..aadf8a84c1c1a6 100644 --- a/doc/api/net.markdown +++ b/doc/api/net.markdown @@ -355,6 +355,8 @@ For TCP sockets, `options` argument should be an object which specifies: - `localPort`: Local port to bind to for network connections. - `family` : Version of IP stack. Defaults to `4`. + + - `lookup` : Custom lookup function. Defaults to `dns.lookup`. For local domain sockets, `options` argument should be an object which specifies: diff --git a/lib/net.js b/lib/net.js index ce2033f9daf101..867e1df7ccc252 100644 --- a/lib/net.js +++ b/lib/net.js @@ -916,6 +916,9 @@ function lookupAndConnect(self, options) { return; } + if (options.lookup && typeof options.lookup !== 'function') + throw new TypeError('options.lookup should be a function.'); + var dnsopts = { family: options.family, hints: 0 @@ -927,7 +930,8 @@ function lookupAndConnect(self, options) { debug('connect: find host ' + host); debug('connect: dns options ' + dnsopts); self._host = host; - dns.lookup(host, dnsopts, function(err, ip, addressType) { + var lookup = options.lookup || dns.lookup; + lookup(host, dnsopts, function(err, ip, addressType) { self.emit('lookup', err, ip, addressType); // It's possible we were destroyed while looking this up. diff --git a/test/parallel/test-net-dns-custom-lookup.js b/test/parallel/test-net-dns-custom-lookup.js new file mode 100644 index 00000000000000..3979bbf0b6d2c5 --- /dev/null +++ b/test/parallel/test-net-dns-custom-lookup.js @@ -0,0 +1,40 @@ +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var dns = require('dns'); +var ok = false; + +function check(addressType, cb) { + var server = net.createServer(function(client) { + client.end(); + server.close(); + cb && cb(); + }); + + var address = addressType === 4 ? '127.0.0.1' : '::1'; + server.listen(common.PORT, address, function() { + net.connect({ + port: common.PORT, + host: 'localhost', + lookup: lookup + }).on('lookup', function(err, ip, type) { + assert.equal(err, null); + assert.equal(ip, address); + assert.equal(type, addressType); + ok = true; + }); + }); + + function lookup(host, dnsopts, cb) { + dnsopts.family = addressType; + dns.lookup(host, dnsopts, cb); + } +} + +check(4, function() { + common.hasIPv6 && check(6); +}); + +process.on('exit', function() { + assert.ok(ok); +}); From 102a993ade492bfd3a4365fd06371110abe78709 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Wed, 18 Feb 2015 12:02:01 -0600 Subject: [PATCH 14/14] net: persist net.Socket options before connect Remembers net.Socket options called before connect and retroactively applies them after the handle has been created. This change makes the following function calls more user-friendly: - setKeepAlive() - setNoDelay() - ref() - unref() Related: https://github.com/joyent/node/issues/7077 and https://github.com/joyent/node/issues/8572 --- lib/net.js | 31 ++++++++++++--- .../parallel/test-net-persistent-keepalive.js | 32 +++++++++++++++ test/parallel/test-net-persistent-nodelay.js | 33 ++++++++++++++++ .../parallel/test-net-persistent-ref-unref.js | 39 +++++++++++++++++++ 4 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 test/parallel/test-net-persistent-keepalive.js create mode 100644 test/parallel/test-net-persistent-nodelay.js create mode 100644 test/parallel/test-net-persistent-ref-unref.js diff --git a/lib/net.js b/lib/net.js index 867e1df7ccc252..7eb3c8ee72e705 100644 --- a/lib/net.js +++ b/lib/net.js @@ -319,14 +319,25 @@ Socket.prototype._onTimeout = function() { Socket.prototype.setNoDelay = function(enable) { + if (!this._handle) { + this.once('connect', + enable ? this.setNoDelay : this.setNoDelay.bind(this, enable)); + return; + } + // backwards compatibility: assume true when `enable` is omitted - if (this._handle && this._handle.setNoDelay) + if (this._handle.setNoDelay) this._handle.setNoDelay(enable === undefined ? true : !!enable); }; Socket.prototype.setKeepAlive = function(setting, msecs) { - if (this._handle && this._handle.setKeepAlive) + if (!this._handle) { + this.once('connect', this.setKeepAlive.bind(this, setting, msecs)); + return; + } + + if (this._handle.setKeepAlive) this._handle.setKeepAlive(setting, ~~(msecs / 1000)); }; @@ -968,14 +979,22 @@ function connectErrorNT(self, err, options) { Socket.prototype.ref = function() { - if (this._handle) - this._handle.ref(); + if (!this._handle) { + this.once('connect', this.ref); + return; + } + + this._handle.ref(); }; Socket.prototype.unref = function() { - if (this._handle) - this._handle.unref(); + if (!this._handle) { + this.once('connect', this.unref); + return; + } + + this._handle.unref(); }; diff --git a/test/parallel/test-net-persistent-keepalive.js b/test/parallel/test-net-persistent-keepalive.js new file mode 100644 index 00000000000000..86936fd2a517e8 --- /dev/null +++ b/test/parallel/test-net-persistent-keepalive.js @@ -0,0 +1,32 @@ +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); + +var serverConnection; +var echoServer = net.createServer(function(connection) { + serverConnection = connection; + connection.setTimeout(0); + assert.notEqual(connection.setKeepAlive, undefined); + connection.on('end', function() { + connection.end(); + }); +}); +echoServer.listen(common.PORT); + +echoServer.on('listening', function() { + var clientConnection = new net.Socket(); + // send a keepalive packet after 1000 ms + // and make sure it persists + clientConnection.setKeepAlive(true, 400); + clientConnection.connect(common.PORT); + clientConnection.setTimeout(0); + + setTimeout(function() { + // make sure both connections are still open + assert.equal(serverConnection.readyState, 'open'); + assert.equal(clientConnection.readyState, 'open'); + serverConnection.end(); + clientConnection.end(); + echoServer.close(); + }, 600); +}); diff --git a/test/parallel/test-net-persistent-nodelay.js b/test/parallel/test-net-persistent-nodelay.js new file mode 100644 index 00000000000000..791c3b7df7478b --- /dev/null +++ b/test/parallel/test-net-persistent-nodelay.js @@ -0,0 +1,33 @@ +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var TCPWrap = process.binding('tcp_wrap').TCP; + +var echoServer = net.createServer(function(connection) { + connection.end(); +}); +echoServer.listen(common.PORT); + +var setTrue = 0; + +var Socket = net.Socket; +var setNoDelay = TCPWrap.prototype.setNoDelay; + +TCPWrap.prototype.setNoDelay = function(enable) { + setNoDelay.call(this, enable); + setTrue++; +}; + +echoServer.on('listening', function() { + var sock1 = new Socket(); + // setNoDelay before the handle is created + // there is probably a better way to test this + + sock1.setNoDelay(); + sock1.connect(common.PORT); + sock1.on('end', process.exit); +}); + +process.on('exit', function() { + assert.ok(setTrue); +}); diff --git a/test/parallel/test-net-persistent-ref-unref.js b/test/parallel/test-net-persistent-ref-unref.js new file mode 100644 index 00000000000000..0474d0053458ff --- /dev/null +++ b/test/parallel/test-net-persistent-ref-unref.js @@ -0,0 +1,39 @@ +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var TCPWrap = process.binding('tcp_wrap').TCP; + +var echoServer = net.createServer(function(conn) { + conn.end(); +}); + +var ref = TCPWrap.prototype.ref; +var unref = TCPWrap.prototype.unref; + +var refed = false; +var unrefed = false; + +TCPWrap.prototype.ref = function() { + ref.call(this); + refed = true; +}; + +TCPWrap.prototype.unref = function() { + unref.call(this); + unrefed = true; +}; + +echoServer.listen(common.PORT); + +echoServer.on('listening', function() { + var sock = new net.Socket(); + sock.unref(); + sock.ref(); + sock.connect(common.PORT); + sock.on('end', process.exit); +}); + +process.on('exit', function() { + assert.ok(refed); + assert.ok(unrefed); +});