Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions doc/api/dgram.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 19 additions & 16 deletions lib/internal/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}
Expand Down
18 changes: 15 additions & 3 deletions test/parallel/test-dgram-custom-lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
Loading