New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@jamy/dash-button

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@jamy/dash-button - npm Package Compare versions

Comparing version 3.2.0 to 3.2.1

build/__mocks__/console.d.ts

10

build/__mocks__/console.js

@@ -5,2 +5,7 @@ "use strict";

const ActualConsole = require.requireActual('console').Console;
class NullWritableStream extends stream_1.Writable {
_write(_chunk, _encoding, callback) {
callback();
}
}
let Console = /** @class */ (() => {

@@ -24,8 +29,3 @@ class Console {

})();
class NullWritableStream extends stream_1.Writable {
_write(_chunk, _encoding, callback) {
callback();
}
}
module.exports = new Console();
//# sourceMappingURL=console.js.map

@@ -7,7 +7,7 @@ "use strict";

const events_1 = __importDefault(require("events"));
let pcap = require.requireActual('pcap');
let pcapMock = jest.genMockFromModule('pcap');
const pcap = require.requireActual('pcap');
const pcapMock = jest.genMockFromModule('pcap');
pcapMock.decode = pcap.decode;
pcapMock.createSession.mockImplementation((interfaceName, filter = '') => {
let session = new events_1.default.EventEmitter();
const session = new events_1.default.EventEmitter();
session.device_name = interfaceName;

@@ -14,0 +14,0 @@ session.filter = filter;

@@ -9,2 +9,31 @@ "use strict";

jest.mock('../NetworkInterfaces');
function createMockArpProbe(sourceMacAddress) {
const decimals = sourceMacAddress.split(':').map(hex => parseInt(hex, 16));
assert_1.default(decimals.length === 6, 'MAC addresses must be six bytes');
return {
link_type: 'LINKTYPE_ETHERNET',
// prettier-ignore
header: Buffer.from([
249, 133, 27, 86,
137, 239, 1, 0,
42, 0, 0, 0,
42, 0, 0, 0,
]),
// prettier-ignore
buf: Buffer.from([
255, 255, 255, 255, 255, 255,
...decimals,
8, 6,
0, 1,
8, 0,
6,
4,
0, 1,
...decimals,
0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
10, 0, 10, 20,
])
};
}
describe('DashButton', () => {

@@ -26,7 +55,7 @@ const MAC_ADDRESS = '00:11:22:33:44:55';

test(`should normalize (lowercase) the dash buttons MAC address`, () => {
let button = new DashButton('00:11:AA:33:44:BB');
const button = new DashButton('00:11:AA:33:44:BB');
expect(button._macAddress).toEqual('00:11:aa:33:44:bb');
});
test(`creates a pcap session the first time a listener is added`, () => {
let button = new DashButton(MAC_ADDRESS);
const button = new DashButton(MAC_ADDRESS);
button.addListener(() => { });

@@ -36,5 +65,5 @@ expect(pcap.createSession).toHaveBeenCalledTimes(1);

test(`shares pcap sessions amongst buttons`, () => {
let button1 = new DashButton(MAC_ADDRESS);
const button1 = new DashButton(MAC_ADDRESS);
button1.addListener(() => { });
let button2 = new DashButton('66:77:88:99:aa:bb');
const button2 = new DashButton('66:77:88:99:aa:bb');
button2.addListener(() => { });

@@ -44,3 +73,3 @@ expect(pcap.createSession).toHaveBeenCalledTimes(1);

test(`creates a pcap session on the default interface`, () => {
let button = new DashButton(MAC_ADDRESS);
const button = new DashButton(MAC_ADDRESS);
button.addListener(() => { });

@@ -51,3 +80,3 @@ expect(pcap.createSession).toHaveBeenCalledTimes(1);

test(`creates a pcap session on the specified interface`, () => {
let button = new DashButton(MAC_ADDRESS, { networkInterface: 'wlan0' });
const button = new DashButton(MAC_ADDRESS, { networkInterface: 'wlan0' });
button.addListener(() => { });

@@ -58,15 +87,15 @@ expect(pcap.createSession).toHaveBeenCalledTimes(1);

test(`notifies the appropriate listeners for each packet`, () => {
let mockSession = pcap.createSession(NetworkInterfaces.getDefault());
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
pcap.createSession.mockReturnValueOnce(mockSession);
let button1Listener = jest.fn();
let button2Listener = jest.fn();
let button1 = new DashButton(MAC_ADDRESS);
const button1Listener = jest.fn();
const button2Listener = jest.fn();
const button1 = new DashButton(MAC_ADDRESS);
button1.addListener(button1Listener);
let button2 = new DashButton('66:77:88:99:aa:bb');
const button2 = new DashButton('66:77:88:99:aa:bb');
button2.addListener(button2Listener);
let packet1 = createMockArpProbe(MAC_ADDRESS);
const packet1 = createMockArpProbe(MAC_ADDRESS);
mockSession.emit('packet', packet1);
expect(button1Listener).toHaveBeenCalledTimes(1);
expect(button2Listener).not.toHaveBeenCalled();
let packet2 = createMockArpProbe('66:77:88:99:aa:bb');
const packet2 = createMockArpProbe('66:77:88:99:aa:bb');
mockSession.emit('packet', packet2);

@@ -77,5 +106,5 @@ expect(button1Listener).toHaveBeenCalledTimes(1);

test(`waits for listeners for a prior packet to asynchronously complete before handling any new packets`, async () => {
let mockSession = pcap.createSession(NetworkInterfaces.getDefault());
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
let listenerCompletion = null;
let originalAddListener = mockSession.addListener;
const originalAddListener = mockSession.addListener;
mockSession.addListener = function addListener(eventName, listener) {

@@ -87,3 +116,3 @@ originalAddListener.call(this, eventName, function (...args) {

pcap.createSession.mockReturnValueOnce(mockSession);
let button = new DashButton(MAC_ADDRESS);
const button = new DashButton(MAC_ADDRESS);
let calls = 0;

@@ -93,6 +122,6 @@ button.addListener(() => {

});
let packet = createMockArpProbe(MAC_ADDRESS);
const packet = createMockArpProbe(MAC_ADDRESS);
mockSession.emit('packet', packet);
expect(calls).toBe(1);
let firstListenerCompletion = listenerCompletion;
const firstListenerCompletion = listenerCompletion;
mockSession.emit('packet', packet);

@@ -105,7 +134,7 @@ expect(calls).toBe(1);

test(`waits for all listeners even if some threw an error`, async () => {
let mockSession = pcap.createSession(NetworkInterfaces.getDefault());
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
pcap.createSession.mockReturnValueOnce(mockSession);
let originalConsole = global.console;
const originalConsole = global.console;
global.console = require.requireMock('console');
let button = new DashButton(MAC_ADDRESS);
const button = new DashButton(MAC_ADDRESS);
let errorCount = 0;

@@ -131,3 +160,3 @@ button.addListener(() => {

});
let packet = createMockArpProbe(MAC_ADDRESS);
const packet = createMockArpProbe(MAC_ADDRESS);
expect(listenerPromise).not.toBeDefined();

@@ -137,3 +166,3 @@ expect(console.error).not.toHaveBeenCalled();

expect(listenerPromise).toBeDefined();
let result = await listenerPromise;
const result = await listenerPromise;
expect(result).toBe('success');

@@ -151,5 +180,5 @@ // TODO: Define a public interface to learn when the DashButton is done

test(`runs its async listeners concurrently`, () => {
let mockSession = pcap.createSession(NetworkInterfaces.getDefault());
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
pcap.createSession.mockReturnValueOnce(mockSession);
let button = new DashButton(MAC_ADDRESS);
const button = new DashButton(MAC_ADDRESS);
let calls = 0;

@@ -164,3 +193,3 @@ button.addListener(async () => {

});
let packet = createMockArpProbe(MAC_ADDRESS);
const packet = createMockArpProbe(MAC_ADDRESS);
expect(calls).toBe(0);

@@ -170,8 +199,23 @@ mockSession.emit('packet', packet);

});
test(`debounces calls`, () => {
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
pcap.createSession.mockReturnValueOnce(mockSession);
const button = new DashButton(MAC_ADDRESS);
let calls = 0;
button.addListener(async () => {
calls++;
await Promise.resolve();
});
const packet = createMockArpProbe(MAC_ADDRESS);
expect(calls).toBe(0);
mockSession.emit('packet', packet);
mockSession.emit('packet', packet);
expect(calls).toBe(1);
});
test(`removes packet listeners when a button has no more listeners`, () => {
let mockSession = pcap.createSession(NetworkInterfaces.getDefault());
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
pcap.createSession.mockReturnValueOnce(mockSession);
let button = new DashButton(MAC_ADDRESS);
let subscription1 = button.addListener(() => { });
let subscription2 = button.addListener(() => { });
const button = new DashButton(MAC_ADDRESS);
const subscription1 = button.addListener(() => { });
const subscription2 = button.addListener(() => { });
expect(mockSession.listenerCount('packet')).toBe(1);

@@ -184,6 +228,6 @@ subscription1.remove();

test(`doesn't throw if you remove a subscription twice`, () => {
let mockSession = pcap.createSession(NetworkInterfaces.getDefault());
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
pcap.createSession.mockReturnValueOnce(mockSession);
let button = new DashButton(MAC_ADDRESS);
let subscription = button.addListener(() => { });
const button = new DashButton(MAC_ADDRESS);
const subscription = button.addListener(() => { });
subscription.remove();

@@ -194,10 +238,10 @@ expect(mockSession.listenerCount('packet')).toBe(0);

test(`closes the pcap session when no more buttons are listening`, () => {
let mockSession = pcap.createSession(NetworkInterfaces.getDefault());
const mockSession = pcap.createSession(NetworkInterfaces.getDefault());
pcap.createSession.mockReturnValueOnce(mockSession);
let button1Listener = jest.fn();
let button2Listener = jest.fn();
let button1 = new DashButton(MAC_ADDRESS);
let subscription1 = button1.addListener(button1Listener);
let button2 = new DashButton('66:77:88:99:aa:bb');
let subscription2 = button2.addListener(button2Listener);
const button1Listener = jest.fn();
const button2Listener = jest.fn();
const button1 = new DashButton(MAC_ADDRESS);
const subscription1 = button1.addListener(button1Listener);
const button2 = new DashButton('66:77:88:99:aa:bb');
const subscription2 = button2.addListener(button2Listener);
subscription1.remove();

@@ -209,31 +253,2 @@ expect(mockSession.close).not.toHaveBeenCalled();

});
function createMockArpProbe(sourceMacAddress) {
let decimals = sourceMacAddress.split(':').map(hex => parseInt(hex, 16));
assert_1.default(decimals.length === 6, 'MAC addresses must be six bytes');
return {
link_type: 'LINKTYPE_ETHERNET',
// prettier-ignore
header: Buffer.from([
249, 133, 27, 86,
137, 239, 1, 0,
42, 0, 0, 0,
42, 0, 0, 0,
]),
// prettier-ignore
buf: Buffer.from([
255, 255, 255, 255, 255, 255,
...decimals,
8, 6,
0, 1,
8, 0,
6,
4,
0, 1,
...decimals,
0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
10, 0, 10, 20,
])
};
}
//# sourceMappingURL=DashButton-test.js.map

@@ -25,9 +25,9 @@ "use strict";

test(`converts arrays of decimal numbers to hex strings`, () => {
let decimals = [115, 107, 32, 146, 92, 19];
let hex = MacAddresses.decimalToHex(decimals);
const decimals = [115, 107, 32, 146, 92, 19];
const hex = MacAddresses.decimalToHex(decimals);
expect(hex).toBe('73:6b:20:92:5c:13');
});
test(`left-pads hex digits with zeros`, () => {
let decimals = [0, 1, 2, 3, 4, 5];
let hex = MacAddresses.decimalToHex(decimals);
const decimals = [0, 1, 2, 3, 4, 5];
const hex = MacAddresses.decimalToHex(decimals);
expect(hex).toBe('00:01:02:03:04:05');

@@ -34,0 +34,0 @@ });

@@ -28,19 +28,3 @@ "use strict";

jest.mock('os');
describe('NetworkInterfaces', () => {
test(`returns null if it can't find an external interface`, () => {
os_1.default.networkInterfaces.mockImplementation(() => {
return { lo0: loopbackInterfaces };
});
let interfaceName = NetworkInterfaces.getDefault();
expect(interfaceName).toBe(null);
});
test(`returns the first external interface it finds`, () => {
os_1.default.networkInterfaces.mockImplementation(() => {
return { lo0: loopbackInterfaces, en0: wifiInterfaces };
});
let interfaceName = NetworkInterfaces.getDefault();
expect(interfaceName).toBe('en0');
});
});
let loopbackInterfaces = [
const loopbackInterfaces = [
{

@@ -70,3 +54,3 @@ address: '::1',

];
let wifiInterfaces = [
const wifiInterfaces = [
{

@@ -88,2 +72,18 @@ address: 'fe80::bae8:56ff:fe37:84c0',

];
describe('NetworkInterfaces', () => {
test(`returns null if it can't find an external interface`, () => {
os_1.default.networkInterfaces.mockImplementation(() => {
return { lo0: loopbackInterfaces };
});
const interfaceName = NetworkInterfaces.getDefault();
expect(interfaceName).toBe(null);
});
test(`returns the first external interface it finds`, () => {
os_1.default.networkInterfaces.mockImplementation(() => {
return { lo0: loopbackInterfaces, en0: wifiInterfaces };
});
const interfaceName = NetworkInterfaces.getDefault();
expect(interfaceName).toBe('en0');
});
});
//# sourceMappingURL=NetworkInterfaces-test.js.map

@@ -32,3 +32,3 @@ #!/usr/bin/env node

if (require.main === module) {
let parser = yargs_1.default
const parser = yargs_1.default
.usage('Usage: $0 <command> [options]')

@@ -47,4 +47,4 @@ .command('scan', 'Scan for DHCP requests and ARP probes')

});
let { argv } = parser;
let commands = new Set(argv._);
const { argv } = parser;
const commands = new Set(argv._);
if (!commands.size) {

@@ -54,8 +54,8 @@ parser.showHelp();

else if (commands.has('scan')) {
let interfaceName = argv.interface;
let pcapSession = Packets.createCaptureSession(interfaceName);
const interfaceName = argv.interface;
const pcapSession = Packets.createCaptureSession(interfaceName);
pcapSession.addListener('packet', rawPacket => {
let packet = pcap_1.default.decode(rawPacket);
const packet = pcap_1.default.decode(rawPacket);
// console.log('Buffer:', packet.payload.payload.payload.data.toString('hex'));
let sourceMacAddress = MacAddresses.getEthernetSource(packet);
const sourceMacAddress = MacAddresses.getEthernetSource(packet);
console.log('Detected a DHCP request or ARP probe from %s', sourceMacAddress);

@@ -62,0 +62,0 @@ });

@@ -32,2 +32,14 @@ "use strict";

const Packets = __importStar(require("./Packets"));
class Subscription {
constructor(onRemove) {
this._remove = onRemove;
}
remove() {
if (!this._remove) {
return;
}
this._remove();
delete this._remove;
}
}
let pcapSession;

@@ -45,4 +57,6 @@ function getPcapSession(interfaceName) {

constructor(macAddress, options = {}) {
this._isDebounced = false;
this._macAddress = macAddress.toLowerCase();
this._networkInterface = options.networkInterface || nullthrows_1.default(NetworkInterfaces.getDefault());
this._debounceTimeMs = options.debounceTimeMs || 500;
this._packetListener = this._handlePacket.bind(this);

@@ -54,3 +68,3 @@ this._dashListeners = new Set();

if (!this._dashListeners.size) {
let session = getPcapSession(this._networkInterface);
const session = getPcapSession(this._networkInterface);
session.addListener('packet', this._packetListener);

@@ -61,3 +75,3 @@ }

// errors they may throw.
let guardedListener = this._createGuardedListener(listener);
const guardedListener = this._createGuardedListener(listener);
this._dashListeners.add(guardedListener);

@@ -67,3 +81,3 @@ return new Subscription(() => {

if (!this._dashListeners.size) {
let session = getPcapSession(this._networkInterface);
const session = getPcapSession(this._networkInterface);
session.removeListener('packet', this._packetListener);

@@ -91,4 +105,4 @@ if (!session.listenerCount('packet')) {

}
let packet = pcap_1.default.decode(rawPacket);
let macAddress = MacAddresses.getEthernetSource(packet);
const packet = pcap_1.default.decode(rawPacket);
const macAddress = MacAddresses.getEthernetSource(packet);
if (macAddress !== this._macAddress) {

@@ -98,8 +112,13 @@ return;

this._isResponding = true;
// debounce the button push
this._isDebounced = true;
setTimeout(() => {
this._isDebounced = false;
}, this._debounceTimeMs);
try {
// The listeners are guarded so this should never throw, but wrap it in try-catch to be
// defensive
let listeners = Array.from(this._dashListeners);
let errors = await Promise.all(listeners.map(listener => listener(packet)));
for (let error of errors) {
const listeners = Array.from(this._dashListeners);
const errors = await Promise.all(listeners.map(listener => listener(packet)));
for (const error of errors) {
if (error) {

@@ -116,14 +135,2 @@ console.error(`Listener threw an uncaught error:\n${error.stack}`);

exports.DashButton = DashButton;
class Subscription {
constructor(onRemove) {
this._remove = onRemove;
}
remove() {
if (!this._remove) {
return;
}
this._remove();
delete this._remove;
}
}
//# sourceMappingURL=DashButton.js.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decimalToHex = exports.getEthernetSource = void 0;
exports.getEthernetSource = exports.decimalToHex = void 0;
function decimalToHex(numbers) {
const hexStrings = numbers.map(decimal => decimal.toString(16).padStart(2, '0'));
return hexStrings.join(':');
}
exports.decimalToHex = decimalToHex;
function getEthernetSource(packet) {

@@ -8,7 +13,2 @@ return decimalToHex(packet.payload.shost.addr);

exports.getEthernetSource = getEthernetSource;
function decimalToHex(numbers) {
let hexStrings = numbers.map(decimal => decimal.toString(16).padStart(2, '0'));
return hexStrings.join(':');
}
exports.decimalToHex = decimalToHex;
//# sourceMappingURL=MacAddresses.js.map

@@ -9,5 +9,5 @@ "use strict";

function getDefault() {
let interfaces = os_1.default.networkInterfaces();
let names = Object.keys(interfaces);
for (let name of names) {
const interfaces = os_1.default.networkInterfaces();
const names = Object.keys(interfaces);
for (const name of names) {
if (interfaces[name].every(iface => !iface.internal)) {

@@ -14,0 +14,0 @@ return name;

{
"name": "@jamy/dash-button",
"version": "3.2.0",
"version": "3.2.1",
"description": "A small server that reacts to Amazon Dash buttons on your WiFi network",

@@ -5,0 +5,0 @@ "main": "build/DashButton.js",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc