summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorOuyang Yadong <oyydoibh@gmail.com>2018-07-29 22:41:11 +0800
committerMatteo Collina <hello@matteocollina.com>2018-08-06 11:05:51 +0200
commit2bea9cefbc10ed1dd497bbae61c07d971da287dd (patch)
tree02bfcbc3fcf39fe7524f9271762617f23e107925 /test
parent214844ea4e561b0f77e97643d28b251cdc574089 (diff)
downloadandroid-node-v8-2bea9cefbc10ed1dd497bbae61c07d971da287dd.tar.gz
android-node-v8-2bea9cefbc10ed1dd497bbae61c07d971da287dd.tar.bz2
android-node-v8-2bea9cefbc10ed1dd497bbae61c07d971da287dd.zip
dgram: implement socket.bind({ fd })
dgram: Implement binding an existing `fd`. Allow pass a `fd` property to `socket.bind()` in dgram. src: Add `UDPWrap::Open` PR-URL: https://github.com/nodejs/node/pull/21745 Fixes: https://github.com/nodejs/node/issues/14961 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'test')
-rw-r--r--test/parallel/test-cluster-dgram-bind-fd.js108
-rw-r--r--test/parallel/test-dgram-bind-fd-error.js55
-rw-r--r--test/parallel/test-dgram-bind-fd.js118
-rw-r--r--test/parallel/test-dgram-create-socket-handle-fd.js42
-rw-r--r--test/parallel/test-dgram-create-socket-handle.js8
5 files changed, 323 insertions, 8 deletions
diff --git a/test/parallel/test-cluster-dgram-bind-fd.js b/test/parallel/test-cluster-dgram-bind-fd.js
new file mode 100644
index 0000000000..429f932608
--- /dev/null
+++ b/test/parallel/test-cluster-dgram-bind-fd.js
@@ -0,0 +1,108 @@
+'use strict';
+const common = require('../common');
+if (common.isWindows)
+ common.skip('dgram clustering is currently not supported on Windows.');
+
+const NUM_WORKERS = 4;
+const PACKETS_PER_WORKER = 10;
+
+const assert = require('assert');
+const cluster = require('cluster');
+const dgram = require('dgram');
+const { UDP } = process.binding('udp_wrap');
+
+if (cluster.isMaster)
+ master();
+else
+ worker();
+
+
+function master() {
+ // Create a handle and use its fd.
+ const rawHandle = new UDP();
+ const err = rawHandle.bind(common.localhostIPv4, 0, 0);
+ assert(err >= 0, String(err));
+ assert.notStrictEqual(rawHandle.fd, -1);
+
+ const fd = rawHandle.fd;
+
+ let listening = 0;
+
+ // Fork 4 workers.
+ for (let i = 0; i < NUM_WORKERS; i++)
+ cluster.fork();
+
+ // Wait until all workers are listening.
+ cluster.on('listening', common.mustCall((worker, address) => {
+ if (++listening < NUM_WORKERS)
+ return;
+
+ // Start sending messages.
+ const buf = Buffer.from('hello world');
+ const socket = dgram.createSocket('udp4');
+ let sent = 0;
+ doSend();
+
+ function doSend() {
+ socket.send(buf, 0, buf.length, address.port, address.address, afterSend);
+ }
+
+ function afterSend() {
+ sent++;
+ if (sent < NUM_WORKERS * PACKETS_PER_WORKER) {
+ doSend();
+ } else {
+ socket.close();
+ }
+ }
+ }, NUM_WORKERS));
+
+ // Set up event handlers for every worker. Each worker sends a message when
+ // it has received the expected number of packets. After that it disconnects.
+ for (const key in cluster.workers) {
+ if (cluster.workers.hasOwnProperty(key))
+ setupWorker(cluster.workers[key]);
+ }
+
+ function setupWorker(worker) {
+ let received = 0;
+
+ worker.send({
+ fd,
+ });
+
+ worker.on('message', common.mustCall((msg) => {
+ received = msg.received;
+ worker.disconnect();
+ }));
+
+ worker.on('exit', common.mustCall(() => {
+ assert.strictEqual(received, PACKETS_PER_WORKER);
+ }));
+ }
+}
+
+
+function worker() {
+ let received = 0;
+
+ process.on('message', common.mustCall((data) => {
+ const { fd } = data;
+ // Create udp socket and start listening.
+ const socket = dgram.createSocket('udp4');
+
+ socket.on('message', common.mustCall((data, info) => {
+ received++;
+
+ // Every 10 messages, notify the master.
+ if (received === PACKETS_PER_WORKER) {
+ process.send({ received });
+ socket.close();
+ }
+ }, PACKETS_PER_WORKER));
+
+ socket.bind({
+ fd,
+ });
+ }));
+}
diff --git a/test/parallel/test-dgram-bind-fd-error.js b/test/parallel/test-dgram-bind-fd-error.js
new file mode 100644
index 0000000000..efe0e43d7b
--- /dev/null
+++ b/test/parallel/test-dgram-bind-fd-error.js
@@ -0,0 +1,55 @@
+// Flags: --expose-internals
+'use strict';
+const common = require('../common');
+if (common.isWindows)
+ common.skip('Does not support binding fd on Windows');
+
+const dgram = require('dgram');
+const assert = require('assert');
+const { kStateSymbol } = require('internal/dgram');
+const { TCP, constants } = process.binding('tcp_wrap');
+const TYPE = 'udp4';
+
+// Throw when the fd is occupied according to https://github.com/libuv/libuv/pull/1851.
+{
+ const socket = dgram.createSocket(TYPE);
+
+ socket.bind(common.mustCall(() => {
+ const anotherSocket = dgram.createSocket(TYPE);
+ const { handle } = socket[kStateSymbol];
+
+ common.expectsError(() => {
+ anotherSocket.bind({
+ fd: handle.fd,
+ });
+ }, {
+ code: 'EEXIST',
+ type: Error,
+ message: /^open EEXIST$/
+ });
+
+ socket.close();
+ }));
+}
+
+// Throw when the type of fd is not "UDP".
+{
+ const handle = new TCP(constants.SOCKET);
+ handle.listen();
+
+ const fd = handle.fd;
+ assert.notStrictEqual(fd, -1);
+
+ const socket = new dgram.createSocket(TYPE);
+ common.expectsError(() => {
+ socket.bind({
+ fd,
+ });
+ }, {
+ code: 'ERR_INVALID_FD_TYPE',
+ type: TypeError,
+ message: /^Unsupported fd type: TCP$/
+ });
+
+ handle.close();
+}
diff --git a/test/parallel/test-dgram-bind-fd.js b/test/parallel/test-dgram-bind-fd.js
new file mode 100644
index 0000000000..c4a80abb92
--- /dev/null
+++ b/test/parallel/test-dgram-bind-fd.js
@@ -0,0 +1,118 @@
+'use strict';
+const common = require('../common');
+if (common.isWindows)
+ common.skip('Does not support binding fd on Windows');
+
+const assert = require('assert');
+const dgram = require('dgram');
+const { UDP } = process.binding('udp_wrap');
+const { UV_UDP_REUSEADDR } = process.binding('constants').os;
+
+const BUFFER_SIZE = 4096;
+
+// Test binding a fd.
+{
+ function createHandle(reuseAddr, udp4, bindAddress) {
+ let flags = 0;
+ if (reuseAddr)
+ flags |= UV_UDP_REUSEADDR;
+
+ const handle = new UDP();
+ let err = 0;
+
+ if (udp4) {
+ err = handle.bind(bindAddress, 0, flags);
+ } else {
+ err = handle.bind6(bindAddress, 0, flags);
+ }
+ assert(err >= 0, String(err));
+ assert.notStrictEqual(handle.fd, -1);
+ return handle;
+ }
+
+ function testWithOptions(reuseAddr, udp4) {
+ const type = udp4 ? 'udp4' : 'udp6';
+ const bindAddress = udp4 ? common.localhostIPv4 : '::1';
+
+ let fd;
+
+ const receiver = dgram.createSocket({
+ type,
+ });
+
+ receiver.bind({
+ port: 0,
+ address: bindAddress,
+ }, common.mustCall(() => {
+ const { port, address } = receiver.address();
+ // Create a handle to reuse its fd.
+ const handle = createHandle(reuseAddr, udp4, bindAddress);
+
+ fd = handle.fd;
+ assert.notStrictEqual(handle.fd, -1);
+
+ const socket = dgram.createSocket({
+ type,
+ recvBufferSize: BUFFER_SIZE,
+ sendBufferSize: BUFFER_SIZE,
+ });
+
+ socket.bind({
+ port: 0,
+ address: bindAddress,
+ fd,
+ }, common.mustCall(() => {
+ // Test address().
+ const rinfo = {};
+ const err = handle.getsockname(rinfo);
+ assert.strictEqual(err, 0);
+ const socketRInfo = socket.address();
+ assert.strictEqual(rinfo.address, socketRInfo.address);
+ assert.strictEqual(rinfo.port, socketRInfo.port);
+
+ // Test buffer size.
+ const recvBufferSize = socket.getRecvBufferSize();
+ const sendBufferSize = socket.getSendBufferSize();
+
+ // note: linux will double the buffer size
+ const expectedBufferSize = common.isLinux ?
+ BUFFER_SIZE * 2 : BUFFER_SIZE;
+ assert.strictEqual(recvBufferSize, expectedBufferSize);
+ assert.strictEqual(sendBufferSize, expectedBufferSize);
+
+ socket.send(String(fd), port, address);
+ }));
+
+ socket.on('message', common.mustCall((data) => {
+ assert.strictEqual(data.toString('utf8'), String(fd));
+ socket.close();
+ }));
+
+ socket.on('error', (err) => {
+ console.error(err.message);
+ assert.fail(err.message);
+ });
+
+ socket.on('close', common.mustCall(() => {}));
+ }));
+
+ receiver.on('message', common.mustCall((data, { address, port }) => {
+ assert.strictEqual(data.toString('utf8'), String(fd));
+ receiver.send(String(fd), port, address);
+ process.nextTick(() => receiver.close());
+ }));
+
+ receiver.on('error', (err) => {
+ console.error(err.message);
+ assert.fail(err.message);
+ });
+
+ receiver.on('close', common.mustCall(() => {}));
+ }
+
+ testWithOptions(true, true);
+ testWithOptions(false, true);
+ if (common.hasIPv6) {
+ testWithOptions(false, false);
+ }
+}
diff --git a/test/parallel/test-dgram-create-socket-handle-fd.js b/test/parallel/test-dgram-create-socket-handle-fd.js
new file mode 100644
index 0000000000..ff507b6ec5
--- /dev/null
+++ b/test/parallel/test-dgram-create-socket-handle-fd.js
@@ -0,0 +1,42 @@
+'use strict';
+const common = require('../common');
+if (common.isWindows)
+ common.skip('Does not support binding fd on Windows');
+
+const assert = require('assert');
+const dgram = require('dgram');
+const { UDP } = process.binding('udp_wrap');
+const { TCP, constants } = process.binding('tcp_wrap');
+const _createSocketHandle = dgram._createSocketHandle;
+
+// Return a negative number if the "existing fd" is invalid.
+{
+ const err = _createSocketHandle(common.localhostIPv4, 0, 'udp4', 42);
+ assert(err < 0);
+}
+
+// Return a negative number if the type of fd is not "UDP".
+{
+ // Create a handle with fd.
+ const rawHandle = new UDP();
+ const err = rawHandle.bind(common.localhostIPv4, 0, 0);
+ assert(err >= 0, String(err));
+ assert.notStrictEqual(rawHandle.fd, -1);
+
+ const handle = _createSocketHandle(null, 0, 'udp4', rawHandle.fd);
+ assert(handle instanceof UDP);
+ assert.strictEqual(typeof handle.fd, 'number');
+ assert(handle.fd > 0);
+}
+
+// Create a bound handle.
+{
+ const rawHandle = new TCP(constants.SOCKET);
+ const err = rawHandle.listen();
+ assert(err >= 0, String(err));
+ assert.notStrictEqual(rawHandle.fd, -1);
+
+ const handle = _createSocketHandle(null, 0, 'udp4', rawHandle.fd);
+ assert(handle < 0);
+ rawHandle.close();
+}
diff --git a/test/parallel/test-dgram-create-socket-handle.js b/test/parallel/test-dgram-create-socket-handle.js
index e49e3e8dd6..3df34a95c2 100644
--- a/test/parallel/test-dgram-create-socket-handle.js
+++ b/test/parallel/test-dgram-create-socket-handle.js
@@ -5,14 +5,6 @@ const assert = require('assert');
const { _createSocketHandle } = require('internal/dgram');
const UDP = process.binding('udp_wrap').UDP;
-// Throws if an "existing fd" is passed in.
-common.expectsError(() => {
- _createSocketHandle(common.localhostIPv4, 0, 'udp4', 42);
-}, {
- code: 'ERR_ASSERTION',
- message: /^false == true$/
-});
-
{
// Create a handle that is not bound.
const handle = _createSocketHandle(null, null, 'udp4');