or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-multicast-dns

Low level multicast-dns implementation in pure javascript

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/multicast-dns@7.2.x

To install, run

npx @tessl/cli install tessl/npm-multicast-dns@7.2.0

index.mddocs/

Multicast DNS

Multicast DNS provides a low-level multicast DNS (mDNS) implementation in pure JavaScript for Node.js applications. It enables service discovery on local networks by implementing the mDNS protocol (RFC 6762) which allows devices to discover services without requiring a centralized DNS server.

Package Information

  • Package Name: multicast-dns
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install multicast-dns

Core Imports

const mdns = require('multicast-dns');

Basic Usage

const mdns = require('multicast-dns')();

// Listen for DNS responses
mdns.on('response', function(response) {
  console.log('got a response packet:', response);
});

// Listen for DNS queries 
mdns.on('query', function(query) {
  console.log('got a query packet:', query);
  
  // Respond to A record queries for 'example.local'
  query.questions.forEach(function(q) {
    if (q.type === 'A' && q.name === 'example.local') {
      mdns.respond({
        answers: [{
          name: 'example.local',
          type: 'A',
          ttl: 300,
          data: '192.168.1.5'
        }]
      });
    }
  });
});

// Query for an A record
mdns.query({
  questions: [{
    name: 'example.local',
    type: 'A'
  }]
});

CLI Interface

The package includes a command-line tool for basic mDNS operations.

Installation for global use:

npm install -g multicast-dns

Usage:

# Query for a hostname (resolve to IP)
multicast-dns example.local
# Output: 192.168.1.5

# Announce a hostname (advertise current machine)
multicast-dns --announce example.local

The CLI tool automatically detects the local IP address for announcements and provides a simple interface for common mDNS operations.

Architecture

Multicast DNS is built around several key components:

  • Factory Function: Main module export creates configured mDNS instances
  • EventEmitter Interface: All instances inherit from Node.js EventEmitter for event-driven communication
  • UDP Socket Management: Handles IPv4/IPv6 multicast socket creation and membership management
  • DNS Packet Processing: Uses dns-packet library for encoding/decoding DNS messages
  • Network Interface Discovery: Automatically discovers and manages multicast group memberships across network interfaces

Capabilities

mDNS Instance Creation

Creates a new multicast DNS instance with configurable network and protocol options.

/**
 * Creates a new multicast DNS instance
 * @param {Object} [options] - Configuration options
 * @param {number} [options.port=5353] - UDP port number
 * @param {string} [options.type='udp4'] - Socket type ('udp4' or 'udp6')
 * @param {string} [options.ip='224.0.0.251'] - Multicast IP address
 * @param {string} [options.host] - Alias for ip option
 * @param {string|string[]} [options.interface] - Network interface(s) to bind to
 * @param {boolean} [options.multicast=true] - Enable multicast functionality
 * @param {number} [options.ttl=255] - Multicast TTL value
 * @param {boolean} [options.loopback=true] - Receive own multicast packets
 * @param {boolean} [options.reuseAddr=true] - Enable SO_REUSEADDR socket option
 * @param {string|boolean} [options.bind] - Bind address or false to disable binding
 * @param {dgram.Socket} [options.socket] - Pre-existing socket to use
 * @returns {EventEmitter} mDNS instance with query/response capabilities
 */
function multicastdns(options)

DNS Query Operations

Send DNS queries to discover services and devices on the local network.

/**
 * Send a DNS query packet
 * @param {string|Object|Object[]} query - Query specification
 * @param {string} [type] - DNS record type when query is a string
 * @param {Object} [rinfo] - Target address information
 * @param {Function} [callback] - Completion callback
 */
mdns.query(query, type, rinfo, callback)

Query Format Options:

// String format with explicit type
mdns.query('example.local', 'A');

// String format with callback (defaults to 'ANY' type)
mdns.query('example.local', callback);

// String format with type and callback
mdns.query('example.local', 'A', callback);

// Array of question objects
mdns.query([{name: 'example.local', type: 'A'}]);

// Full packet object
mdns.query({
  questions: [{name: 'example.local', type: 'A'}]
});

DNS Response Operations

Send DNS responses to advertise services and answer queries from other devices.

/**
 * Send a DNS response packet
 * @param {Object[]|Object} response - Response data
 * @param {Object} [rinfo] - Target address information
 * @param {Function} [callback] - Completion callback
 */
mdns.respond(response, rinfo, callback)

/**
 * Alias for respond method - identical signature
 * @param {Object[]|Object} response - Response data
 * @param {Object} [rinfo] - Target address information
 * @param {Function} [callback] - Completion callback
 */
mdns.response(response, rinfo, callback)

Response Format Options:

// Array of answer records
mdns.respond([{
  name: 'example.local',
  type: 'A', 
  ttl: 300,
  data: '192.168.1.5'
}]);

// Full packet object
mdns.respond({
  answers: [{name: 'example.local', type: 'A', data: '192.168.1.5'}]
});

Packet Transmission

Low-level packet sending for custom DNS operations.

/**
 * Send a raw DNS packet
 * @param {Object} packet - DNS packet object
 * @param {Object} [rinfo] - Target address information
 * @param {Function} [callback] - Completion callback
 */
mdns.send(packet, rinfo, callback)

Instance Management

Control the lifecycle and network configuration of mDNS instances.

/**
 * Destroy the mDNS instance and close the UDP socket
 * @param {Function} [callback] - Completion callback
 */
