diff --git a/src/lib/transport/Connection.mjs b/src/lib/transport/Connection.mjs index a498e09..e2b288a 100644 --- a/src/lib/transport/Connection.mjs +++ b/src/lib/transport/Connection.mjs @@ -15,9 +15,13 @@ import { encrypt_bytes, decrypt_bytes } from '../crypto/secretbox.mjs'; * Represents a connection to a single endpoint. */ class Connection extends EventEmitter { - constructor(secret_join) { + constructor(secret_join, socket) { super(); + this.socket = socket; + + this.rekey_last = null; + this.rekey_interval = 30 * 60 * 1000; // 30 minutes this.session_key = Buffer.from(secret_join, "base64"); } @@ -34,9 +38,14 @@ class Connection extends EventEmitter { address, port }); await once(this.socket, "connect"); + + await this.init(); + } + + async init() { this.socket.setKeepAlive(true); - this.session_key = await rekey(this.socket, this.session_key); + await this.rekey(); this.framer = new FramedTransport(this.socket); this.framer.on("frame", this.handle_frame); @@ -44,8 +53,13 @@ class Connection extends EventEmitter { this.read_task = read_loop(); } - destroy() { - this.socket.destroy(); + async rekey() { + this.rekey_last = new Date(); + this.session_key = await rekey(this.socket, this.session_key); + } + + async destroy() { + await this.framer.destroy(); this.emit("destroy"); } @@ -69,14 +83,28 @@ class Connection extends EventEmitter { } async send(message) { - // TODO: Implement a binary frame-based protocol here instead? It would be 33% more bandwidth efficient. - // Perhaps ? If messages are too long, we'll have to do something about that though.... + if(new Date() - this.rekey_last > this.rekey_interval) + await this.rekey(); + // TODO: Consider https://devdocs.io/node/crypto#crypto.createCipheriv() - which lets us use any openssl ciphers we like - e.g. ChaCha20-Poly1305 let payload = JSON.stringify(message); payload = encrypt_bytes(this.session_key, payload); - await this., payload); + + await this.framer.write(payload); } } +Connection.Wrap = async function(secret_join, socket) { + const socket = new Connection(secret_join, socket); + await socket.init(); + + return socket; +} + +Connection.Create = async function(secret_join, address, port) { + const socket = new Connection(secret_join); + socket.connect(address, port); +} + export default Connection;