-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtunnelDataHandler.js
172 lines (150 loc) · 5.97 KB
/
tunnelDataHandler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
const endpoint = require("./endpoint/device");
const endpointDB = require("./endpoint/db");
const bridge = require("./bridge/connection");
const dataHB = require("./endpoint/dataHBHandler");
const logger = require("./logger");
function tunnelRawDataHandler(clientSocket, data) {
//Parse string by expected
const dataStr = data.toString("ascii");
const dataParts = dataStr.split(";");
if (dataParts.length > 1) {
if (dataParts[0] === "beat" && dataParts.length == 5) {
//HEARTHBEAT from elfin devices
//Example: beat;uuid:undifined;mac:%MAC;host:%HOST
logger.silly(`Received hearthbeat: ${dataStr}`);
//Parse incoming data
const user = dataParts[1];
const macAddress = dataParts[2];
const hostName = dataParts[3];
const deviceType = dataParts[4];
const deviceObject = endpoint.createActiveDevice(user, hostName, macAddress, clientSocket);
//Add or update device in the activeDevices list
endpoint.addOrUpdateDevice(deviceObject);
//Save new last seen date to DB
endpointDB.connectToUser(deviceObject);
} else if (dataParts[0] === "data" && dataParts.length >= 4) {
//DATA SENT from elfin
//Example: data;uuid:almafa;mac:%MAC;#PAYLOAD#
logger.silly(`Received data: ${dataStr}`);
//Parse incoming data
const user = dataParts[1];
const dev1MAC = dataParts[2];
const hostName = dataParts[3];
const deviceType = dataParts[4]; //If zero, its a elfin device (Physical device),
if (deviceType === "0") {
const deviceObject = endpoint.createActiveDevice(user, hostName, dev1MAC, clientSocket);
endpoint.addOrUpdateDevice(deviceObject);
dataHB.timerHandler(endpoint.getKey(user, dev1MAC));
}
//Get the payload from the data
const headerSize = dataParts[0].length + dataParts[1].length + dataParts[2].length + dataParts[3].length + dataParts[4].length + 5; //+5 is the length of the separators
const payload = data.subarray(headerSize, data.length);
try{
//Search for destination device
const destinationDeviceSocket = bridge.getEndpointSocket(user, clientSocket);
//Send the payload to the destination device
destinationDeviceSocket.write(payload);
}catch(e){
logger.silly(`Data forwarding error: ${e.message}`);
if(deviceType !== "0"){
clientSocket.destroy();
}
}
} else if (dataParts[0] === "connthem" && dataParts.length == 4) {
//TO CREATE a connection for user between 2 end-device
//Exapmle connthem;uuid:almafa;mac1:#MAC1#;mac2:#MAC2#
logger.info(`Received connection 2 device request: ${dataStr}`);
//----Its a legacy feature in specifiaction, but not used in the current version----
/*
const user = dataParts[1];
const dev1MAC = dataParts[2];
const dev2MAC = dataParts[3];
try {
const device1 = endpoint.getDevice(endpoint.getKey(user, dev1MAC));
const device2 = endpoint.getDevice(endpoint.getKey(user, dev2MAC));
bridge.setupSocketConnection(user, device2.clientSocket, device1.clientSocket);
clientSocket.write('{"status":"success"}' + "\n");
} catch (e) {
logger.warn(e);
clientSocket.write('{"status":"failed"}' + "\n");
}
*/
} else if (dataParts[0] === "connme" && (dataParts.length == 3 || dataParts.length == 4)) {
//TO CREATE a connection for user between incomming socket and an endpoint-device
//Exapmle connme;uuid:almafa;mac:#MAC#
logger.info(`Received connection socket-endpoint device request: ${dataStr}`);
//Parse incoming data
const user = dataParts[1];
const devMAC = dataParts[2];
const priority = dataParts[3] || 0; //Priority is optional by default 0 (Highest priority is 0, lowering by 1->) --Backward compatibility
//Search for destination device, check status and create connection
try {
//Get the device from the activeDevices list
const device = endpoint.getDevice(endpoint.getKey(user, devMAC));
//Check if the device is online
if (!endpoint.isOnline(endpoint.getKey(user, devMAC))) {
throw new Error("Device is offline.");
}
//Create a connection between the incommed and device`s socket
bridge.setupSocketConnection(user, clientSocket, device.clientSocket, priority);
//Send success message to the client
clientSocket.write('{"status":"success"}' + "\n");
} catch (e) {
logger.warn(e);
//Send failed message to the client
clientSocket.write(`{"status":"failed","reason":"${e.message}"}` + "\n");
}
} else if (dataParts[0] === "query" && dataParts.length == 2) {
//Query user`s devices
//query;userid
logger.verbose(`User query: ${dataStr}`);
const user = dataParts[1];
getDevicesJson(user).then((json) => {
json += "\n";
clientSocket.write(Buffer.from(json, "utf8"));
});
} else {
logger.warn(`Invalid payload: ${dataStr}`);
}
} else {
//logger.warn(`Invalid payload: ${Buffer.from(dataStr, 'ascii').toString('hex')}`);
logger.warn(`Invalid payload: ${dataStr}`);
}
}
async function getDevicesJson(user) {
try {
const devices = await endpointDB.getDevices(user);
const jsonArray = devices.map((dbDevice) => ({
hostname: dbDevice.hostName,
macaddress: dbDevice.macAddress,
lastseendate: convertESTto24Time(dbDevice.lastSeenDate),
status: calcOnline(dbDevice.lastSeenDate),
}));
return JSON.stringify(jsonArray);
} catch (error) {
console.error("Error fetching devices:", error);
return JSON.stringify([]);
}
}
function convertESTto24Time(estDateString) {
// Create a formatter with the desired format and set the time zone to 'America/New_York'
const formatter = new Intl.DateTimeFormat("hu-HU", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
timeZone: "Europe/Budapest",
});
// Parse the EST date string
const estDate = new Date(estDateString);
// Format the date in the 24-hour format
const formattedESTString = formatter.format(estDate);
return formattedESTString;
}
function calcOnline(date) {
return date > new Date(Date.now() - 60000) ? "online" : "offline";
}
module.exports = tunnelRawDataHandler;