Initial idea commit

This commit is contained in:
Sören Beye 2021-07-26 20:27:40 +02:00
parent d972121d93
commit 3f5228fccc
7 changed files with 79 additions and 12 deletions

View File

@ -105,6 +105,10 @@ class Tools {
load: os.loadavg().map(v => v / os.cpus().length)
};
}
static IS_ASCII(str) {
return /^[\x00-\x7F]*$/.test(str);
}
}
module.exports = Tools;

View File

@ -1,6 +1,6 @@
const dgram = require("dgram");
const Logger = require("../Logger");
const MiioSocket = require("./MiioSocket");
const MiioUDPSocket = require("./MiioUDPSocket");
class Dummycloud {
/**
@ -29,7 +29,7 @@ class Dummycloud {
this.socket.bind(Dummycloud.PORT, this.bindIP);
this.miioSocket = new MiioSocket({
this.miioUDPSocket = new MiioUDPSocket({
socket: this.socket,
token: options.cloudSecret,
onMessage: this.handleMessage.bind(this),
@ -48,7 +48,7 @@ class Dummycloud {
// some default handling.
switch (msg.method) {
case "_otc.info":
this.miioSocket.sendMessage({
this.miioUDPSocket.sendMessage({
"id": msg.id,
"result": {
"otc_list": [{"ip": this.spoofedIP, "port": Dummycloud.PORT}],
@ -81,12 +81,12 @@ class Dummycloud {
* @returns {Promise<void>}
*/
async shutdown() {
await this.miioSocket.shutdown();
await this.miioUDPSocket.shutdown();
}
}
/**
* @constant
* The miio port the dummycloud listens on.
* The miio UDP port the dummycloud listens on.
*/
Dummycloud.PORT = 8053;

View File

@ -21,7 +21,7 @@ const TRACE_METHODS = [
* Performs encryption and decryption, and tracks message ids and retries to provide an easy
* promise interface.
*/
class MiioSocket {
class MiioUDPSocket {
/**
* @param {object} options
* @param {import("dgram").Socket} options.socket
@ -250,6 +250,6 @@ class MiioSocket {
}
/** The default remote port. @const {int} */
MiioSocket.PORT = 54321;
MiioUDPSocket.PORT = 54321;
module.exports = MiioSocket;
module.exports = MiioUDPSocket;

View File

@ -14,7 +14,7 @@ const STATES = Object.freeze({
*/
class RetryWrapper {
/**
* @param {import("./MiioSocket")} socket
* @param {import("./MiioUDPSocket")} socket
* @param {() => Buffer} tokenProvider
*/
constructor(socket, tokenProvider) {

View File

@ -8,7 +8,7 @@ const path = require("path");
const Dummycloud = require("../miio/Dummycloud");
const Logger = require("../Logger");
const MiioSocket = require("../miio/MiioSocket");
const MiioUDPSocket = require("../miio/MiioUDPSocket");
const NotImplementedError = require("../core/NotImplementedError");
const RetryWrapper = require("../miio/RetryWrapper");
const ValetudoRobot = require("../core/ValetudoRobot");
@ -38,7 +38,7 @@ class MiioValetudoRobot extends ValetudoRobot {
const socket = dgram.createSocket("udp4");
socket.bind();
return new MiioSocket({
return new MiioUDPSocket({
socket: socket,
token: this.localSecret,
onMessage: () => {},

View File

@ -0,0 +1,52 @@
const net = require("net");
const http = require("http");
const Tools = require("../Tools");
//Adapted from https://stackoverflow.com/a/42019773/10951033
class DualUseTCPServer {
/**
* @param {*} handler
*/
constructor(handler) {
this.server = net.createServer(socket => {
socket.once('data', buffer => {
// Pause the socket
socket.pause();
//ASCII = HTTP, lol
if (Tools.IS_ASCII(buffer.toString())) {
socket.unshift(buffer);
this.httpServer.emit("connection", socket);
} else if (this.miioServer) {
socket.unshift(buffer);
this.miioServer.emit("connection", socket);
}
// As of NodeJS 10.x the socket must be
// resumed asynchronously or the socket
// connection hangs, potentially crashing
// the process. Prior to NodeJS 10.x
// the socket may be resumed synchronously.
process.nextTick(() => socket.resume());
});
});
this.miioServer = undefined;
this.httpServer = http.createServer(handler);
}
getServer() {
return this.server;
}
setMiioServer(miioServer) {
this.miioServer = miioServer;
}
}
module.exports = DualUseTCPServer;

View File

@ -22,6 +22,7 @@ const MiioValetudoRobot = require("../robots/MiioValetudoRobot");
const NTPClientRouter = require("./NTPClientRouter");
const SystemRouter = require("./SystemRouter");
const TimerRouter = require("./TimerRouter");
const DualUseTCPServer = require("../utils/DualUseTCPServer");
class WebServer {
/**
@ -72,7 +73,9 @@ class WebServer {
}
});
const server = http.createServer(this.app);
this.dualUseTCPServer = new DualUseTCPServer(this.app);
const server = this.dualUseTCPServer.getServer();
this.loadApiSpec();
this.validator = function noOpValidationMiddleware(req, res, next) {
@ -208,6 +211,14 @@ class WebServer {
});
}
/**
* @public
* @returns {DualUseTCPServer}
*/
getDualUseTCPServer() {
return this.dualUseTCPServer;
}
/**
* @private
*/