OpenHausIO / backend

HTTP API for the OpenHaus SmartHome/IoT solution
https://docs.open-haus.io
6 stars 2 forks source link

Refactor interface stream/socket handling #460

Closed mStirner closed 5 months ago

mStirner commented 6 months ago

The initial idea/current interface implementation is garbage. There needs to be a way to open multiple sockets to a device.

interface.createSocket() tells the connector to create a bridge between the device interface (e.g. tcp://192.168.122.53:8123) and the interface websocket endpoint.

This connections is then converted into a stream, which is returned by .createSocket(). (Maybe rename the function)

For this, there needs a "management" websocket connections, just like the current /api/events one. Overt that connection the connector is told, "bridge from A to B" as described above.

mStirner commented 6 months ago

Relation: #458

mStirner commented 6 months ago

Couple of things to be noted:

How could be a "alive check" implemented without anything mentioned above?

mStirner commented 6 months ago

interface.bridge/socket/whatever() should emit on the component scope a "socket" event with payload:

{
  "type": "request",
  "uuid": "cf459c67-2f23-41a9-b9f5-70096114fdda",
  "interface": "6647482a09095ddc6a03fc47" 
  "device": "66474820ad108d95b47b2481",
  "protocol": "tcp|udp|raw|icmp",
  "ping" true
}

This object is forwarded to all connectors via websocket on a endpoint (e.g. /api/system/connector). Each receiving connector checks then if filter rules apply or if they are responsible for this device/network subnet/etc.pp.

If so, the connector creates a websocket briddge between the interface and the corresponding underlaying networksocket, with a query string arguments socket=true&uuid=cf459c67-2f23-41a9-b9f5-70096114fdda&type=response. Full URL: http://open-haus.lan:8080/api/devices/6647496087d475120b295d3a/interfaces/664749688b0b43f41ec55e45?socket=true&uuid=cf459c67-2f23-41a9-b9f5-70096114fdda&type=response

This websocket connection is then transformed into a stream, which is passed through the adapter stack configured. At last, the adapter stack stream is returned via also a emitted "socket" event on the component scoped, with the object from above, type set to "response".

The properties "protocol" & "ping" are set to create a icmp ping request to the host/ip address set on the interface. This allows to check if the device is "online".

The described mechanism above is just a draft and need do be fine tuned. Especially the icmp/ping/raw part.

mStirner commented 6 months ago

Add a handshake/signing method, that no one can hijack the connection request/attempt? Asked chatgpt for a simple signing/handshake:

const crypto = require("crypto");
const SECRET = "S3c4et";
const challenge = crypto.randomBytes(16).toString('hex');

// server
const expectedHash = crypto.createHash('sha256').update(challenge + SECRET).digest('hex');

// client
const hash = crypto.createHash('sha256').update(challenge + SECRET).digest('hex');

if (receivedHash === expectedHash) {
            console.log('Client authorized.');
} else {
            console.log('Client auth error');
}

Use something in combination like the auth token as secret?

mStirner commented 1 month ago

Some modification of class.interface.js stream/bridge handling. Just for documentation purpose.

solution-works-no-2.txt solution-works-no-1.txt solution-works.txt