DeutschGitHub
prototypepackages/mdns/src

mDNS

@ralphschuler/mdns

Provides a deterministic local discovery model and an explicitly started multicast adapter.

multicastDNS-SDLAN discovery

01 · Problem

What is it for?

Discovery can produce several delayed answers; it is not a one-request/one-response RPC.

02 · Mental model

How should you think about it?

Announcements create discoverable records owned by a publisher. Queries collect matching records until a deadline.

In this repository

Provides a deterministic local discovery model and an explicitly started multicast adapter. MDNS verifies TTL and cleanup locally; NetworkMDNS collects delayed network answers through multicast-dns. CI uses an injected transport; interface selection and cross-machine reliability remain integration work.

03 · Control flow

What happens in which order?

  1. Publish a typed service record.
  2. Match queries by name and record type.
  3. Collect all matching answers.
  4. Expire records by TTL.
  5. Remove owned records on shutdown.

04 · Building blocks

The important contracts

MDNS.query / announce / destroyDiscover matching local records, publish them and remove owned records.
DNSRecord / DNSTypeDescribe supported record data and query types.

05 · Build it yourself

Implement a small core

Start with this small independent implementation, then use the steps below to make its contract explicit.

  1. Publish a typed service record.
  2. Match queries by name and record type.
  3. Collect all matching answers.
  4. Expire records by TTL.
  5. Remove owned records on shutdown.
Concept sketch · may reference omitted helpers
async function query(name: string, type: string, signal: AbortSignal) {
  const answers: unknown[] = [];
  const onResponse = (packet: any) => {
    for (const record of [...packet.answers, ...packet.additionals]) {
      if (record.name === name && (type === "ANY" || record.type === type)) {
        answers.push(record);
      }
    }
  };
  socket.on("response", onResponse);
  try { socket.query({ questions: [{ name, type }] }); await delay(500, signal); }
  finally { socket.off("response", onResponse); }
  return deduplicate(answers);
}

06 · Verify

What should you test?

  • Discover multiple publishers without duplicates.
  • Test TTL expiry and publisher shutdown.
  • Test transport timeouts using an injected clock or adapter.

Try it yourself

Turn the first verification claim into a failing test, implement the smallest fix, then add a boundary case.

Discover multiple publishers without duplicates.

Compare your approach

Your check should fail when the stated invariant is deliberately broken, and pass again after the fix. Keep setup deterministic and assert an observable result.

07 · Limits

Trade-offs and failure modes

  • The in-process core cannot discover another machine.
  • Real multicast needs interface selection and socket cleanup.
  • TTL is part of the discovery contract.
Important

MDNS verifies TTL and cleanup locally; NetworkMDNS collects delayed network answers through multicast-dns. CI uses an injected transport; interface selection and cross-machine reliability remain integration work.

08 · Keep exploring

Source code and related ideas

yarn tsx packages/mdns/examples/basic.ts