From 1c82f8d7968e60127bc542f435e1cbffd564780e Mon Sep 17 00:00:00 2001 From: Wes <3253051+vves@users.noreply.github.com> Date: Wed, 15 Feb 2023 14:11:31 -0700 Subject: [PATCH 01/15] Fix for OSX network interface. set to en0 --- src/Device.ts | 5 +++-- src/util/Platform.ts | 11 +++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/util/Platform.ts diff --git a/src/Device.ts b/src/Device.ts index 979ead19..98782a19 100644 --- a/src/Device.ts +++ b/src/Device.ts @@ -43,6 +43,7 @@ import { AdminCommissioningCluster, CommissioningWindowStatus } from "./matter/c import { AdminCommissioningHandler } from "./matter/cluster/server/AdminCommissioningServer"; import { NetworkCommissioningHandler } from "./matter/cluster/server/NetworkCommissioningServer"; import { FabricIndex } from "./matter/common/FabricIndex"; +import { isMacOSX } from "./util/Platform"; // From Chip-Test-DAC-FFF1-8000-0007-Key.der const DevicePrivateKey = ByteArray.fromHex("727F1005CBA47ED7822A9D930943621617CFD3B79D9AF528B801ECF9F1992204"); @@ -64,7 +65,7 @@ class Device { async start() { logger.info(`node-matter@${packageJson.version}`); - const deviceName = "Matter test device"; + const deviceName = `${isMacOSX()?'OSX':''} Matter test device`; const deviceType = 257 /* Dimmable bulb */; const vendorName = "node-matter"; const passcode = 20202021; @@ -94,7 +95,7 @@ class Device { .addNetInterface(await UdpInterface.create(5540, "udp4")) .addNetInterface(await UdpInterface.create(5540, "udp6")) .addScanner(await MdnsScanner.create()) - .addBroadcaster(await MdnsBroadcaster.create()) + .addBroadcaster(await MdnsBroadcaster.create(isMacOSX()?"en0":undefined)) .addProtocolHandler(secureChannelProtocol) .addProtocolHandler(new InteractionServer() .addEndpoint(0x00, DEVICE.ROOT, [ diff --git a/src/util/Platform.ts b/src/util/Platform.ts new file mode 100644 index 00000000..e5acea20 --- /dev/null +++ b/src/util/Platform.ts @@ -0,0 +1,11 @@ +/** + * Utils for Platform.ts. + * + * @license + * Copyright 2023 The node-matter Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +export function isMacOSX () : boolean { + return process.platform === 'darwin' +} \ No newline at end of file From 799a7de70fa6a1a6471abacae94f2b986cae12e8 Mon Sep 17 00:00:00 2001 From: Wes <3253051+vves@users.noreply.github.com> Date: Thu, 16 Feb 2023 11:00:06 -0700 Subject: [PATCH 02/15] better logging for mdns issue --- src/matter/mdns/MdnsBroadcaster.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/matter/mdns/MdnsBroadcaster.ts b/src/matter/mdns/MdnsBroadcaster.ts index d65a6b09..9bd243c2 100644 --- a/src/matter/mdns/MdnsBroadcaster.ts +++ b/src/matter/mdns/MdnsBroadcaster.ts @@ -30,7 +30,7 @@ export class MdnsBroadcaster implements Broadcaster { ) {} setCommissionMode(mode: number,deviceName: string, deviceType: number, vendorId: VendorId, productId: number, discriminator: number) { - logger.debug(`announce commissioning mode ${mode} ${deviceName} ${deviceType} ${vendorId} ${productId} ${discriminator}`); + logger.debug(`announce commissioning mode ${mode} ${deviceName} ${deviceType} ${vendorId.id} ${productId} ${discriminator}`); const shortDiscriminator = (discriminator >> 8) & 0x0F; const instanceId = Crypto.getRandomData(8).toHex().toUpperCase(); @@ -46,6 +46,8 @@ export class MdnsBroadcaster implements Broadcaster { if (ipMac === undefined) return []; const { mac, ips } = ipMac; const hostname = mac.replace(/:/g, "").toUpperCase() + "0000.local"; + logger.debug(`on IP Addr: ${ips}`) + logger.debug(`using hostname ${hostname}`) const records = [ PtrRecord(SERVICE_DISCOVERY_QNAME, MATTER_COMMISSION_SERVICE_QNAME), PtrRecord(SERVICE_DISCOVERY_QNAME, vendorQname), From ac96697ca30168d972d01a55cb2f116b835cc202 Mon Sep 17 00:00:00 2001 From: Wes <3253051+vves@users.noreply.github.com> Date: Fri, 17 Feb 2023 15:29:16 -0700 Subject: [PATCH 03/15] ease of use package scripts for library consumers --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 013a7db2..85ae28a2 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,9 @@ "scripts": { "clean": "rm -rf build", "build": "npm run clean; tsc", - "test": "TZ=utc mocha" + "test": "TZ=utc mocha", + "device": "npm run build; node build/Device.js", + "list-c-nodes": "dns-sd -B _matterc._udp" }, "devDependencies": { "@types/bn.js": "^5.1.0", From b0f775003b888b85b2917e36bc8f5bf32122ecb9 Mon Sep 17 00:00:00 2001 From: Wes <3253051+vves@users.noreply.github.com> Date: Fri, 17 Feb 2023 15:29:55 -0700 Subject: [PATCH 04/15] mdns should only provide the AAAA record for local IPv6 addresses --- src/matter/mdns/MdnsBroadcaster.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/matter/mdns/MdnsBroadcaster.ts b/src/matter/mdns/MdnsBroadcaster.ts index 9bd243c2..1eba681a 100644 --- a/src/matter/mdns/MdnsBroadcaster.ts +++ b/src/matter/mdns/MdnsBroadcaster.ts @@ -112,7 +112,9 @@ export class MdnsBroadcaster implements Broadcaster { if (isIPv4(ip)) { records.push(ARecord(hostname, ip)); } else { - records.push(AAAARecord(hostname, ip)); + if(ip.startsWith('fe80::')){ // only add the local address + records.push(AAAARecord(hostname, ip)); + } } }); return records; From 9d361c6ebcfa087de8059461337bc4e2e20e38cb Mon Sep 17 00:00:00 2001 From: Wes <3253051+vves@users.noreply.github.com> Date: Fri, 17 Feb 2023 15:30:23 -0700 Subject: [PATCH 05/15] explicitly select the network interface --- src/Device.ts | 17 +++++++++++----- src/util/Platform.ts | 48 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/Device.ts b/src/Device.ts index 98782a19..7a9f866e 100644 --- a/src/Device.ts +++ b/src/Device.ts @@ -43,7 +43,7 @@ import { AdminCommissioningCluster, CommissioningWindowStatus } from "./matter/c import { AdminCommissioningHandler } from "./matter/cluster/server/AdminCommissioningServer"; import { NetworkCommissioningHandler } from "./matter/cluster/server/NetworkCommissioningServer"; import { FabricIndex } from "./matter/common/FabricIndex"; -import { isMacOSX } from "./util/Platform"; +import { Platform } from "./util/Platform"; // From Chip-Test-DAC-FFF1-8000-0007-Key.der const DevicePrivateKey = ByteArray.fromHex("727F1005CBA47ED7822A9D930943621617CFD3B79D9AF528B801ECF9F1992204"); @@ -62,10 +62,10 @@ Network.get = singleton(() => new NetworkNode()); const logger = Logger.get("Device"); class Device { - async start() { + async start(networkInterface : string|undefined = undefined) { logger.info(`node-matter@${packageJson.version}`); - const deviceName = `${isMacOSX()?'OSX':''} Matter test device`; + const deviceName = `Matter test device`; const deviceType = 257 /* Dimmable bulb */; const vendorName = "node-matter"; const passcode = 20202021; @@ -95,7 +95,7 @@ class Device { .addNetInterface(await UdpInterface.create(5540, "udp4")) .addNetInterface(await UdpInterface.create(5540, "udp6")) .addScanner(await MdnsScanner.create()) - .addBroadcaster(await MdnsBroadcaster.create(isMacOSX()?"en0":undefined)) + .addBroadcaster(await MdnsBroadcaster.create(networkInterface)) .addProtocolHandler(secureChannelProtocol) .addProtocolHandler(new InteractionServer() .addEndpoint(0x00, DEVICE.ROOT, [ @@ -198,4 +198,11 @@ class Device { } } -new Device().start(); + +const demo = async () => { + const cli = new Platform() + const selectedInterface = await cli.selectInterface() + new Device().start(selectedInterface); +} + +demo() \ No newline at end of file diff --git a/src/util/Platform.ts b/src/util/Platform.ts index e5acea20..90835a05 100644 --- a/src/util/Platform.ts +++ b/src/util/Platform.ts @@ -6,6 +6,48 @@ * SPDX-License-Identifier: Apache-2.0 */ -export function isMacOSX () : boolean { - return process.platform === 'darwin' -} \ No newline at end of file +import { networkInterfaces } from 'os'; + +export class Platform { + readonly interfaces = networkInterfaces(); + + constructor() { + this.listInterfaces() + } + + private listInterfaces() { + const { interfaces } = this + + console.log('Select a network interface:'); + + Object.keys(interfaces).forEach((interfaceName, index) => { + const addresses = interfaces[interfaceName]!.map((addressInfo) => addressInfo.address); + console.log(`${index + 1}: ${interfaceName} (${addresses.join(', ')})`); + }); + } + + selectInterface(): Promise { + return new Promise((resolve) => { + const { interfaces } = this + const stdin = process.openStdin(); + + stdin.on('data', (data) => { + const choice = parseInt(data.toString().trim(), 10); + + if (isNaN(choice) || choice < 1 || choice > Object.keys(interfaces).length) { + console.error('Invalid choice. Please select a number from the list.'); + return; + } + + const interfaceName = Object.keys(interfaces)[choice - 1]; + const addresses = interfaces[interfaceName]!.map((addressInfo) => addressInfo.address); + + console.log(`Selected interface: ${interfaceName} (${addresses.join(', ')})`); + stdin.removeAllListeners('data'); + stdin.pause(); + resolve(interfaceName); + }) + }) + } +} + From c354a11247e6c51a2df671e04c69d111afe528f2 Mon Sep 17 00:00:00 2001 From: Wes <3253051+vves@users.noreply.github.com> Date: Mon, 20 Feb 2023 18:34:06 -0700 Subject: [PATCH 06/15] code review updates --- package.json | 4 +--- src/Device.ts | 16 +++++-------- src/util/Platform.ts | 53 -------------------------------------------- 3 files changed, 6 insertions(+), 67 deletions(-) delete mode 100644 src/util/Platform.ts diff --git a/package.json b/package.json index 85ae28a2..013a7db2 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,7 @@ "scripts": { "clean": "rm -rf build", "build": "npm run clean; tsc", - "test": "TZ=utc mocha", - "device": "npm run build; node build/Device.js", - "list-c-nodes": "dns-sd -B _matterc._udp" + "test": "TZ=utc mocha" }, "devDependencies": { "@types/bn.js": "^5.1.0", diff --git a/src/Device.ts b/src/Device.ts index 7a9f866e..5a10a04d 100644 --- a/src/Device.ts +++ b/src/Device.ts @@ -26,7 +26,7 @@ import { DEVICE } from "./matter/common/DeviceTypes"; import { MdnsBroadcaster } from "./matter/mdns/MdnsBroadcaster"; import { Network } from "./net/Network"; import { NetworkNode } from "./net/node/NetworkNode"; -import { commandExecutor } from "./util/CommandLine"; +import { commandExecutor, getParameter } from "./util/CommandLine"; import { OnOffCluster } from "./matter/cluster/OnOffCluster"; import { GeneralCommissioningClusterHandler } from "./matter/cluster/server/GeneralCommissioningServer"; import { OperationalCredentialsClusterHandler } from "./matter/cluster/server/OperationalCredentialsServer"; @@ -43,7 +43,6 @@ import { AdminCommissioningCluster, CommissioningWindowStatus } from "./matter/c import { AdminCommissioningHandler } from "./matter/cluster/server/AdminCommissioningServer"; import { NetworkCommissioningHandler } from "./matter/cluster/server/NetworkCommissioningServer"; import { FabricIndex } from "./matter/common/FabricIndex"; -import { Platform } from "./util/Platform"; // From Chip-Test-DAC-FFF1-8000-0007-Key.der const DevicePrivateKey = ByteArray.fromHex("727F1005CBA47ED7822A9D930943621617CFD3B79D9AF528B801ECF9F1992204"); @@ -62,10 +61,10 @@ Network.get = singleton(() => new NetworkNode()); const logger = Logger.get("Device"); class Device { - async start(networkInterface : string|undefined = undefined) { + async start(networkInterface? : string) { logger.info(`node-matter@${packageJson.version}`); - const deviceName = `Matter test device`; + const deviceName = "Matter test device"; const deviceType = 257 /* Dimmable bulb */; const vendorName = "node-matter"; const passcode = 20202021; @@ -198,11 +197,6 @@ class Device { } } +const networkInterface = getParameter("interface"); -const demo = async () => { - const cli = new Platform() - const selectedInterface = await cli.selectInterface() - new Device().start(selectedInterface); -} - -demo() \ No newline at end of file +new Device().start(networkInterface); diff --git a/src/util/Platform.ts b/src/util/Platform.ts deleted file mode 100644 index 90835a05..00000000 --- a/src/util/Platform.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Utils for Platform.ts. - * - * @license - * Copyright 2023 The node-matter Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { networkInterfaces } from 'os'; - -export class Platform { - readonly interfaces = networkInterfaces(); - - constructor() { - this.listInterfaces() - } - - private listInterfaces() { - const { interfaces } = this - - console.log('Select a network interface:'); - - Object.keys(interfaces).forEach((interfaceName, index) => { - const addresses = interfaces[interfaceName]!.map((addressInfo) => addressInfo.address); - console.log(`${index + 1}: ${interfaceName} (${addresses.join(', ')})`); - }); - } - - selectInterface(): Promise { - return new Promise((resolve) => { - const { interfaces } = this - const stdin = process.openStdin(); - - stdin.on('data', (data) => { - const choice = parseInt(data.toString().trim(), 10); - - if (isNaN(choice) || choice < 1 || choice > Object.keys(interfaces).length) { - console.error('Invalid choice. Please select a number from the list.'); - return; - } - - const interfaceName = Object.keys(interfaces)[choice - 1]; - const addresses = interfaces[interfaceName]!.map((addressInfo) => addressInfo.address); - - console.log(`Selected interface: ${interfaceName} (${addresses.join(', ')})`); - stdin.removeAllListeners('data'); - stdin.pause(); - resolve(interfaceName); - }) - }) - } -} - From 3cbc0bd567a17b10d3916cf0acc55b04c89a10ca Mon Sep 17 00:00:00 2001 From: wes Date: Wed, 22 Feb 2023 18:21:24 -0700 Subject: [PATCH 07/15] Filter Multicast Addresses for local IPv6 only. --- src/matter/mdns/MdnsBroadcaster.ts | 4 +--- src/net/node/NetworkNode.ts | 8 +++++--- src/util/Ip.ts | 9 ++++++++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/matter/mdns/MdnsBroadcaster.ts b/src/matter/mdns/MdnsBroadcaster.ts index 1eba681a..9bd243c2 100644 --- a/src/matter/mdns/MdnsBroadcaster.ts +++ b/src/matter/mdns/MdnsBroadcaster.ts @@ -112,9 +112,7 @@ export class MdnsBroadcaster implements Broadcaster { if (isIPv4(ip)) { records.push(ARecord(hostname, ip)); } else { - if(ip.startsWith('fe80::')){ // only add the local address - records.push(AAAARecord(hostname, ip)); - } + records.push(AAAARecord(hostname, ip)); } }); return records; diff --git a/src/net/node/NetworkNode.ts b/src/net/node/NetworkNode.ts index 909096a4..3381fc86 100644 --- a/src/net/node/NetworkNode.ts +++ b/src/net/node/NetworkNode.ts @@ -8,7 +8,7 @@ import { networkInterfaces, NetworkInterfaceInfo } from "os"; import { UdpChannelOptions, UdpChannel } from "../UdpChannel"; import { UdpChannelNode } from "./UdpChannelNode"; import { Network } from "../Network"; -import { onSameNetwork } from "../../util/Ip.js"; +import { isLocalIPv6Address, onSameNetwork } from "../../util/Ip.js"; import { Cache } from "../../util/Cache.js"; export class NetworkNode extends Network { @@ -38,7 +38,7 @@ export class NetworkNode extends Network { (ip: string) => this.getNetInterfaceForIpInternal(ip), 5 * 60 * 1000, /* 5mn */ ) - + private static getNetInterfaceForIpInternal(ip: string) { if (ip.indexOf("%") !== -1) { // IPv6 address with scope @@ -72,7 +72,9 @@ export class NetworkNode extends Network { getIpMac(netInterface: string): { mac: string; ips: string[]; } | undefined { const netInterfaceInfo = networkInterfaces()[netInterface]; if (netInterfaceInfo === undefined) return undefined; - return { mac: netInterfaceInfo[0].mac, ips: netInterfaceInfo.map(({address}) => address) }; + // only use local IPv6 address + const ips = netInterfaceInfo.map(({address}) => address).filter(ip => isLocalIPv6Address(ip)) + return { mac: netInterfaceInfo[0].mac, ips: ips }; } override createUdpChannel(options: UdpChannelOptions): Promise { diff --git a/src/util/Ip.ts b/src/util/Ip.ts index 1b5d41fc..441a572a 100644 --- a/src/util/Ip.ts +++ b/src/util/Ip.ts @@ -23,7 +23,7 @@ export function iPv4ToNumber(ip: string) { return dataView.getUint32(0); } -export function iPv6ToArray(ip: string) { +export function iPv6ToArray(ip: string) : Uint16Array { const array = new Uint16Array(8); let ipParts = ip.split(":"); const valueCount = ipParts.filter(value => value !== "").length; @@ -60,4 +60,11 @@ export function onSameNetwork(ip1: string, ip2: string, mask: string) { if ((ip1Array[i] & mask) !== (ip2Array[i] & mask)) return false; } } + return false } + +export function isLocalIPv6Address(ipv6Address: string): boolean { + const localAddressPrefixes = ["fc", "fd"]; + const firstTwoBytes = ipv6Address.slice(0, 2); + return localAddressPrefixes.includes(firstTwoBytes); + } From ecb81c178d3cb52441338be689f86f3c5d740938 Mon Sep 17 00:00:00 2001 From: wes Date: Thu, 23 Feb 2023 07:09:24 -0700 Subject: [PATCH 08/15] maintaining consistency with other 'demo' code in library --- src/Device.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Device.ts b/src/Device.ts index 5a10a04d..13c27b9b 100644 --- a/src/Device.ts +++ b/src/Device.ts @@ -61,9 +61,12 @@ Network.get = singleton(() => new NetworkNode()); const logger = Logger.get("Device"); class Device { - async start(networkInterface? : string) { + + + async start() { logger.info(`node-matter@${packageJson.version}`); + const networkInterface = getParameter("interface"); const deviceName = "Matter test device"; const deviceType = 257 /* Dimmable bulb */; const vendorName = "node-matter"; @@ -197,6 +200,4 @@ class Device { } } -const networkInterface = getParameter("interface"); - -new Device().start(networkInterface); +new Device().start(); From f67363c7348b7434fe4f78fb427faf450873488c Mon Sep 17 00:00:00 2001 From: wes Date: Tue, 7 Mar 2023 11:12:22 -0700 Subject: [PATCH 09/15] rename for clarity --- src/net/node/NetworkNode.ts | 4 ++-- src/util/Ip.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net/node/NetworkNode.ts b/src/net/node/NetworkNode.ts index 3381fc86..6e3824a5 100644 --- a/src/net/node/NetworkNode.ts +++ b/src/net/node/NetworkNode.ts @@ -8,7 +8,7 @@ import { networkInterfaces, NetworkInterfaceInfo } from "os"; import { UdpChannelOptions, UdpChannel } from "../UdpChannel"; import { UdpChannelNode } from "./UdpChannelNode"; import { Network } from "../Network"; -import { isLocalIPv6Address, onSameNetwork } from "../../util/Ip.js"; +import { isIpV6UniqueLocalAddress, onSameNetwork } from "../../util/Ip.js"; import { Cache } from "../../util/Cache.js"; export class NetworkNode extends Network { @@ -73,7 +73,7 @@ export class NetworkNode extends Network { const netInterfaceInfo = networkInterfaces()[netInterface]; if (netInterfaceInfo === undefined) return undefined; // only use local IPv6 address - const ips = netInterfaceInfo.map(({address}) => address).filter(ip => isLocalIPv6Address(ip)) + const ips = netInterfaceInfo.map(({address}) => address).filter(ip => isIpV6UniqueLocalAddress(ip)) return { mac: netInterfaceInfo[0].mac, ips: ips }; } diff --git a/src/util/Ip.ts b/src/util/Ip.ts index 441a572a..30760fca 100644 --- a/src/util/Ip.ts +++ b/src/util/Ip.ts @@ -63,7 +63,7 @@ export function onSameNetwork(ip1: string, ip2: string, mask: string) { return false } -export function isLocalIPv6Address(ipv6Address: string): boolean { +export function isIpV6UniqueLocalAddress(ipv6Address: string): boolean { const localAddressPrefixes = ["fc", "fd"]; const firstTwoBytes = ipv6Address.slice(0, 2); return localAddressPrefixes.includes(firstTwoBytes); From 333832b9f3753cf43d3b820ff7fdfc6a7ed14352 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 10 Mar 2023 12:44:21 -0700 Subject: [PATCH 10/15] exclude IPv6 localhost address from mDNS Ad --- src/matter/mdns/MdnsBroadcaster.ts | 6 ++++-- src/net/node/NetworkNode.ts | 5 ++--- src/util/Ip.ts | 11 +++++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/matter/mdns/MdnsBroadcaster.ts b/src/matter/mdns/MdnsBroadcaster.ts index 9bd243c2..e8d03633 100644 --- a/src/matter/mdns/MdnsBroadcaster.ts +++ b/src/matter/mdns/MdnsBroadcaster.ts @@ -45,9 +45,11 @@ export class MdnsBroadcaster implements Broadcaster { const ipMac = this.network.getIpMac(netInterface); if (ipMac === undefined) return []; const { mac, ips } = ipMac; + if( ips.length === 0) { + return []; // post filtering the mac might not have any valid ips. + } const hostname = mac.replace(/:/g, "").toUpperCase() + "0000.local"; - logger.debug(`on IP Addr: ${ips}`) - logger.debug(`using hostname ${hostname}`) + logger.debug(`${netInterface} on IP Addrs: ${ips.join(", ")} host: ${hostname}`) const records = [ PtrRecord(SERVICE_DISCOVERY_QNAME, MATTER_COMMISSION_SERVICE_QNAME), PtrRecord(SERVICE_DISCOVERY_QNAME, vendorQname), diff --git a/src/net/node/NetworkNode.ts b/src/net/node/NetworkNode.ts index 6e3824a5..da561d3f 100644 --- a/src/net/node/NetworkNode.ts +++ b/src/net/node/NetworkNode.ts @@ -8,7 +8,7 @@ import { networkInterfaces, NetworkInterfaceInfo } from "os"; import { UdpChannelOptions, UdpChannel } from "../UdpChannel"; import { UdpChannelNode } from "./UdpChannelNode"; import { Network } from "../Network"; -import { isIpV6UniqueLocalAddress, onSameNetwork } from "../../util/Ip.js"; +import { isMatterAddressableIPv6Address, onSameNetwork } from "../../util/Ip.js"; import { Cache } from "../../util/Cache.js"; export class NetworkNode extends Network { @@ -72,8 +72,7 @@ export class NetworkNode extends Network { getIpMac(netInterface: string): { mac: string; ips: string[]; } | undefined { const netInterfaceInfo = networkInterfaces()[netInterface]; if (netInterfaceInfo === undefined) return undefined; - // only use local IPv6 address - const ips = netInterfaceInfo.map(({address}) => address).filter(ip => isIpV6UniqueLocalAddress(ip)) + const ips = netInterfaceInfo.map(({address}) => address).filter(ip => isMatterAddressableIPv6Address(ip)) return { mac: netInterfaceInfo[0].mac, ips: ips }; } diff --git a/src/util/Ip.ts b/src/util/Ip.ts index 30760fca..036c23ae 100644 --- a/src/util/Ip.ts +++ b/src/util/Ip.ts @@ -63,8 +63,11 @@ export function onSameNetwork(ip1: string, ip2: string, mask: string) { return false } -export function isIpV6UniqueLocalAddress(ipv6Address: string): boolean { - const localAddressPrefixes = ["fc", "fd"]; - const firstTwoBytes = ipv6Address.slice(0, 2); - return localAddressPrefixes.includes(firstTwoBytes); + +/** + * return true if ipV6 address meets the Matter Spec to advertise in MDNS + * filter out IPv6 Loopback addresses - fe80 - for obvious reasons + */ +export function isMatterAddressableIPv6Address(ipv6Address: string): boolean { + return !ipv6Address.toLowerCase().startsWith("fe80") } From 96b151c47bb32f393e8e3ed0468be23964901c49 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 10 Mar 2023 13:04:06 -0700 Subject: [PATCH 11/15] better localhost matching w/ v4 addition --- src/util/Ip.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/util/Ip.ts b/src/util/Ip.ts index 036c23ae..403e9280 100644 --- a/src/util/Ip.ts +++ b/src/util/Ip.ts @@ -68,6 +68,10 @@ export function onSameNetwork(ip1: string, ip2: string, mask: string) { * return true if ipV6 address meets the Matter Spec to advertise in MDNS * filter out IPv6 Loopback addresses - fe80 - for obvious reasons */ -export function isMatterAddressableIPv6Address(ipv6Address: string): boolean { - return !ipv6Address.toLowerCase().startsWith("fe80") +export function isMatterAddressableIPv6Address(targetIpAddr: string): boolean { + return !( + targetIpAddr.toLowerCase().startsWith("fe80") || + targetIpAddr.startsWith('::1') || + targetIpAddr.startsWith('0::1') || + targetIpAddr.startsWith('127.')) } From 88b1584053feba19d6417b4b4a20874e1b4e3170 Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 13 Mar 2023 08:47:21 -0600 Subject: [PATCH 12/15] naming preference change --- src/Device.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Device.ts b/src/Device.ts index ca5087cc..0970a444 100644 --- a/src/Device.ts +++ b/src/Device.ts @@ -56,7 +56,7 @@ class Device { async start() { logger.info(`node-matter@${packageJson.version}`); - const networkInterface = getParameter("interface"); + const networkInterface = getParameter("broadcastInterface"); const deviceName = "Matter test device"; const deviceType = 257 /* Dimmable bulb */; const vendorName = "node-matter"; From f26d95e62ebbe0d58f4b63e890dc0f6186998762 Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 13 Mar 2023 13:35:36 -0600 Subject: [PATCH 13/15] filter network interfaces for valid networks before setting up MdnsBroadcaster --- src/matter/mdns/MdnsBroadcaster.ts | 5 +---- src/net/node/NetworkNode.ts | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/matter/mdns/MdnsBroadcaster.ts b/src/matter/mdns/MdnsBroadcaster.ts index e8d03633..5ee97c42 100644 --- a/src/matter/mdns/MdnsBroadcaster.ts +++ b/src/matter/mdns/MdnsBroadcaster.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { AAAARecord, ARecord, PtrRecord, Record, SrvRecord, TxtRecord } from "../../codec/DnsCodec"; +import { AAAARecord, ARecord, PtrRecord, SrvRecord, TxtRecord } from "../../codec/DnsCodec"; import { Crypto } from "../../crypto/Crypto"; import { Broadcaster } from "../common/Broadcaster"; import { getDeviceMatterQname, getFabricQname, MATTER_COMMISSION_SERVICE_QNAME, MATTER_SERVICE_QNAME, SERVICE_DISCOVERY_QNAME } from "./MdnsConsts"; @@ -45,9 +45,6 @@ export class MdnsBroadcaster implements Broadcaster { const ipMac = this.network.getIpMac(netInterface); if (ipMac === undefined) return []; const { mac, ips } = ipMac; - if( ips.length === 0) { - return []; // post filtering the mac might not have any valid ips. - } const hostname = mac.replace(/:/g, "").toUpperCase() + "0000.local"; logger.debug(`${netInterface} on IP Addrs: ${ips.join(", ")} host: ${hostname}`) const records = [ diff --git a/src/net/node/NetworkNode.ts b/src/net/node/NetworkNode.ts index da561d3f..6ad3ef03 100644 --- a/src/net/node/NetworkNode.ts +++ b/src/net/node/NetworkNode.ts @@ -73,6 +73,7 @@ export class NetworkNode extends Network { const netInterfaceInfo = networkInterfaces()[netInterface]; if (netInterfaceInfo === undefined) return undefined; const ips = netInterfaceInfo.map(({address}) => address).filter(ip => isMatterAddressableIPv6Address(ip)) + if(0 === ips.length) return undefined; return { mac: netInterfaceInfo[0].mac, ips: ips }; } From f0597aa215b2d354a2102bc17f65a288b28d14b3 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Wed, 15 Mar 2023 09:43:44 +0100 Subject: [PATCH 14/15] codestyle --- src/net/node/NetworkNode.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/node/NetworkNode.ts b/src/net/node/NetworkNode.ts index 6ad3ef03..7825cb82 100644 --- a/src/net/node/NetworkNode.ts +++ b/src/net/node/NetworkNode.ts @@ -73,7 +73,7 @@ export class NetworkNode extends Network { const netInterfaceInfo = networkInterfaces()[netInterface]; if (netInterfaceInfo === undefined) return undefined; const ips = netInterfaceInfo.map(({address}) => address).filter(ip => isMatterAddressableIPv6Address(ip)) - if(0 === ips.length) return undefined; + if (ips.length === 0) return undefined; return { mac: netInterfaceInfo[0].mac, ips: ips }; } From 17bafcf56e95610b08ad9e39ac968b2ef20b1879 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Wed, 15 Mar 2023 09:44:25 +0100 Subject: [PATCH 15/15] consistent naming --- src/Device.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Device.ts b/src/Device.ts index 0970a444..0e82bdfc 100644 --- a/src/Device.ts +++ b/src/Device.ts @@ -56,7 +56,7 @@ class Device { async start() { logger.info(`node-matter@${packageJson.version}`); - const networkInterface = getParameter("broadcastInterface"); + const broadcastInterface = getParameter("broadcastInterface"); const deviceName = "Matter test device"; const deviceType = 257 /* Dimmable bulb */; const vendorName = "node-matter"; @@ -91,7 +91,7 @@ class Device { .addNetInterface(await UdpInterface.create(5540, "udp4")) .addNetInterface(await UdpInterface.create(5540, "udp6")) .addScanner(await MdnsScanner.create()) - .addBroadcaster(await MdnsBroadcaster.create(networkInterface)) + .addBroadcaster(await MdnsBroadcaster.create(broadcastInterface)) .addProtocolHandler(secureChannelProtocol) .addProtocolHandler(new InteractionServer() .addEndpoint(0x00, DEVICE.ROOT, [