• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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