Skip to content

Commit

Permalink
feat: added ServiceDomain and FDQN to Hostname string utility functions
Browse files Browse the repository at this point in the history
  • Loading branch information
amydevs committed Oct 12, 2023
1 parent f4f6c12 commit 4dbbde7
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 17 deletions.
40 changes: 24 additions & 16 deletions src/MDNS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
MulticastSocketInfo,
SocketHostRow,
RemoteInfo,
FDQN,
} from './types';
import type {
CachableResourceRecord,
Expand Down Expand Up @@ -57,10 +58,10 @@ class MDNS {

protected localRecordCache: ResourceRecordCache;
protected localRecordCacheDirty = true;
protected _localServices: Map<Hostname, Service> = new Map();
protected _localServices: Map<FDQN, Service> = new Map();

protected networkRecordCache: ResourceRecordCache;
protected _networkServices: Map<Hostname, Service> = new Map();
protected _networkServices: Map<FDQN, Service> = new Map();
protected sockets: Array<dgram.Socket> = [];
protected socketMap: WeakMap<dgram.Socket, SocketInfo> = new WeakMap();
protected socketHostTable: Table<SocketHostRow> = new Table(
Expand Down Expand Up @@ -140,7 +141,7 @@ class MDNS {
* The Key is a FDQN.
*/
@ready(new errors.ErrorMDNSNotRunning())
public get localServices(): ReadonlyMap<Hostname, Service> {
public get localServices(): ReadonlyMap<FDQN, Service> {
return this._localServices;
}

Expand All @@ -149,7 +150,7 @@ class MDNS {
* The Key is a FDQN.
*/
@ready(new errors.ErrorMDNSNotRunning())
public get networkServices(): ReadonlyMap<Hostname, Service> {
public get networkServices(): ReadonlyMap<FDQN, Service> {
return this._networkServices;
}

Expand Down Expand Up @@ -1003,22 +1004,22 @@ class MDNS {

protected extractRelatedFdqns(
resourceRecords: ResourceRecord | Array<ResourceRecord>,
): Array<Hostname> {
): Array<FDQN> {
if (!Array.isArray(resourceRecords)) {
return this.extractRelatedFdqns([resourceRecords]);
}
const relatedFdqns: Array<Hostname> = [];
const relatedFdqns: Array<FDQN> = [];
for (const resourceRecord of resourceRecords) {
if (
resourceRecord.type === RType.SRV ||
resourceRecord.type === RType.TXT
) {
relatedFdqns.push(resourceRecord.name as Hostname);
relatedFdqns.push(resourceRecord.name as FDQN);
} else if (
resourceRecord.type === RType.PTR &&
resourceRecord.name !== '_services._dns-sd._udp.local'
) {
relatedFdqns.push(resourceRecord.data as Hostname);
relatedFdqns.push(resourceRecord.data as FDQN);
} else if (
resourceRecord.type === RType.A ||
resourceRecord.type === RType.AAAA
Expand All @@ -1029,7 +1030,7 @@ class MDNS {
);
for (const relatedResourceRecord of relatedResourceRecords) {
if (relatedResourceRecord.type === RType.SRV) {
relatedFdqns.push(relatedResourceRecord.name as Hostname);
relatedFdqns.push(relatedResourceRecord.name as FDQN);
}
}
}
Expand Down Expand Up @@ -1160,9 +1161,7 @@ class MDNS {
hostname: this._hostname,
hosts: [],
};
const serviceDomain =
`_${service.type}._${service.protocol}.local` as Hostname;
const fdqn = `${service.name}.${serviceDomain}` as Hostname;
const fdqn = utils.toFdqn(service);

this._localServices.set(fdqn, service);
this.localRecordCacheDirty = true;
Expand Down Expand Up @@ -1200,8 +1199,11 @@ class MDNS {
type: string;
protocol: 'udp' | 'tcp';
}) {
const serviceDomain = `_${type}._${protocol}.local` as Hostname;
const fdqn = `${name}.${serviceDomain}` as Hostname;
const fdqn = utils.toFdqn({
name,
type,
protocol,
});

const foundService = this._localServices.get(fdqn);
if (foundService == null) return;
Expand Down Expand Up @@ -1248,7 +1250,10 @@ class MDNS {
minDelay?: number;
maxDelay?: number;
}) {
const serviceDomain = `_${type}._${protocol}.local` as Hostname;
const serviceDomain = utils.toServiceDomain({
type,
protocol,
});
const questionRecord: QuestionRecord = {
name: serviceDomain,
type: QType.PTR,
Expand Down Expand Up @@ -1329,7 +1334,10 @@ class MDNS {
type: string;
protocol: 'udp' | 'tcp';
}) {
const serviceDomain = `_${type}._${protocol}.local`;
const serviceDomain = utils.toServiceDomain({
type,
protocol,
});
this.queries.get(serviceDomain)?.cancel();
}
}
Expand Down
9 changes: 8 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ type Host = Opaque<'Host', string>;
/**
* Hostnames are resolved to IP addresses
*/
type Hostname = Opaque<'Hostname', string>;
type Hostname = Opaque<'Hostname', string> | FDQN;

/**
* FDQNs are in the format `{service.name}._${service.type}._${service.protocol}.local`.
* FDQNs are also Hostnames.
*/
type FDQN = Opaque<'FDQN', string>;

/**
* Ports are numbers from 0 to 65535
Expand Down Expand Up @@ -122,6 +128,7 @@ export type {
PromiseDeconstructed,
Host,
Hostname,
FDQN,
Port,
Address,
Service,
Expand Down
44 changes: 44 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
Callback,
FDQN,
Host,
Hostname,
NetworkInterfaces,
Expand Down Expand Up @@ -239,6 +240,47 @@ function getRandomPacketId(): number {
return Math.floor(Math.random() * 65535);
}

function toServiceDomain({
type,
protocol,
}: {
type: string;
protocol: 'udp' | 'tcp';
}): Hostname {
return `_${type}._${protocol}.local` as Hostname;
}

function toFdqn({
name,
type,
protocol,
serviceDomain,
}: {
name: string;
} & (
| {
type: string;
protocol: 'udp' | 'tcp';
serviceDomain?: undefined;
}
| {
type?: undefined;
protocol?: undefined;
serviceDomain: Hostname;
}
)): FDQN {
let serviceDomain_: Hostname | undefined;
if (serviceDomain == null) {
serviceDomain_ = toServiceDomain({
type,
protocol,
});
} else {
serviceDomain_ = serviceDomain;
}
return `${name}.${serviceDomain_}` as FDQN;
}

export {
isPort,
isIPv4,
Expand All @@ -254,4 +296,6 @@ export {
toServiceResourceRecords,
bindSocket,
getRandomPacketId,
toServiceDomain,
toFdqn,
};

0 comments on commit 4dbbde7

Please sign in to comment.