From f7ca7a0929f276f734e87ce5f0dcdb94488cbebb Mon Sep 17 00:00:00 2001 From: Mathieu Date: Fri, 15 May 2026 14:21:45 +0200 Subject: [PATCH] fix(mdns-scanner): browser par type au lieu d'une recherche globale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bonjour-service exige un `type` dans BrowserConfig ; il n'existe pas d'option pour écouter "tous les services". Le scanner instancie maintenant un browser par type mDNS courant en homelab (http, ssh, smb, airplay, googlecast, homekit, ipp, etc.) et agrège les annonces par IP via une fonction `ingest` partagée. Co-Authored-By: Claude Opus 4.7 --- .../discovery/scanners/mdns.scanner.ts | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/modules/discovery/scanners/mdns.scanner.ts b/src/modules/discovery/scanners/mdns.scanner.ts index 97348be..ccf9e19 100644 --- a/src/modules/discovery/scanners/mdns.scanner.ts +++ b/src/modules/discovery/scanners/mdns.scanner.ts @@ -1,13 +1,36 @@ -import { Bonjour } from 'bonjour-service'; +import { Bonjour, type Service } from 'bonjour-service'; import { env } from '@/config/env'; import type { DiscoveryResult, DiscoveryTarget, Scanner } from '../types'; /** - * Découverte via mDNS / DNS-SD (_services._dns-sd._udp.local). - * Écoute pendant `timeout` ms et agrège les annonces reçues. + * Découverte via mDNS / DNS-SD. + * `bonjour-service` exige un `type` par browser : on en lance un par type + * courant en homelab et on agrège les annonces reçues pendant `timeout` ms. */ const DEFAULT_TIMEOUT_MS = 4000; +// Types mDNS les plus fréquents en homelab (sans le préfixe `_` ni le suffixe `._tcp/._udp`) +const COMMON_SERVICE_TYPES: Array<{ type: string; protocol: 'tcp' | 'udp' }> = [ + { type: 'http', protocol: 'tcp' }, + { type: 'https', protocol: 'tcp' }, + { type: 'ssh', protocol: 'tcp' }, + { type: 'sftp-ssh', protocol: 'tcp' }, + { type: 'smb', protocol: 'tcp' }, + { type: 'nfs', protocol: 'tcp' }, + { type: 'afpovertcp', protocol: 'tcp' }, + { type: 'workstation', protocol: 'tcp' }, + { type: 'device-info', protocol: 'tcp' }, + { type: 'printer', protocol: 'tcp' }, + { type: 'ipp', protocol: 'tcp' }, + { type: 'ipps', protocol: 'tcp' }, + { type: 'airplay', protocol: 'tcp' }, + { type: 'raop', protocol: 'tcp' }, + { type: 'googlecast', protocol: 'tcp' }, + { type: 'homekit', protocol: 'tcp' }, + { type: 'hap', protocol: 'tcp' }, + { type: 'spotify-connect', protocol: 'tcp' }, +]; + export const mdnsScanner: Scanner = { kind: 'mdns', label: 'mDNS / Bonjour', @@ -17,11 +40,14 @@ export const mdnsScanner: Scanner = { const bonjour = new Bonjour(); const byIp = new Map(); - const browser = bonjour.find({}); - browser.on('up', (svc) => { + const ingest = (svc: Service) => { const ips = (svc.addresses ?? []).filter((a) => a && !a.includes(':')); // IPv4 for (const ip of ips) { - const existing = byIp.get(ip) ?? { ipAddress: ip, hostname: svc.host, services: [] }; + const existing = byIp.get(ip) ?? { + ipAddress: ip, + hostname: svc.host, + services: [], + }; existing.services!.push({ name: svc.name, type: `_${svc.type}._${svc.protocol}.local`, @@ -29,10 +55,16 @@ export const mdnsScanner: Scanner = { }); byIp.set(ip, existing); } + }; + + const browsers = COMMON_SERVICE_TYPES.map(({ type, protocol }) => { + const browser = bonjour.find({ type, protocol }); + browser.on('up', ingest); + return browser; }); await new Promise((r) => setTimeout(r, DEFAULT_TIMEOUT_MS)); - browser.stop(); + for (const b of browsers) b.stop(); bonjour.destroy(); return [...byIp.values()];