1// Flags: --expose-internals 2'use strict'; 3const common = require('../common'); 4if (common.isWindows) 5 common.skip('Does not support binding fd on Windows'); 6 7const assert = require('assert'); 8const dgram = require('dgram'); 9const { internalBinding } = require('internal/test/binding'); 10const { UDP } = internalBinding('udp_wrap'); 11const { UV_UDP_REUSEADDR } = require('os').constants; 12 13const BUFFER_SIZE = 4096; 14 15// Test binding a fd. 16{ 17 function createHandle(reuseAddr, udp4, bindAddress) { 18 let flags = 0; 19 if (reuseAddr) 20 flags |= UV_UDP_REUSEADDR; 21 22 const handle = new UDP(); 23 let err = 0; 24 25 if (udp4) { 26 err = handle.bind(bindAddress, 0, flags); 27 } else { 28 err = handle.bind6(bindAddress, 0, flags); 29 } 30 assert(err >= 0, String(err)); 31 assert.notStrictEqual(handle.fd, -1); 32 return handle; 33 } 34 35 function testWithOptions(reuseAddr, udp4) { 36 const type = udp4 ? 'udp4' : 'udp6'; 37 const bindAddress = udp4 ? common.localhostIPv4 : '::1'; 38 39 let fd; 40 41 const receiver = dgram.createSocket({ 42 type, 43 }); 44 45 receiver.bind({ 46 port: 0, 47 address: bindAddress, 48 }, common.mustCall(() => { 49 const { port, address } = receiver.address(); 50 // Create a handle to reuse its fd. 51 const handle = createHandle(reuseAddr, udp4, bindAddress); 52 53 fd = handle.fd; 54 assert.notStrictEqual(handle.fd, -1); 55 56 const socket = dgram.createSocket({ 57 type, 58 recvBufferSize: BUFFER_SIZE, 59 sendBufferSize: BUFFER_SIZE, 60 }); 61 62 socket.bind({ 63 port: 0, 64 address: bindAddress, 65 fd, 66 }, common.mustCall(() => { 67 // Test address(). 68 const rinfo = {}; 69 const err = handle.getsockname(rinfo); 70 assert.strictEqual(err, 0); 71 const socketRInfo = socket.address(); 72 assert.strictEqual(rinfo.address, socketRInfo.address); 73 assert.strictEqual(rinfo.port, socketRInfo.port); 74 75 // Test buffer size. 76 const recvBufferSize = socket.getRecvBufferSize(); 77 const sendBufferSize = socket.getSendBufferSize(); 78 79 // note: linux will double the buffer size 80 const expectedBufferSize = common.isLinux ? 81 BUFFER_SIZE * 2 : BUFFER_SIZE; 82 assert.strictEqual(recvBufferSize, expectedBufferSize); 83 assert.strictEqual(sendBufferSize, expectedBufferSize); 84 85 socket.send(String(fd), port, address); 86 })); 87 88 socket.on('message', common.mustCall((data) => { 89 assert.strictEqual(data.toString('utf8'), String(fd)); 90 socket.close(); 91 })); 92 93 socket.on('error', (err) => { 94 console.error(err.message); 95 assert.fail(err.message); 96 }); 97 98 socket.on('close', common.mustCall()); 99 })); 100 101 receiver.on('message', common.mustCall((data, { address, port }) => { 102 assert.strictEqual(data.toString('utf8'), String(fd)); 103 receiver.send(String(fd), port, address); 104 process.nextTick(() => receiver.close()); 105 })); 106 107 receiver.on('error', (err) => { 108 console.error(err.message); 109 assert.fail(err.message); 110 }); 111 112 receiver.on('close', common.mustCall()); 113 } 114 115 testWithOptions(true, true); 116 testWithOptions(false, true); 117 if (common.hasIPv6) { 118 testWithOptions(false, false); 119 } 120} 121