*Add heartbeat support to protocol

This commit is contained in:
Derrick Hammer 2022-12-05 06:59:46 -05:00
parent c67bc2bba7
commit 8ecd021a1d
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
3 changed files with 67 additions and 4 deletions

View File

@ -7,6 +7,7 @@ enum Type {
DISCONNECTED = 4;
ADD_ITEM = 5;
REMOVE_ITEM = 6;
HEARTBEAT = 7;
}
message Message {

View File

@ -56,7 +56,7 @@ export default class DHTCache extends EventEmitter {
this.flood.on("message", (message, id) => this.onGetBroadcast(message, id));
this.swarm.on("connection", (peer: any) =>
this.flood.send(peer, b4a.from("hello"), 0)
this.send(peer, b4a.from("hello"))
);
[...this.swarm.peers.values()]
@ -69,6 +69,8 @@ export default class DHTCache extends EventEmitter {
});
this._ensurePeer(this.id);
setInterval(() => this._heartbeatCheck(), 5 * 1000);
setInterval(() => this._emitHeartbeat(), 60 * 1000);
}
private _cache: Set<string>;
@ -163,8 +165,8 @@ export default class DHTCache extends EventEmitter {
this.flood.broadcast(message, ttl);
}
public send(message: any) {
this.flood.send(message, 0);
public send(peer: any, message: any) {
this.flood.send(peer, message, 0);
}
protected addPeerHandler(peer: any) {
@ -186,6 +188,8 @@ export default class DHTCache extends EventEmitter {
id,
});
this._emitHeartbeat(peer);
if (this.bootstrapped) {
return;
}
@ -278,6 +282,15 @@ export default class DHTCache extends EventEmitter {
} else if (type === Type.BOOTSTRAP_RESPONSE) {
const { bootstrap } = decoded;
this._bootstrapFrom(bootstrap);
} else if (type === Type.HEARTBEAT) {
let { id: toId, signature, data: bufData } = decoded;
toId = b4a.from(toId as Uint8Array);
if (signature && crypto.verify(bufData, signature, id)) {
this._addEntityConnection(id, toId as Buffer);
this._setEntity(toId as Buffer, { heartbeat: Date.now() });
}
}
}
@ -447,4 +460,49 @@ export default class DHTCache extends EventEmitter {
}
})();
}
private _heartbeatCheck() {
for (const peer of this.connectedTo) {
const pubkey = b4a.from(peer, "hex");
const heartbeat = this.graph.node.get(peer)?.heartbeat;
const conn = this.swarm._allConnections.get(pubkey);
if (!conn) {
this.onRemovePeer({ remotePublicKey: pubkey });
continue;
}
if (heartbeat > 0 && Date.now() - heartbeat > 60 * 1000) {
conn.end();
}
}
}
private _emitHeartbeat(peer?: any) {
let peers = [...this.connectedTo];
if (peer) {
// @ts-ignore
peers = [b4a.from(peer.remotePublicKey).toString("hex")];
}
for (const peer of peers) {
const pubkey = b4a.from(peer, "hex");
const conn = this.swarm._allConnections.get(pubkey);
if (!conn) {
continue;
}
const data = b4a.from(Uint8Array.from([1]));
this.send(
conn,
this._compileMessage({
type: Type.HEARTBEAT,
id: this.id,
data,
signature: crypto.sign(data, this.swarm.keyPair.secretKey),
})
);
}
}
}

View File

@ -78,7 +78,11 @@ export enum Type {
/**
* @generated from protobuf enum value: REMOVE_ITEM = 6;
*/
REMOVE_ITEM = 6
REMOVE_ITEM = 6,
/**
* @generated from protobuf enum value: HEARTBEAT = 7;
*/
HEARTBEAT = 7
}
// @generated message type with reflection information, may provide speed optimized methods
class Message$Type extends MessageType<Message> {