mdns.destroy(callback)

/**
 * Update multicast group memberships for current network interfaces
 */
mdns.update()

Events

DNS Packet Events

/**
 * Emitted for all incoming DNS packets
 * @param {Object} packet - Decoded DNS packet
 * @param {Object} rinfo - Remote address information
 */
mdns.on('packet', function(packet, rinfo) {})

/**
 * Emitted for incoming DNS query packets
 * @param {Object} query - DNS query packet
 * @param {Object} rinfo - Remote address information  
 */
mdns.on('query', function(query, rinfo) {})

/**
 * Emitted for incoming DNS response packets
 * @param {Object} response - DNS response packet
 * @param {Object} rinfo - Remote address information
 */
mdns.on('response', function(response, rinfo) {})

Lifecycle Events

/**
 * Emitted when the socket is bound and ready to send/receive
 */
mdns.on('ready', function() {})

/**
 * Emitted when network interface memberships are updated
 */
mdns.on('networkInterface', function() {})

Error Events

/**
 * Emitted for critical socket errors (EACCES, EADDRINUSE)
 * @param {Error} error - Error object
 */
mdns.on('error', function(error) {})

/**
 * Emitted for non-critical errors and warnings
 * @param {Error} error - Error object
 */
mdns.on('warning', function(error) {})

Data Structures

DNS Packet Structure

interface DNSPacket {
  type: 'query' | 'response';
  questions: Question[];
  answers: Record[];
  authorities: Record[];
  additionals: Record[];
  flags?: number;
  flag_aa?: boolean;  // Authoritative Answer flag
}

Question Structure

interface Question {
  name: string;      // Domain name (e.g., 'example.local')
  type: string;      // Record type ('A', 'AAAA', 'SRV', 'PTR', 'TXT', 'HINFO', 'ANY')
  class: string;     // Usually 'IN'
}

Record Structure

interface Record {
  name: string;      // Domain name
  type: string;      // Record type
  class: string;     // Usually 'IN'
  ttl: number;       // Time to live in seconds
  data: any;         // Record-specific data (see Record Data Types)
  flush?: boolean;   // Cache flush bit for mDNS
}

Record Data Types

// A Record - IPv4 address
// data: string (e.g., '192.168.1.5')

// AAAA Record - IPv6 address  
// data: string (e.g., 'fe80::5ef9:38ff:fe8c:ceaa')

// SRV Record - Service record
// data: {
//   port: number,      // Service port number
//   target: string,    // Target hostname
//   priority: number,  // Priority value (lower = higher priority)
//   weight: number     // Weight for same priority services
// }

// TXT Record - Text data
// data: Buffer[] | string[]  // Array of text strings or buffers

// PTR Record - Pointer record
// data: string  // Target domain name

// HINFO Record - Host information
// data: {
//   cpu: string,    // CPU type
//   os: string      // Operating system
// }

Remote Info Structure

interface RemoteInfo {
  address: string;  // Remote IP address
  port: number;     // Remote port number
  family: string;   // 'IPv4' or 'IPv6'
  size: number;     // Message size in bytes
}

Usage Examples

Service Discovery

const mdns = require('multicast-dns')();

// Discover all services
mdns.query('_services._dns-sd._udp.local', 'PTR');

mdns.on('response', function(response) {
  response.answers.forEach(function(answer) {
    if (answer.type === 'PTR') {
      console.log('Found service:', answer.data);
    }
  });
});

Service Advertisement

const mdns = require('multicast-dns')();

mdns.on('query', function(query) {
  query.questions.forEach(function(question) {
    if (question.name === '_http._tcp.local' && question.type === 'PTR') {
      mdns.respond({
        answers: [{
          name: '_http._tcp.local',
          type: 'PTR',
          ttl: 120,
          data: 'My Web Server._http._tcp.local'
        }],
        additionals: [{
          name: 'My Web Server._http._tcp.local',
          type: 'SRV',
          ttl: 120,
          data: {
            port: 8080,
            target: 'my-server.local',
            priority: 0,
            weight: 5
          }
        }, {
          name: 'my-server.local',
          type: 'A',
          ttl: 120,
          data: '192.168.1.100'
        }]
      });
    }
  });
});

IPv6 Configuration

Important: IPv6 multicast requires both ip and interface options to be specified or it will throw an error.

const mdns = require('multicast-dns')({
  type: 'udp6',
  ip: 'ff02::fb',        // Required for IPv6
  interface: 'eth0'      // Required for IPv6
});

mdns.query('example.local', 'AAAA');

// This will throw an error:
// const mdns = require('multicast-dns')({type: 'udp6'}); // Missing ip and interface

Custom Network Interface

const mdns = require('multicast-dns')({
  interface: '192.168.1.100',  // Bind to specific interface
  port: 5353
});

// Listen on multiple interfaces
const mdns2 = require('multicast-dns')({
  interface: ['192.168.1.100', '10.0.0.100']
});

Error Handling

The library categorizes errors into critical and non-critical types:

  • Critical errors (emit 'error'): EACCES (permission denied), EADDRINUSE (port in use)
  • Non-critical errors (emit 'warning'): Invalid DNS packets, network interface issues, socket warnings
const mdns = require('multicast-dns')();

mdns.on('error', function(err) {
  console.error('Critical error:', err.message);
  // Handle critical errors - may need to recreate instance
});

mdns.on('warning', function(err) {
  console.warn('Warning:', err.message);
  // Handle warnings - instance continues operating
});