11cb0ef41Sopenharmony_ci// Flags: --expose-internals
21cb0ef41Sopenharmony_ci'use strict';
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciif (common.isWindows)
51cb0ef41Sopenharmony_ci  common.skip('Does not support binding fd on Windows');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst assert = require('assert');
81cb0ef41Sopenharmony_ciconst dgram = require('dgram');
91cb0ef41Sopenharmony_ciconst { internalBinding } = require('internal/test/binding');
101cb0ef41Sopenharmony_ciconst { UDP } = internalBinding('udp_wrap');
111cb0ef41Sopenharmony_ciconst { UV_UDP_REUSEADDR } = require('os').constants;
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciconst BUFFER_SIZE = 4096;
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci// Test binding a fd.
161cb0ef41Sopenharmony_ci{
171cb0ef41Sopenharmony_ci  function createHandle(reuseAddr, udp4, bindAddress) {
181cb0ef41Sopenharmony_ci    let flags = 0;
191cb0ef41Sopenharmony_ci    if (reuseAddr)
201cb0ef41Sopenharmony_ci      flags |= UV_UDP_REUSEADDR;
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci    const handle = new UDP();
231cb0ef41Sopenharmony_ci    let err = 0;
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci    if (udp4) {
261cb0ef41Sopenharmony_ci      err = handle.bind(bindAddress, 0, flags);
271cb0ef41Sopenharmony_ci    } else {
281cb0ef41Sopenharmony_ci      err = handle.bind6(bindAddress, 0, flags);
291cb0ef41Sopenharmony_ci    }
301cb0ef41Sopenharmony_ci    assert(err >= 0, String(err));
311cb0ef41Sopenharmony_ci    assert.notStrictEqual(handle.fd, -1);
321cb0ef41Sopenharmony_ci    return handle;
331cb0ef41Sopenharmony_ci  }
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  function testWithOptions(reuseAddr, udp4) {
361cb0ef41Sopenharmony_ci    const type = udp4 ? 'udp4' : 'udp6';
371cb0ef41Sopenharmony_ci    const bindAddress = udp4 ? common.localhostIPv4 : '::1';
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci    let fd;
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci    const receiver = dgram.createSocket({
421cb0ef41Sopenharmony_ci      type,
431cb0ef41Sopenharmony_ci    });
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci    receiver.bind({
461cb0ef41Sopenharmony_ci      port: 0,
471cb0ef41Sopenharmony_ci      address: bindAddress,
481cb0ef41Sopenharmony_ci    }, common.mustCall(() => {
491cb0ef41Sopenharmony_ci      const { port, address } = receiver.address();
501cb0ef41Sopenharmony_ci      // Create a handle to reuse its fd.
511cb0ef41Sopenharmony_ci      const handle = createHandle(reuseAddr, udp4, bindAddress);
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci      fd = handle.fd;
541cb0ef41Sopenharmony_ci      assert.notStrictEqual(handle.fd, -1);
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci      const socket = dgram.createSocket({
571cb0ef41Sopenharmony_ci        type,
581cb0ef41Sopenharmony_ci        recvBufferSize: BUFFER_SIZE,
591cb0ef41Sopenharmony_ci        sendBufferSize: BUFFER_SIZE,
601cb0ef41Sopenharmony_ci      });
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci      socket.bind({
631cb0ef41Sopenharmony_ci        port: 0,
641cb0ef41Sopenharmony_ci        address: bindAddress,
651cb0ef41Sopenharmony_ci        fd,
661cb0ef41Sopenharmony_ci      }, common.mustCall(() => {
671cb0ef41Sopenharmony_ci        // Test address().
681cb0ef41Sopenharmony_ci        const rinfo = {};
691cb0ef41Sopenharmony_ci        const err = handle.getsockname(rinfo);
701cb0ef41Sopenharmony_ci        assert.strictEqual(err, 0);
711cb0ef41Sopenharmony_ci        const socketRInfo = socket.address();
721cb0ef41Sopenharmony_ci        assert.strictEqual(rinfo.address, socketRInfo.address);
731cb0ef41Sopenharmony_ci        assert.strictEqual(rinfo.port, socketRInfo.port);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci        // Test buffer size.
761cb0ef41Sopenharmony_ci        const recvBufferSize = socket.getRecvBufferSize();
771cb0ef41Sopenharmony_ci        const sendBufferSize = socket.getSendBufferSize();
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci        // note: linux will double the buffer size
801cb0ef41Sopenharmony_ci        const expectedBufferSize = common.isLinux ?
811cb0ef41Sopenharmony_ci          BUFFER_SIZE * 2 : BUFFER_SIZE;
821cb0ef41Sopenharmony_ci        assert.strictEqual(recvBufferSize, expectedBufferSize);
831cb0ef41Sopenharmony_ci        assert.strictEqual(sendBufferSize, expectedBufferSize);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci        socket.send(String(fd), port, address);
861cb0ef41Sopenharmony_ci      }));
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci      socket.on('message', common.mustCall((data) => {
891cb0ef41Sopenharmony_ci        assert.strictEqual(data.toString('utf8'), String(fd));
901cb0ef41Sopenharmony_ci        socket.close();
911cb0ef41Sopenharmony_ci      }));
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci      socket.on('error', (err) => {
941cb0ef41Sopenharmony_ci        console.error(err.message);
951cb0ef41Sopenharmony_ci        assert.fail(err.message);
961cb0ef41Sopenharmony_ci      });
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci      socket.on('close', common.mustCall());
991cb0ef41Sopenharmony_ci    }));
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci    receiver.on('message', common.mustCall((data, { address, port }) => {
1021cb0ef41Sopenharmony_ci      assert.strictEqual(data.toString('utf8'), String(fd));
1031cb0ef41Sopenharmony_ci      receiver.send(String(fd), port, address);
1041cb0ef41Sopenharmony_ci      process.nextTick(() => receiver.close());
1051cb0ef41Sopenharmony_ci    }));
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci    receiver.on('error', (err) => {
1081cb0ef41Sopenharmony_ci      console.error(err.message);
1091cb0ef41Sopenharmony_ci      assert.fail(err.message);
1101cb0ef41Sopenharmony_ci    });
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci    receiver.on('close', common.mustCall());
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  testWithOptions(true, true);
1161cb0ef41Sopenharmony_ci  testWithOptions(false, true);
1171cb0ef41Sopenharmony_ci  if (common.hasIPv6) {
1181cb0ef41Sopenharmony_ci    testWithOptions(false, false);
1191cb0ef41Sopenharmony_ci  }
1201cb0ef41Sopenharmony_ci}
121