Compare commits
5 Commits
d11aac5599
...
1aae9d5e71
Author | SHA1 | Date | |
---|---|---|---|
1aae9d5e71 | |||
6bc248b667 | |||
0cbbecbd2c | |||
368b6585ba | |||
4f1463eb4f |
16
package-lock.json
generated
16
package-lock.json
generated
@ -10,7 +10,8 @@
|
|||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@influxdata/influxdb-client": "^1.20.0",
|
"@influxdata/influxdb-client": "^1.20.0",
|
||||||
"log4js": "^6.3.0"
|
"log4js": "^6.3.0",
|
||||||
|
"luxon": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@influxdata/influxdb-client": {
|
"node_modules/@influxdata/influxdb-client": {
|
||||||
@ -88,6 +89,14 @@
|
|||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/luxon": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/luxon/-/luxon-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-6VQVNw7+kQu3hL1ZH5GyOhnk8uZm21xS7XJ/6vDZaFNcb62dpFDKcH8TI5NkoZOdMRxr7af7aYGrJlE/Wv0i1w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@ -187,6 +196,11 @@
|
|||||||
"streamroller": "^2.2.4"
|
"streamroller": "^2.2.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"luxon": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/luxon/-/luxon-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-6VQVNw7+kQu3hL1ZH5GyOhnk8uZm21xS7XJ/6vDZaFNcb62dpFDKcH8TI5NkoZOdMRxr7af7aYGrJlE/Wv0i1w=="
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@influxdata/influxdb-client": "^1.20.0",
|
"@influxdata/influxdb-client": "^1.20.0",
|
||||||
"log4js": "^6.3.0"
|
"log4js": "^6.3.0",
|
||||||
|
"luxon": "^2.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ const PacketType = {
|
|||||||
ProbeRequest: 'ProbeRequest',
|
ProbeRequest: 'ProbeRequest',
|
||||||
ProbeResponse: 'ProbeResponse',
|
ProbeResponse: 'ProbeResponse',
|
||||||
Data: 'Data',
|
Data: 'Data',
|
||||||
|
MoreData: 'MoreData',
|
||||||
RequestToSend: 'RequestToSend',
|
RequestToSend: 'RequestToSend',
|
||||||
ClearToSend: 'ClearToSend',
|
ClearToSend: 'ClearToSend',
|
||||||
Acknowledgment: 'Acknowledgment',
|
Acknowledgment: 'Acknowledgment',
|
||||||
|
96
src/streamHandler/PacketStreamFactory.js
Normal file
96
src/streamHandler/PacketStreamFactory.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
const logger = require.main.require("./helper/logger.js")("PacketStreamFactory");
|
||||||
|
const { Transform } = require('stream');
|
||||||
|
const { DateTime } = require("luxon");
|
||||||
|
const { PacketType, Packet, PacketWithSSID, BeaconPacket, ProbeRequestPacket, ProbeResponsePacket } = require.main.require('./dto/Packet.js');
|
||||||
|
|
||||||
|
const PACKET_TYPE_MAP = {
|
||||||
|
"Beacon": PacketType.Beacon,
|
||||||
|
"Probe Request": PacketType.ProbeRequest,
|
||||||
|
"Probe Response": PacketType.ProbeResponse,
|
||||||
|
"Data": PacketType.Data,
|
||||||
|
"More Data": PacketType.MoreData,
|
||||||
|
"Request-To-Send": PacketType.RequestToSend,
|
||||||
|
"Clear-To-Send": PacketType.ClearToSend,
|
||||||
|
"Acknowledgment": PacketType.Acknowledgment,
|
||||||
|
"BA": PacketType.BlockAcknowledgment
|
||||||
|
};
|
||||||
|
const PACKET_TYPES_REGEX = Object.keys(PACKET_TYPE_MAP).join('|');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from text-blocks and convert them to Packet
|
||||||
|
*/
|
||||||
|
class PacketStreamFactory extends Transform{
|
||||||
|
matcher;
|
||||||
|
withholdLastBlock;
|
||||||
|
matchAllOnFlush;
|
||||||
|
|
||||||
|
constructor(){
|
||||||
|
super({
|
||||||
|
readableObjectMode: true,
|
||||||
|
writableObjectMode: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_transform(chunk, encoding, next){
|
||||||
|
let packet = new Packet();
|
||||||
|
|
||||||
|
const lines = chunk.split('\n');
|
||||||
|
const header = lines.splice(0, 1)[0]; // Grab first line, 'lines' is now the payload
|
||||||
|
this._handleHeader(packet, header);
|
||||||
|
this._handlePayload(packet, lines);
|
||||||
|
|
||||||
|
logger.debug(packet);
|
||||||
|
|
||||||
|
this.read();
|
||||||
|
next(null, packet); // Get next chunk
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleHeader(packet, data){
|
||||||
|
// Convert time to epoch-micros Unfortunately luxon doesnt use micros, but millis as smallest time-unit requiring some "hacks"
|
||||||
|
packet.timestampMicros = DateTime.fromISO(data.slice(0, 12)).toSeconds() + data.slice(12, 15)/1000000;
|
||||||
|
|
||||||
|
packet.dataRate = Number(data.match(/(^| )([0-9]+(\.[0-9]+)?) Mb\/s($| )/i)[2]);
|
||||||
|
packet.frequency = Number(data.match(/(^| )([0-9]{4}) MHz($| )/i)[2]);
|
||||||
|
|
||||||
|
let signalStrMatch = data.match(/(^| )(-[0-9]{2})dBm Signal($| )/i);
|
||||||
|
if(signalStrMatch) packet.signal = Number(signalStrMatch[2]);
|
||||||
|
else packet.signal = -100;
|
||||||
|
|
||||||
|
let packetTypeStrMatch = data.match(new RegExp(`(^|.{80} )(${PACKET_TYPES_REGEX})($| )`, 'i'));
|
||||||
|
let packetTypeStr;
|
||||||
|
if(packetTypeStrMatch) {
|
||||||
|
packetTypeStr = packetTypeStrMatch[2];
|
||||||
|
packet.packetType = PACKET_TYPE_MAP[packetTypeStr];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
packet.packetType = PacketType.Unknown;
|
||||||
|
|
||||||
|
let srcMacMatch = data.match(/(^| )(SA|TA):(.{17})($| )/i);
|
||||||
|
if(srcMacMatch) packet.srcMac = srcMacMatch[3];
|
||||||
|
|
||||||
|
let dstMacMatch = data.match(/(^| )(DA|RA):(.{17})($| )/i);
|
||||||
|
if(dstMacMatch) packet.dstMac = dstMacMatch[3];
|
||||||
|
|
||||||
|
let bssidMatch = data.match(/(^| )BSSID:(.{17})($| )/i)
|
||||||
|
if(bssidMatch) packet.bssid = bssidMatch[2];
|
||||||
|
|
||||||
|
// Cover special cases with more data
|
||||||
|
switch(packet.packetType){
|
||||||
|
case PacketType.Beacon:
|
||||||
|
case PacketType.ProbeRequest:
|
||||||
|
case PacketType.ProbeResponse:
|
||||||
|
packet = Object.assign(new PacketWithSSID(), packet); // Create new, more specific, packet and copy old data over
|
||||||
|
packet.ssid = data.match(new RegExp(`(^| )${packetTypeStr} `+'\\'+`((.{0,32})`+'\\'+`)($| )`, 'i'))[2];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_handlePayload(packet, data){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Specify exports
|
||||||
|
module.exports = {
|
||||||
|
PacketStreamFactory
|
||||||
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
const logger = require.main.require("./helper/logger.js")("RegexBlockStream");
|
||||||
const { Transform } = require('stream')
|
const { Transform } = require('stream')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,20 +23,19 @@ class RegexBlockStream extends Transform{
|
|||||||
this.matcher = matcher;
|
this.matcher = matcher;
|
||||||
this.withholdLastBlock = withholdLastBlock;
|
this.withholdLastBlock = withholdLastBlock;
|
||||||
this.matchAllOnFlush = matchAllOnFlush;
|
this.matchAllOnFlush = matchAllOnFlush;
|
||||||
|
|
||||||
this._buffer = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_transform(chunk, encoding, next){
|
_transform(chunk, encoding, next){
|
||||||
chunk = this._buffer + chunk; // Add previous buffer to current chunk
|
chunk = this.readableBuffer.length? this.readableBuffer.join() + chunk: chunk; // Add previous buffer to current chunk
|
||||||
|
this.readableBuffer.length && this.readableBuffer.clear(); // Clear buffer once we read it
|
||||||
|
|
||||||
let matches = chunk.match(this.matcher); // Match
|
let matches = chunk.match(this.matcher); // Match
|
||||||
if(matches){
|
if(matches){
|
||||||
if(this.withholdLastBlock) matches.pop(); // Remove last if we want to withhold it
|
if(this.withholdLastBlock) matches.pop(); // Remove last if we want to withhold it
|
||||||
chunk = this._writeMatches(chunk, matches);
|
chunk = this._writeMatches(matches, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._buffer = chunk; // Store remaining data in buffer
|
this.readableBuffer.push(chunk); // Store remaining data in buffer
|
||||||
next(); // Get next chunk
|
next(); // Get next chunk
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,8 +51,9 @@ class RegexBlockStream extends Transform{
|
|||||||
|
|
||||||
_flush(next){
|
_flush(next){
|
||||||
if(matchAllOnFlush){ // When requested, we'll match one last time over the remaining buffer
|
if(matchAllOnFlush){ // When requested, we'll match one last time over the remaining buffer
|
||||||
let matches = this._buffer.match(this.matcher); // Match remaining buffer
|
let chunk = this.readableBuffer.toString();
|
||||||
_writeMatches(this._buffer); // Write matches including last element
|
let matches = chunk.match(this.matcher); // Match remaining buffer
|
||||||
|
_writeMatches(matches); // Write matches including last element
|
||||||
}
|
}
|
||||||
|
|
||||||
next(); // Tell system we are done
|
next(); // Tell system we are done
|
||||||
|
Loading…
x
Reference in New Issue
Block a user