connection: fix some edge cases
This commit is contained in:
parent
c43aeb6c3b
commit
bbc5d54158
1 changed files with 35 additions and 7 deletions
|
@ -15,9 +15,13 @@ import { encrypt_bytes, decrypt_bytes } from '../crypto/secretbox.mjs';
|
||||||
* Represents a connection to a single endpoint.
|
* Represents a connection to a single endpoint.
|
||||||
*/
|
*/
|
||||||
class Connection extends EventEmitter {
|
class Connection extends EventEmitter {
|
||||||
constructor(secret_join) {
|
constructor(secret_join, socket) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.socket = socket;
|
||||||
|
|
||||||
|
this.rekey_last = null;
|
||||||
|
this.rekey_interval = 30 * 60 * 1000; // 30 minutes
|
||||||
this.session_key = Buffer.from(secret_join, "base64");
|
this.session_key = Buffer.from(secret_join, "base64");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,9 +38,14 @@ class Connection extends EventEmitter {
|
||||||
address, port
|
address, port
|
||||||
});
|
});
|
||||||
await once(this.socket, "connect");
|
await once(this.socket, "connect");
|
||||||
|
|
||||||
|
await this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
this.socket.setKeepAlive(true);
|
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 = new FramedTransport(this.socket);
|
||||||
this.framer.on("frame", this.handle_frame);
|
this.framer.on("frame", this.handle_frame);
|
||||||
|
@ -44,8 +53,13 @@ class Connection extends EventEmitter {
|
||||||
this.read_task = read_loop();
|
this.read_task = read_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
async rekey() {
|
||||||
this.socket.destroy();
|
this.rekey_last = new Date();
|
||||||
|
this.session_key = await rekey(this.socket, this.session_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
async destroy() {
|
||||||
|
await this.framer.destroy();
|
||||||
this.emit("destroy");
|
this.emit("destroy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,14 +83,28 @@ class Connection extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(message) {
|
async send(message) {
|
||||||
// TODO: Implement a binary frame-based protocol here instead? It would be 33% more bandwidth efficient.
|
if(new Date() - this.rekey_last > this.rekey_interval)
|
||||||
// Perhaps <length> <data>? If messages are too long, we'll have to do something about that though....
|
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
|
// 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);
|
let payload = JSON.stringify(message);
|
||||||
payload = encrypt_bytes(this.session_key, payload);
|
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;
|
export default Connection;
|
||||||
|
|
Loading…
Reference in a new issue