<commit_before>/*    Copyright 2016-2021 Firewalla Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program 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 Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

const log = require('../net2/logger.js')(__filename);

const sysManager = require('../net2/SysManager.js');
const HostTool = require('../net2/HostTool.js');
const hostTool = new HostTool();

const Sensor = require('./Sensor.js').Sensor;

const extensionManager = require('./ExtensionManager.js');
const _ = require('lodash');

const net = require('net');
const udp = require('dgram');

class WOLSensor extends Sensor {

  apiRun() {
    extensionManager.onCmd("wol:wake", (msg, data) => {
      const mac = msg.target;
      this.wake(mac, function(err, res){
        if (err) log.error("wake up fail.", err);
        log.info("wake up result: ", res);
      });
    })
  }

  createMagicPacket(mac){
    const MAC_REPEAT    = 16;
    const MAC_LENGTH    = 0x06;
    const PACKET_HEADER = 0x06;
    const parts  = mac.match(/[0-9a-fA-F]{2}/g);
    if(!parts || parts.length != MAC_LENGTH)
      throw new Error(`malformed MAC address "${mac}"`);
    var buffer = Buffer.alloc(PACKET_HEADER);
    var bufMac = Buffer.from(parts.map(p => parseInt(p, 16)));
    buffer.fill(0xff);
    for(var i = 0; i < MAC_REPEAT; i++){
      buffer = Buffer.concat([ buffer, bufMac ]);
    }
    return buffer;
  };

  getBoxInterfaceIP(mac) {
    const ips = hostTool.getIPsByMac(mac);
    if (_.isEmpty(ips)) {
      return null;
    }

    const ipv4 = ips[0];
    const intf = sysManager.getInterfaceViaIP(ipv4);
    if (!intf || !intf.ip_address) {
      return null;
    }

    return intf.ip_address;
  }

  wake(mac, options, callback){
    options = options || {};
    if(typeof options == 'function'){
      callback = options;
    }
    const { address, port } = Object.assign({
      address : '255.255.255.255',
      port    : 9
    }, options);

    // to make sure box doesn't use other interface to send
    const boxIntfIP = this.getBoxInterfaceIP(mac);
    if (!boxIntfIP) {
      callback && callback(null, "device not found");
      return;
    }

    // create magic packet
    const magicPacket = this.createMagicPacket(mac);
    const socket = udp.createSocket('udp4');
    socket.bind(0, boxIntfIP);
    socket.on('error', function(err){
      socket.close();
      callback && callback(err);
    }).once('listening', function(){
      socket.setBroadcast(true);
    });

    socket.send(
      magicPacket, 0, magicPacket.length, port, address,
      (err, res) => {
        const result = res == magicPacket.length;
        socket.close();
        callback && callback(err, result);
    });
  };

}

module.exports = WOLSensor;<commit_msg>bug fix<commit_after>/*    Copyright 2016-2021 Firewalla Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program 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 Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

const log = require('../net2/logger.js')(__filename);

const sysManager = require('../net2/SysManager.js');
const HostTool = require('../net2/HostTool.js');
const hostTool = new HostTool();

const Sensor = require('./Sensor.js').Sensor;

const extensionManager = require('./ExtensionManager.js');
const _ = require('lodash');

const net = require('net');
const udp = require('dgram');

class WOLSensor extends Sensor {

  apiRun() {
    extensionManager.onCmd("wol:wake", (msg, data) => {
      const mac = msg.target;
      this.wake(mac, function(err, res){
        if (err) log.error("wake up fail.", err);
        log.info("wake up result: ", res);
      });
    })
  }

  createMagicPacket(mac){
    const MAC_REPEAT    = 16;
    const MAC_LENGTH    = 0x06;
    const PACKET_HEADER = 0x06;
    const parts  = mac.match(/[0-9a-fA-F]{2}/g);
    if(!parts || parts.length != MAC_LENGTH)
      throw new Error(`malformed MAC address "${mac}"`);
    var buffer = Buffer.alloc(PACKET_HEADER);
    var bufMac = Buffer.from(parts.map(p => parseInt(p, 16)));
    buffer.fill(0xff);
    for(var i = 0; i < MAC_REPEAT; i++){
      buffer = Buffer.concat([ buffer, bufMac ]);
    }
    return buffer;
  };

  async getBoxInterfaceIP(mac) {
    const ips = await hostTool.getIPsByMac(mac);
    if (_.isEmpty(ips)) {
      return null;
    }

    const ipv4 = ips[0];
    const intf = sysManager.getInterfaceViaIP(ipv4);
    if (!intf || !intf.ip_address) {
      return null;
    }

    return intf.ip_address;
  }

  async wake(mac, options, callback){
    options = options || {};
    if(typeof options == 'function'){
      callback = options;
    }
    const { address, port } = Object.assign({
      address : '255.255.255.255',
      port    : 9
    }, options);

    // to make sure box doesn't use other interface to send
    const boxIntfIP = await this.getBoxInterfaceIP(mac);
    if (!boxIntfIP) {
      callback && callback(null, "device not found");
      return;
    }

    // create magic packet
    const magicPacket = this.createMagicPacket(mac);
    const socket = udp.createSocket('udp4');
    socket.bind(0, boxIntfIP);
    socket.on('error', function(err){
      socket.close();
      callback && callback(err);
    }).once('listening', function(){
      socket.setBroadcast(true);
    });

    socket.send(
      magicPacket, 0, magicPacket.length, port, address,
      (err, res) => {
        const result = res == magicPacket.length ? "success" : "fail";
        socket.close();
        callback && callback(err, result);
    });
  };

}

module.exports = WOLSensor;
{'fraction_non_alphanumeric': 0.13695287479030044, 'fraction_numerical': 0.014030806771389355, 'mean_word_length': 2.853113983548766, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3056272', 'n_tokens_mistral': 2093, 'n_tokens_neox': 2032, 'n_words': 586}