| 37 | const TTL = 4500; |
| 38 | |
| 39 | class MDNS extends Socket { |
| 40 | constructor(dictionary = {}, callback) { |
| 41 | super({kind: "UDP", port: MDNS.PORT, multicast: MDNS.IP}); |
| 42 | |
| 43 | this.services = []; |
| 44 | this.monitors = []; |
| 45 | this.client = callback ?? function() {}; |
| 46 | |
| 47 | if (dictionary.hostName) { |
| 48 | this.hostName = dictionary.hostName; |
| 49 | this.hostNameLower = this.hostName.toLowerCase(); |
| 50 | this.probing = 1; |
| 51 | Timer.set(() => this.probe(), 0); |
| 52 | } |
| 53 | } |
| 54 | close() { |
| 55 | while (this.services.length) |
| 56 | this.remove(this.services[0]); |
| 57 | |
| 58 | while (this.monitors.length) |
| 59 | this.remove(this.monitors[0].service.substring(0, this.monitors[0].service.length - 6)); |
| 60 | |
| 61 | Timer.clear(this.probeTimer); |
| 62 | |
| 63 | super.close(); |
| 64 | } |
| 65 | add(service) { |
| 66 | if (!this.hostName) |
| 67 | throw new Error("no hostName"); |
| 68 | |
| 69 | if (this.probing) |
| 70 | throw new Error("not ready"); |
| 71 | |
| 72 | service.txt ??= {}; |
| 73 | this.services.push(service); |
| 74 | |
| 75 | this.write(MDNS.IP, MDNS.PORT, this.reply(null, 0x1F | 0x8000, service, true)); // remove before adding to clear stale state in clients |
| 76 | service.timer = Timer.repeat(timer => { |
| 77 | this.write(MDNS.IP, MDNS.PORT, this.reply(null, 0x1F, service)); |
| 78 | timer.interval *= 2; |
| 79 | if (timer.interval > 16000) { |
| 80 | Timer.clear(timer); |
| 81 | delete service.timer; |
| 82 | } |
| 83 | else |
| 84 | Timer.schedule(timer, timer.interval, timer.interval); |
| 85 | }, 500); |
| 86 | service.timer.interval = 500; |
| 87 | } |
| 88 | update(service) { |
| 89 | const index = this.services.indexOf(service); |
| 90 | if (index < 0) throw new Error("service not found"); |
| 91 | |
| 92 | if (!service.updater) { |
| 93 | service.updater = Timer.set(updater => { |
| 94 | this.write(MDNS.IP, MDNS.PORT, this.reply(null, 0x04 | 0x8000, service)); |
| 95 | updater.interval += 250; |
| 96 | if (updater.interval >= 1500) { |
nothing calls this directly
no outgoing calls
no test coverage detected