Repository: denoland/deno
Pull request: fix(ext/node): implement dgram setMulticastLoopback

`npm:multicast-dns` works in Deno now.

Ref https://github.com/denoland/deno/issues/18324


Changed files:
filename: ext/net/01_net.js
patch: @@ -378,14 +378,19 @@ class Listener {
   }
 }
 
-const _setBroadcast = Symbol("setBroadcast");
 const _dropMembership = Symbol("dropMembership");
+const _setBroadcast = Symbol("setBroadcast");
+const _setMultiLoopback = Symbol("setMultiLoopback");
 const _setMulticastTTL = Symbol("setMulticastTTL");
 
 function setDatagramBroadcast(conn, broadcast) {
   return conn[_setBroadcast](broadcast);
 }
 
+function setMulticastLoopback(conn, v6, loopback) {
+  return conn[_setMultiLoopback](v6, loopback);
+}
+
 function dropMembership(conn, v6, addr, multiInterface) {
   return conn[_dropMembership](v6, addr, multiInterface);
 }
@@ -426,6 +431,10 @@ class DatagramConn {
     return op_net_set_multi_ttl_udp(this.#rid, ttl);
   }
 
+  [_setMultiLoopback](v6, loopback) {
+    return op_net_set_multi_loopback_udp(this.#rid, !v6, loopback);
+  }
+
   async joinMulticastV4(addr, multiInterface) {
     await op_net_join_multi_v4_udp(
       this.#rid,
@@ -723,6 +732,7 @@ export {
   listenOptionApiName,
   resolveDns,
   setDatagramBroadcast,
+  setMulticastLoopback,
   setMulticastTTL,
   TcpConn,
   UnixConn,

filename: ext/node/polyfills/internal_binding/udp_wrap.ts
patch: @@ -360,8 +360,17 @@ export class UDP extends HandleWrap {
     notImplemented("udp.UDP.prototype.setMulticastInterface");
   }
 
-  setMulticastLoopback(_bool: 0 | 1): number {
-    notImplemented("udp.UDP.prototype.setMulticastLoopback");
+  setMulticastLoopback(bool: 0 | 1): number {
+    if (!this.#listener) {
+      return codeMap.get("EBADF")!;
+    }
+
+    net.setMulticastLoopback(
+      this.#listener,
+      this.#family === "IPv6",
+      bool === 1,
+    );
+    return 0;
   }
 
   setMulticastTTL(ttl: number): number {

filename: tests/node_compat/config.jsonc
patch: @@ -429,6 +429,7 @@
       "test-dgram-listen-after-bind.js",
       "test-dgram-membership.js",
       "test-dgram-msgsize.js",
+      "test-dgram-multicast-loopback.js",
       "test-dgram-multicast-setTTL.js",
       "test-dgram-oob-buffer.js",
       "test-dgram-recv-error.js",

filename: tests/node_compat/runner/TODO.md
patch: @@ -1,7 +1,7 @@
 <!-- deno-fmt-ignore-file -->
 # Remaining Node Tests
 
-1167 tests out of 3993 have been ported from Node 23.9.0 (29.23% ported, 71.30% remaining).
+1168 tests out of 3993 have been ported from Node 23.9.0 (29.25% ported, 71.27% remaining).
 
 NOTE: This file should not be manually edited. Please edit `tests/node_compat/config.json` and run `deno task setup` in `tests/node_compat/runner` dir instead.
 
@@ -614,7 +614,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
 - [parallel/test-dgram-create-socket-handle.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-create-socket-handle.js)
 - [parallel/test-dgram-deprecation-error.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-deprecation-error.js)
 - [parallel/test-dgram-exclusive-implicit-bind.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-exclusive-implicit-bind.js)
-- [parallel/test-dgram-multicast-loopback.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-multicast-loopback.js)
 - [parallel/test-dgram-multicast-set-interface.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-multicast-set-interface.js)
 - [parallel/test-dgram-reuseport.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-reuseport.js)
 - [parallel/test-dgram-send-address-types.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-dgram-send-address-types.js)

filename: tests/node_compat/test/parallel/test-dgram-multicast-loopback.js
patch: @@ -0,0 +1,30 @@
+// deno-fmt-ignore-file
+// deno-lint-ignore-file
+
+// Copyright Joyent and Node contributors. All rights reserved. MIT license.
+// Taken from Node 23.9.0
+// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
+
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const dgram = require('dgram');
+
+{
+  const socket = dgram.createSocket('udp4');
+
+  assert.throws(() => {
+    socket.setMulticastLoopback(16);
+  }, /^Error: setMulticastLoopback EBADF$/);
+}
+
+{
+  const socket = dgram.createSocket('udp4');
+
+  socket.bind(0);
+  socket.on('listening', common.mustCall(() => {
+    assert.strictEqual(socket.setMulticastLoopback(16), 16);
+    assert.strictEqual(socket.setMulticastLoopback(0), 0);
+    socket.close();
+  }));
+}