From be3899a8f61863e4c19febcaf7a3ba059b03bfdb Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Tue, 7 Feb 2023 12:54:10 -0600 Subject: [PATCH] add search for sending udp direct to IPs for ATEM --- plugins/atem/main.js | 16 +++++++++------- src/search.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/plugins/atem/main.js b/plugins/atem/main.js index 8015426..0dd337f 100644 --- a/plugins/atem/main.js +++ b/plugins/atem/main.js @@ -3,15 +3,17 @@ exports.config = { connectionType: 'atem', defaultPort: 9910, mayChangePort: false, - // heartbeatInterval: 5000, - // heartbeatTimeout: 20000, searchOptions: { - // TODO: actually populate search options - type: 'UDPsocket', - searchBuffer: Buffer.from('', 'ascii'), - testPort: 9910, + type: 'UDPScan', + searchBuffer: Buffer.from([ + 0x10, 0x14, 0x53, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, + ]), + listenPort: 0, + devicePort: 9910, validateResponse(msg, info) { - return true; + // This is a tad bit hacky but works from what I can see. + return Buffer.compare(msg.slice(0, 4), Buffer.from([16, 20, 83, 171])) === 0; }, }, }; diff --git a/src/search.js b/src/search.js index 012c2a2..a713dbe 100644 --- a/src/search.js +++ b/src/search.js @@ -5,6 +5,7 @@ const net = require('net'); const os = require('os'); const ip = require('ip'); +const { Netmask } = require('netmask'); const DEVICE = require('./device.js'); const PLUGINS = require('./plugins.js'); @@ -91,6 +92,8 @@ function searchAll() { searchUDP(pluginType, plugin.config); } else if (searchType === 'multicast') { searchMulticast(pluginType, plugin.config); + } else if (searchType === 'UDPScan') { + searchUDPScan(pluginType, plugin.config); } } catch (err) { console.error(`Unable to search for plugin ${pluginType}`); @@ -167,6 +170,36 @@ function TCPtest(ipAddr, pluginType, pluginConfig) { }); } +function searchUDPScan(pluginType, pluginConfig) { + for (let i = 0; i < Object.keys(validInterfaces).length; i++) { + const interfaceID = Object.keys(validInterfaces)[i]; + const interfaceObj = validInterfaces[interfaceID]; + interfaceObj.forEach((netInterface) => { + const udpSocket = dgram.createSocket('udp4'); + udpSocket.bind(pluginConfig.searchOptions.listenPort, netInterface.address); + + udpSocket.on('message', (msg, info) => { + if (pluginConfig.searchOptions.validateResponse(msg, info, DEVICE.all)) { + udpSocket.close(); + DEVICE.registerDevice( + { + type: pluginType, + defaultName: pluginConfig.defaultName, + port: pluginConfig.defaultPort, + addresses: [info.address], + }, + 'fromSearch' + ); + } + }); + const interfaceBlock = new Netmask(netInterface.cidr); + interfaceBlock.forEach((address, long, index) => { + udpSocket.send(pluginConfig.searchOptions.searchBuffer, pluginConfig.searchOptions.devicePort, address); + }); + }); + } +} + function searchUDP(pluginType, pluginConfig) { for (let i = 0; i < Object.keys(validInterfaces).length; i++) { const interfaceID = Object.keys(validInterfaces)[i];