@matterbridge/dgram 3.10.12-dev-20260925-36fa6cb → 3.10.12-dev-20260928-9345dd7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mdns.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import type dgram from 'node:dgram';
2
2
  import { type AnsiLogger } from 'node-ansi-logger';
3
3
  import { Multicast } from './multicast.js';
4
+ export declare const MDNS_MAX_MESSAGE_LENGTH: number;
5
+ export declare const MDNS_MAX_RESOURCE_RECORD_LENGTH: number;
4
6
  export declare enum DnsRecordType {
5
7
  A = 1,
6
8
  NS = 2,
@@ -103,6 +105,18 @@ export declare enum DnsClassFlag {
103
105
  FLUSH = 32768,
104
106
  QU = 32768
105
107
  }
108
+ export declare enum DnsHeaderFlag {
109
+ QR = 32768,
110
+ OPCODE = 30720,
111
+ AA = 1024,
112
+ TC = 512,
113
+ RD = 256,
114
+ RA = 128,
115
+ Z = 64,
116
+ AD = 32,
117
+ CD = 16,
118
+ RCODE = 15
119
+ }
106
120
  export interface MdnsMessage {
107
121
  id: number;
108
122
  qr: number;
@@ -124,8 +138,8 @@ export interface MdnsMessage {
124
138
  }
125
139
  interface DnsQuestion {
126
140
  name: string;
127
- type: number;
128
- class: number;
141
+ type: DnsRecordType;
142
+ class: DnsClass;
129
143
  }
130
144
  interface MdnsRecord {
131
145
  name: string;
@@ -158,11 +172,19 @@ export declare class Mdns extends Multicast {
158
172
  name: string;
159
173
  newOffset: number;
160
174
  };
161
- encodeDnsName(name: string): Buffer;
175
+ encodeDnsName(name: string, compression?: Map<string, number>, offset?: number): Buffer;
162
176
  encodeTxtRdata(txt: string[]): Buffer;
163
177
  encodeSrvRdata(priority: number, weight: number, port: number, target: string): Buffer;
164
178
  encodeA(ipv4: string): Buffer;
165
179
  encodeAAAA(ipv6WithOptionalScope: string): Buffer;
180
+ encodeResourceRecord({ name, rtype, rclass, flush, ttl, rdata }: {
181
+ name: string;
182
+ rtype: number;
183
+ rclass: number;
184
+ flush?: boolean;
185
+ ttl: number;
186
+ rdata: Buffer;
187
+ }, compression?: Map<string, number>, offset?: number): Buffer;
166
188
  decodeResourceRecord(msg: Buffer, offset: number): {
167
189
  record: MdnsRecord;
168
190
  newOffset: number;
@@ -172,11 +194,47 @@ export declare class Mdns extends Multicast {
172
194
  type: number;
173
195
  class: number;
174
196
  unicastResponse?: boolean;
197
+ }[], answers?: {
198
+ name: string;
199
+ rtype: number;
200
+ rclass: number;
201
+ flush?: boolean;
202
+ ttl: number;
203
+ rdata: Buffer;
204
+ }[], authorities?: {
205
+ name: string;
206
+ rtype: number;
207
+ rclass: number;
208
+ flush?: boolean;
209
+ ttl: number;
210
+ rdata: Buffer;
211
+ }[], additionals?: {
212
+ name: string;
213
+ rtype: number;
214
+ rclass: number;
215
+ flush?: boolean;
216
+ ttl: number;
217
+ rdata: Buffer;
175
218
  }[]): Buffer<ArrayBuffer>;
176
219
  sendResponse(answers: {
177
220
  name: string;
178
221
  rtype: number;
179
222
  rclass: number;
223
+ flush?: boolean;
224
+ ttl: number;
225
+ rdata: Buffer;
226
+ }[], authorities?: {
227
+ name: string;
228
+ rtype: number;
229
+ rclass: number;
230
+ flush?: boolean;
231
+ ttl: number;
232
+ rdata: Buffer;
233
+ }[], additionals?: {
234
+ name: string;
235
+ rtype: number;
236
+ rclass: number;
237
+ flush?: boolean;
180
238
  ttl: number;
181
239
  rdata: Buffer;
182
240
  }[]): Buffer<ArrayBuffer>;
package/dist/mdns.js CHANGED
@@ -2,6 +2,8 @@ import { hasParameter } from '@matterbridge/utils/cli';
2
2
  import { getErrorMessage } from '@matterbridge/utils/error';
3
3
  import { BLUE, CYAN, db, GREEN, idn, MAGENTA, nf, rs } from 'node-ansi-logger';
4
4
  import { Multicast } from './multicast.js';
5
+ export const MDNS_MAX_MESSAGE_LENGTH = 1500 - 40 - 8;
6
+ export const MDNS_MAX_RESOURCE_RECORD_LENGTH = MDNS_MAX_MESSAGE_LENGTH - 12;
5
7
  export var DnsRecordType;
6
8
  (function (DnsRecordType) {
7
9
  DnsRecordType[DnsRecordType["A"] = 1] = "A";
@@ -107,6 +109,19 @@ export var DnsClassFlag;
107
109
  DnsClassFlag[DnsClassFlag["FLUSH"] = 32768] = "FLUSH";
108
110
  DnsClassFlag[DnsClassFlag["QU"] = 32768] = "QU";
109
111
  })(DnsClassFlag || (DnsClassFlag = {}));
112
+ export var DnsHeaderFlag;
113
+ (function (DnsHeaderFlag) {
114
+ DnsHeaderFlag[DnsHeaderFlag["QR"] = 32768] = "QR";
115
+ DnsHeaderFlag[DnsHeaderFlag["OPCODE"] = 30720] = "OPCODE";
116
+ DnsHeaderFlag[DnsHeaderFlag["AA"] = 1024] = "AA";
117
+ DnsHeaderFlag[DnsHeaderFlag["TC"] = 512] = "TC";
118
+ DnsHeaderFlag[DnsHeaderFlag["RD"] = 256] = "RD";
119
+ DnsHeaderFlag[DnsHeaderFlag["RA"] = 128] = "RA";
120
+ DnsHeaderFlag[DnsHeaderFlag["Z"] = 64] = "Z";
121
+ DnsHeaderFlag[DnsHeaderFlag["AD"] = 32] = "AD";
122
+ DnsHeaderFlag[DnsHeaderFlag["CD"] = 16] = "CD";
123
+ DnsHeaderFlag[DnsHeaderFlag["RCODE"] = 15] = "RCODE";
124
+ })(DnsHeaderFlag || (DnsHeaderFlag = {}));
110
125
  export function isMdns(message) {
111
126
  if (!message || message.length < 12)
112
127
  return false;
@@ -118,7 +133,7 @@ export function isMdnsQuery(message) {
118
133
  return false;
119
134
  const id = message.readUInt16BE(0);
120
135
  const flags = message.readUInt16BE(2);
121
- const qr = (flags & 0x8000) >> 15;
136
+ const qr = (flags & DnsHeaderFlag.QR) >> 15;
122
137
  return id == 0 && qr === 0;
123
138
  }
124
139
  export function isMdnsResponse(message) {
@@ -126,7 +141,7 @@ export function isMdnsResponse(message) {
126
141
  return false;
127
142
  const id = message.readUInt16BE(0);
128
143
  const flags = message.readUInt16BE(2);
129
- const qr = (flags & 0x8000) >> 15;
144
+ const qr = (flags & DnsHeaderFlag.QR) >> 15;
130
145
  return id == 0 && qr === 1;
131
146
  }
132
147
  export class Mdns extends Multicast {
@@ -196,14 +211,14 @@ export class Mdns extends Multicast {
196
211
  }
197
212
  const id = msg.readUInt16BE(0);
198
213
  const flags = msg.readUInt16BE(2);
199
- const qr = (flags & 0x8000) >> 15;
200
- const opcode = (flags & 0x7800) >> 11;
201
- const aa = Boolean(flags & 0x0400);
202
- const tc = Boolean(flags & 0x0200);
203
- const rd = Boolean(flags & 0x0100);
204
- const ra = Boolean(flags & 0x0080);
205
- const z = (flags & 0x0070) >> 4;
206
- const rcode = flags & 0x000f;
214
+ const qr = (flags & DnsHeaderFlag.QR) >> 15;
215
+ const opcode = (flags & DnsHeaderFlag.OPCODE) >> 11;
216
+ const aa = Boolean(flags & DnsHeaderFlag.AA);
217
+ const tc = Boolean(flags & DnsHeaderFlag.TC);
218
+ const rd = Boolean(flags & DnsHeaderFlag.RD);
219
+ const ra = Boolean(flags & DnsHeaderFlag.RA);
220
+ const z = (flags & (DnsHeaderFlag.Z | DnsHeaderFlag.AD | DnsHeaderFlag.CD)) >> 4;
221
+ const rcode = flags & DnsHeaderFlag.RCODE;
207
222
  const qdCount = msg.readUInt16BE(4);
208
223
  const anCount = msg.readUInt16BE(6);
209
224
  const nsCount = msg.readUInt16BE(8);
@@ -293,13 +308,25 @@ export class Mdns extends Multicast {
293
308
  }
294
309
  return { name: labels.join('.'), newOffset: jumped ? originalOffset : offset };
295
310
  }
296
- encodeDnsName(name) {
311
+ encodeDnsName(name, compression, offset = 0) {
297
312
  const labels = name.split('.');
298
- const buffers = labels.map((label) => {
313
+ const buffers = [];
314
+ let length = 0;
315
+ for (const [index, label] of labels.entries()) {
316
+ if (compression && label !== '') {
317
+ const suffix = labels.slice(index).join('.');
318
+ const pointer = compression.get(suffix);
319
+ if (pointer !== undefined)
320
+ return Buffer.concat([...buffers, Buffer.from([0xc0 | (pointer >> 8), pointer & 0xff])]);
321
+ if (offset + length < 0x4000)
322
+ compression.set(suffix, offset + length);
323
+ }
324
+ const labelBuf = Buffer.from(label, 'utf8');
299
325
  const lenBuf = Buffer.alloc(1);
300
- lenBuf.writeUInt8(label.length, 0);
301
- return Buffer.concat([lenBuf, Buffer.from(label)]);
302
- });
326
+ lenBuf.writeUInt8(labelBuf.length, 0);
327
+ buffers.push(lenBuf, labelBuf);
328
+ length += 1 + labelBuf.length;
329
+ }
303
330
  return Buffer.concat([...buffers, Buffer.from([0])]);
304
331
  }
305
332
  encodeTxtRdata(txt) {
@@ -355,6 +382,28 @@ export class Mdns extends Multicast {
355
382
  return [(word >> 8) & 0xff, word & 0xff];
356
383
  }));
357
384
  }
385
+ encodeResourceRecord({ name, rtype, rclass, flush = false, ttl, rdata }, compression, offset = 0) {
386
+ const rname = this.encodeDnsName(name, compression, offset);
387
+ const nameStart = rtype === DnsRecordType.PTR ? 0 : rtype === DnsRecordType.SRV ? 6 : -1;
388
+ if (compression && nameStart >= 0) {
389
+ let rdataName;
390
+ try {
391
+ rdataName = this.decodeDnsName(rdata, nameStart).name;
392
+ }
393
+ catch {
394
+ rdataName = undefined;
395
+ }
396
+ if (rdataName !== undefined && this.encodeDnsName(rdataName).equals(rdata.subarray(nameStart))) {
397
+ rdata = Buffer.concat([rdata.subarray(0, nameStart), this.encodeDnsName(rdataName, compression, offset + rname.length + 10 + nameStart)]);
398
+ }
399
+ }
400
+ const recordFixed = Buffer.alloc(10);
401
+ recordFixed.writeUInt16BE(rtype, 0);
402
+ recordFixed.writeUInt16BE(flush ? rclass | DnsClassFlag.FLUSH : rclass, 2);
403
+ recordFixed.writeUInt32BE(ttl, 4);
404
+ recordFixed.writeUInt16BE(rdata.length, 8);
405
+ return Buffer.concat([rname, recordFixed, rdata]);
406
+ }
358
407
  decodeResourceRecord(msg, offset) {
359
408
  const nameResult = this.decodeDnsName(msg, offset);
360
409
  const name = nameResult.name;
@@ -451,22 +500,30 @@ export class Mdns extends Multicast {
451
500
  newOffset: offset,
452
501
  };
453
502
  }
454
- sendQuery(questions) {
503
+ sendQuery(questions, answers = [], authorities = [], additionals = []) {
455
504
  const header = Buffer.alloc(12);
456
505
  header.writeUInt16BE(0, 0);
457
506
  header.writeUInt16BE(0, 2);
458
507
  header.writeUInt16BE(questions.length, 4);
459
- header.writeUInt16BE(0, 6);
460
- header.writeUInt16BE(0, 8);
461
- header.writeUInt16BE(0, 10);
508
+ header.writeUInt16BE(answers.length, 6);
509
+ header.writeUInt16BE(authorities.length, 8);
510
+ header.writeUInt16BE(additionals.length, 10);
511
+ const compression = new Map();
512
+ let offset = 12;
462
513
  const questionBuffers = questions.map(({ name, type: qtype, class: qclass, unicastResponse = false }) => {
463
- const qname = this.encodeDnsName(name);
514
+ const qname = this.encodeDnsName(name, compression, offset);
464
515
  const qfields = Buffer.alloc(4);
465
516
  qfields.writeUInt16BE(qtype, 0);
466
517
  qfields.writeUInt16BE(unicastResponse ? qclass | DnsClassFlag.QU : qclass, 2);
518
+ offset += qname.length + 4;
467
519
  return Buffer.concat([qname, qfields]);
468
520
  });
469
- const query = Buffer.concat([header, ...questionBuffers]);
521
+ const recordBuffers = [...answers, ...authorities, ...additionals].map((record) => {
522
+ const recordBuffer = this.encodeResourceRecord(record, compression, offset);
523
+ offset += recordBuffer.length;
524
+ return recordBuffer;
525
+ });
526
+ const query = Buffer.concat([header, ...questionBuffers, ...recordBuffers]);
470
527
  if (hasParameter('v') || hasParameter('verbose')) {
471
528
  const decoded = this.decodeMdnsMessage(query);
472
529
  this.logMdnsMessage(decoded, undefined, `Sending query mDNS message (${query.length} bytes)`);
@@ -483,27 +540,25 @@ export class Mdns extends Multicast {
483
540
  });
484
541
  return query;
485
542
  }
486
- sendResponse(answers) {
543
+ sendResponse(answers, authorities = [], additionals = []) {
487
544
  if (!Array.isArray(answers) || answers.length === 0) {
488
545
  throw new Error('sendResponse requires a non-empty answers array');
489
546
  }
490
547
  const header = Buffer.alloc(12);
491
548
  header.writeUInt16BE(0, 0);
492
- header.writeUInt16BE(0x8400, 2);
549
+ header.writeUInt16BE(DnsHeaderFlag.QR | DnsHeaderFlag.AA, 2);
493
550
  header.writeUInt16BE(0, 4);
494
551
  header.writeUInt16BE(answers.length, 6);
495
- header.writeUInt16BE(0, 8);
496
- header.writeUInt16BE(0, 10);
497
- const answerBuffers = answers.map(({ name, rtype, rclass, ttl, rdata }) => {
498
- const aname = this.encodeDnsName(name);
499
- const answerFixed = Buffer.alloc(10);
500
- answerFixed.writeUInt16BE(rtype, 0);
501
- answerFixed.writeUInt16BE(rclass, 2);
502
- answerFixed.writeUInt32BE(ttl, 4);
503
- answerFixed.writeUInt16BE(rdata.length, 8);
504
- return Buffer.concat([aname, answerFixed, rdata]);
552
+ header.writeUInt16BE(authorities.length, 8);
553
+ header.writeUInt16BE(additionals.length, 10);
554
+ const compression = new Map();
555
+ let offset = 12;
556
+ const recordBuffers = [...answers, ...authorities, ...additionals].map((record) => {
557
+ const recordBuffer = this.encodeResourceRecord(record, compression, offset);
558
+ offset += recordBuffer.length;
559
+ return recordBuffer;
505
560
  });
506
- const response = Buffer.concat([header, ...answerBuffers]);
561
+ const response = Buffer.concat([header, ...recordBuffers]);
507
562
  if (hasParameter('v') || hasParameter('verbose')) {
508
563
  const decoded = this.decodeMdnsMessage(response);
509
564
  this.logMdnsMessage(decoded, undefined, `Sending response mDNS message (${response.length} bytes)`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/dgram",
3
- "version": "3.10.12-dev-20260925-36fa6cb",
3
+ "version": "3.10.12-dev-20260928-9345dd7",
4
4
  "description": "Matterbridge dgram library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -67,7 +67,7 @@
67
67
  "skipTsconfig": true
68
68
  },
69
69
  "dependencies": {
70
- "@matterbridge/utils": "3.10.12-dev-20260925-36fa6cb",
70
+ "@matterbridge/utils": "3.10.12-dev-20260928-9345dd7",
71
71
  "node-ansi-logger": "3.3.1"
72
72
  }
73
73
  }