diff --git a/doc/api/dgram.md b/doc/api/dgram.md index 2113cbc442269f..d78d032fb55125 100644 --- a/doc/api/dgram.md +++ b/doc/api/dgram.md @@ -1039,8 +1039,8 @@ changes: * `recvBufferSize` {number} Sets the `SO_RCVBUF` socket value. * `sendBufferSize` {number} Sets the `SO_SNDBUF` socket value. * `lookup` {Function} Custom lookup function. **Default:** [`dns.lookup()`][]. - When the default is used, a literal IP address of the socket's family - resolves to itself without calling [`dns.lookup()`][]. + A literal IP address of the socket's family resolves to itself; the lookup + function is not called for it. * `signal` {AbortSignal} An AbortSignal that may be used to close a socket. * `receiveBlockList` {net.BlockList} `receiveBlockList` can be used for discarding inbound datagram to specific IP addresses, IP ranges, or IP subnets. This does not diff --git a/lib/internal/dgram.js b/lib/internal/dgram.js index 3e477a6a798f9c..a332adaca12cb9 100644 --- a/lib/internal/dgram.js +++ b/lib/internal/dgram.js @@ -19,32 +19,35 @@ const { UV_EINVAL } = internalBinding('uv'); const kStateSymbol = Symbol('state symbol'); let dns; // Lazy load for startup performance. +function lookupOrSkip(lookup, address, family, callback) { + if (isIP(address) === family) { + process.nextTick(callback, null, address, family); + return; + } + return lookup(address, family, callback); +} function lookup4(lookup, address, callback) { - return lookup(address || '127.0.0.1', 4, callback); + if (address) { + return lookupOrSkip(lookup, address, 4, callback); + } + process.nextTick(callback, null, '127.0.0.1', 4); } - function lookup6(lookup, address, callback) { - return lookup(address || '::1', 6, callback); -} - -// A literal IP of the socket's family resolves to itself, so skip dns.lookup(). -// Defer with nextTick to keep the callback async (e.g. bind()'s 'listening'). -function defaultLookup(address, family, callback) { - if (isIP(address) === family) { - process.nextTick(callback, null, address, family); - return; + if (address) { + return lookupOrSkip(lookup, address, 6, callback); } - if (dns === undefined) { - dns = require('dns'); - } - return dns.lookup(address, family, callback); + process.nextTick(callback, null, '::1', 6); } function newHandle(type, lookup) { if (lookup === undefined) { - lookup = defaultLookup; + if (dns === undefined) { + dns = require('dns'); + } + + lookup = dns.lookup; } else { validateFunction(lookup, 'lookup'); } diff --git a/test/parallel/test-dgram-custom-lookup.js b/test/parallel/test-dgram-custom-lookup.js index 7a2bf92187bda8..0dff5e22d29da5 100644 --- a/test/parallel/test-dgram-custom-lookup.js +++ b/test/parallel/test-dgram-custom-lookup.js @@ -9,18 +9,30 @@ const originalLookup = dns.lookup; { // Verify that the provided lookup function is called. const lookup = common.mustCall((host, family, callback) => { - originalLookup(host, family, callback); + assert.strictEqual(host, 'example.invalid'); + callback(null, '127.0.0.1', 4); }); const socket = dgram.createSocket({ type: 'udp4', lookup }); - socket.bind(common.mustCall(() => { + socket.bind(0, 'example.invalid', common.mustCall(() => { + socket.close(); + })); +} + +{ + // IPs resolve to themselves, so a custom lookup is not called. + const lookup = common.mustNotCall('lookup ran for a literal IP address'); + + const socket = dgram.createSocket({ type: 'udp4', lookup }); + + socket.bind(0, '127.0.0.1', common.mustCall(() => { socket.close(); })); } { - // Verify that the default lookup forwards host names to dns.lookup(). + // Verify that lookup defaults to dns.lookup(). dns.lookup = common.mustCall((host, family, callback) => { dns.lookup = originalLookup; assert.strictEqual(host, 'example.invalid');