| // Flags: --expose-internals |
| '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 { internalBinding } = require('internal/test/binding'); |
| const { UDP } = internalBinding('udp_wrap'); |
| const { UV_UDP_REUSEADDR } = require('os').constants; |
| |
| 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); |
| } |
| } |