UNPKG

domotz-remote-pawn

Version:

Domotz Agent

121 lines (100 loc) 4.17 kB
/** This file is part of Domotz Agent. * Copyright (C) 2016 Domotz UK LLP * * Domotz Agent is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Domotz Agent is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>. * * Listens for broadcast DHCP lease packets and sends the data to the backend * * Created by Iacopo Papalini <iacopo@domotz.com> * * 40 seconds: the assumption is that in the meantime the fast discovery * has produced the creation if the missing device */ const RETRY_INTERVAL = 35000; const LOG_PREFIX = 'DHCP_LISTEN '; function isWellFormed(message) { if (message.op.value !== 1) { // not a BOOTPREQUEST throw new Error(LOG_PREFIX + "- Not a BOOTREQUEST. Value: " + message.op.value); } if (!message.options) { // not a DHCP request throw new Error(LOG_PREFIX + "- Not a DHCP request"); } var hwaddr = message.options.clientIdentifier || message.options.chaddr; if (!hwaddr || !hwaddr.type || hwaddr.type.value !== 1) { throw new Error(LOG_PREFIX + "- Not an ethernet device"); } return hwaddr.address.toUpperCase(); } var dhcpDiscoveryFactory = function (dhcpjs, random, discoveryUtils, engineRequest) { "use strict"; var sentFingerprints = {}; // Filter for known devices var unknownDevices = {}; // Filter for unknown devices function signalToEngine(mac, dhcpData) { if (unknownDevices[mac]) { // Put filter as early as possible console.verbose(LOG_PREFIX + " not sending unknown devices with mac %s", mac); return; } var hash = random.md5(JSON.stringify(dhcpData)); if (sentFingerprints[mac] === hash) { console.debug(LOG_PREFIX + " not sending to engine matching md5 (%s) for mac %s", hash, mac); return; } var deviceId = discoveryUtils.getDeviceIdFromMac(mac); if (!deviceId) { unknownDevices[mac] = true; console.warn(LOG_PREFIX + " Unknown device for mac %s, retrying " + "in %s ms. Fingerprint: %s", mac, RETRY_INTERVAL, JSON.stringify(dhcpData)); setTimeout(function () { unknownDevices[mac] = false; signalToEngine(mac, dhcpData); }, RETRY_INTERVAL); return; } console.info(LOG_PREFIX + "Sending DHCP fingerprint for device %s (mac: %s) ", deviceId, mac); engineRequest.sendWithPromise('/device/' + deviceId + '/inspection-data/dhcp', 'PUT', dhcpData) .then(function () { sentFingerprints[mac] = hash; } ); } function handleMessage(message) { try { var mac = isWellFormed(message); console.verbose(LOG_PREFIX + "DHCP Packet arrived: mac=%s", mac); signalToEngine(mac, message.options); } catch (err) { console.warn('%s %s. Ignoring unexpected packet', LOG_PREFIX, err.message); console.debug(LOG_PREFIX + JSON.stringify(message)); return err.message; // For testing purpose } } function onListening(address) { console.info(LOG_PREFIX + '- listening for DHCP packets on ' + address); } function listenForLeasePackets() { var server = dhcpjs.createServer(); server.on('listening', onListening); server.on('message', handleMessage); server.bind(); } return { // ----- TEST ----- _handleMessage: handleMessage, // ----- TEST ----- listenForLeasePackets: listenForLeasePackets }; }; module.exports.factory = dhcpDiscoveryFactory;