Skip to content

Commit

Permalink
feat: ptp and group messaging (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
d-roak authored Jun 21, 2024
1 parent 06abbc6 commit 5c15be3
Show file tree
Hide file tree
Showing 8 changed files with 721 additions and 743 deletions.
43 changes: 43 additions & 0 deletions examples/canvas/src/handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { toString as uint8ArrayToString } from "uint8arrays/to-string";
import { ICanvas } from "./objects/canvas";

// TODO: this should be superseded by wasm and main ts-topology library
export const handleCanvasMessages = (canvas: ICanvas, e: any) => {
if (e.detail.msg.topic === "_peer-discovery._p2p._pubsub") return;
const input = uint8ArrayToString(e.detail.msg.data);
const message = JSON.parse(input);
switch (message["type"]) {
case "object_update": {
const fn = uint8ArrayToString(new Uint8Array(message["data"]));
handleObjectUpdate(canvas, fn);
break;
}
default: {
break;
}
}
};

function handleObjectUpdate(canvas: ICanvas, fn: string) {
// In this case we only have paint
// `paint(${node.getPeerId()}, [${[x, y]}], [${painting}])`
let args = fn.replace("paint(", "").replace(")", "").split(", ");
let offset_p = args[1]
.replace("[", "")
.replace("]", "")
.split(",")
.map((s) => parseInt(s, 10));
const offset: [number, number] = [offset_p[0], offset_p[1]];
let rgb_p = args[2]
.replace("[", "")
.replace("]", "")
.split(",")
.map((s) => parseInt(s, 10));
const rgb: [number, number, number] = [rgb_p[0], rgb_p[1], rgb_p[2]];

try {
canvas.paint(args[0], offset, rgb);
} catch (e) {
console.error(e);
}
}
8 changes: 7 additions & 1 deletion examples/canvas/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { TopologyNode } from "@topology-foundation/node";
import { Canvas, ICanvas } from "./objects/canvas";
import { Pixel } from "./objects/pixel";
import { GCounter } from "@topology-foundation/crdt";
import { handleCanvasMessages } from "./handlers";

const node = new TopologyNode();
let canvasCRO: ICanvas;
Expand Down Expand Up @@ -45,13 +46,18 @@ async function paint_pixel(pixel: HTMLDivElement) {

node.updateObject(
canvasCRO,
`paint(${node.getPeerId()}, ${[x, y]}, ${painting})`,
`paint(${node.getPeerId()}, [${[x, y]}], [${painting}])`,
);
}

async function init() {
await node.start();

node.addCustomGroupMessageHandler((e) => {
handleCanvasMessages(canvasCRO, e);
if (canvasCRO) render();
});

let create_button = <HTMLButtonElement>document.getElementById("create");
create_button.addEventListener("click", () => {
canvasCRO = new Canvas(node.getPeerId(), 5, 10);
Expand Down
97 changes: 30 additions & 67 deletions examples/canvas/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,19 @@
uint8-varint "^2.0.1"
uint8arrays "^5.0.0"

"@multiformats/multiaddr@^12.3.0":
version "12.3.0"
resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-12.3.0.tgz#b1422813446e5cdec4b0f6cba51f93239f390884"
integrity sha512-JQ8Gc/jgucqqvEaDTFN/AvxlYDHEE7lgEWLMYW7hKZkWggER+GvG/tVxUgUxIP8M0vFpvEHKKHE0lKzyMsgi8Q==
dependencies:
"@chainsafe/is-ip" "^2.0.1"
"@chainsafe/netmask" "^2.0.0"
"@libp2p/interface" "^1.0.0"
"@multiformats/dns" "^1.0.3"
multiformats "^13.0.0"
uint8-varint "^2.0.1"
uint8arrays "^5.0.0"

"@noble/ciphers@^0.4.0":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.4.1.tgz#977fc35f563a4ca315ebbc4cbb1f9b670bd54456"
Expand All @@ -571,11 +584,11 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/fnv1a/-/fnv1a-3.1.0.tgz#f8e46597298f6fd4c12dc901cdd4e73beb4d24fa"
integrity sha512-KV321z5m/0nuAg83W1dPLy85HpHDk7Sdi4fJbwvacWsEhAh+rZUW4ZfGcXmUIvjZg4ss2bcwNlRhJ7GBEUG08w==

"@topology-foundation/[email protected].2", "@topology-foundation/crdt@file:../../packages/crdt":
version "0.0.2"
"@topology-foundation/[email protected].5", "@topology-foundation/crdt@file:../../packages/crdt":
version "0.0.5"

"@topology-foundation/[email protected].2", "@topology-foundation/network@file:../../packages/network":
version "0.0.2"
"@topology-foundation/[email protected].5", "@topology-foundation/network@file:../../packages/network":
version "0.0.5"
dependencies:
"@chainsafe/libp2p-gossipsub" "^13.0.0"
"@chainsafe/libp2p-noise" "^15.0.0"
Expand All @@ -586,24 +599,24 @@
"@libp2p/pubsub-peer-discovery" "^10.0.2"
"@libp2p/webrtc" "^4.0.33"
"@libp2p/websockets" "^8.0.24"
"@multiformats/multiaddr" "^12.3.0"
it-pipe "^3.0.1"
libp2p "^1.6.0"
multiaddr "^10.0.1"

"@topology-foundation/node@file:../../packages/node":
version "0.0.2"
version "0.0.5"
dependencies:
"@topology-foundation/crdt" "0.0.2"
"@topology-foundation/network" "0.0.2"
"@topology-foundation/object" "0.0.2"
"@topology-foundation/crdt" "0.0.5"
"@topology-foundation/network" "0.0.5"
"@topology-foundation/object" "0.0.5"

"@topology-foundation/[email protected].2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@topology-foundation/object/-/object-0.0.2.tgz#674e019f557efba6bdbc914b5764b859fbb87a7b"
integrity sha512-/TkJvoJmmEsEB1437Y6fLlg8hOo/fK9uDy+QkQVAbRCtHRHlN4eEUIxhQqz+SAaiIc6LIbJf6uXt6ky8OHNmTA==
"@topology-foundation/[email protected].5":
version "0.0.5"
resolved "https://registry.yarnpkg.com/@topology-foundation/object/-/object-0.0.5.tgz#04651b88b948bde2aca7bf757bb298d3147d221b"
integrity sha512-CgohmrNbkwzR0MQURqKQHUCEVL03QJ3z5G60ycF08ketk5ATbXEMVybCpriX9aTZ6+EyQc+goFsveVLD3ehETA==

"@topology-foundation/object@file:../../packages/object":
version "0.0.2"
version "0.0.5"

"@tsconfig/node10@^1.0.7":
version "1.0.11"
Expand Down Expand Up @@ -1495,7 +1508,7 @@ [email protected], debug@^4.1.0:
dependencies:
ms "2.1.2"

debug@^4.3.1, debug@^4.3.4:
debug@^4.3.4:
version "4.3.5"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==
Expand Down Expand Up @@ -1597,15 +1610,6 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"

dns-over-http-resolver@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/dns-over-http-resolver/-/dns-over-http-resolver-1.2.3.tgz#194d5e140a42153f55bb79ac5a64dd2768c36af9"
integrity sha512-miDiVSI6KSNbi4SVifzO/reD8rMnxgrlnkrlkugOLQpWQTe2qMdHsZp5DmfKjxNE+/T3VAAYLQUZMv9SMr6+AA==
dependencies:
debug "^4.3.1"
native-fetch "^3.0.0"
receptacle "^1.3.2"

dns-packet@^5.2.2, dns-packet@^5.6.1:
version "5.6.1"
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f"
Expand Down Expand Up @@ -2175,11 +2179,6 @@ interpret@^2.2.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==

ip-regex@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==

[email protected]:
version "1.9.1"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
Expand Down Expand Up @@ -2226,13 +2225,6 @@ is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"

is-ip@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8"
integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==
dependencies:
ip-regex "^4.0.0"

is-loopback-addr@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz#70a6668fa3555d47caebdcee045745ab80adf5e4"
Expand Down Expand Up @@ -2666,23 +2658,11 @@ [email protected]:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==

[email protected], ms@^2.1.1:
[email protected]:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

multiaddr@^10.0.1:
version "10.0.1"
resolved "https://registry.yarnpkg.com/multiaddr/-/multiaddr-10.0.1.tgz#0d15848871370860a4d266bb44d93b3dac5d90ef"
integrity sha512-G5upNcGzEGuTHkzxezPrrD6CaIHR9uo+7MwqhNVcXTs33IInon4y7nMiGxl2CY5hG7chvYQUQhz5V52/Qe3cbg==
dependencies:
dns-over-http-resolver "^1.2.3"
err-code "^3.0.1"
is-ip "^3.1.0"
multiformats "^9.4.5"
uint8arrays "^3.0.0"
varint "^6.0.0"

multibase@^4.0.1:
version "4.0.6"
resolved "https://registry.yarnpkg.com/multibase/-/multibase-4.0.6.tgz#6e624341483d6123ca1ede956208cb821b440559"
Expand Down Expand Up @@ -2713,7 +2693,7 @@ multiformats@^13.0.1:
resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-13.1.1.tgz#b22ce4df26330d2cf0d69f5bdcbc9a787095a6e5"
integrity sha512-JiptvwMmlxlzIlLLwhCi/srf/nk409UL0eUBr0kioRJq15hqqKyg68iftrBvhCRjR6Rw4fkNnSc4ZJXJDuta/Q==

multiformats@^9.4.2, multiformats@^9.4.5:
multiformats@^9.4.2:
version "9.9.0"
resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37"
integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==
Expand All @@ -2737,11 +2717,6 @@ napi-build-utils@^1.0.1:
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==

native-fetch@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/native-fetch/-/native-fetch-3.0.0.tgz#06ccdd70e79e171c365c75117959cf4fe14a09bb"
integrity sha512-G3Z7vx0IFb/FQ4JxvtqGABsOTIqRWvgQz6e+erkB+JJD6LrszQtMozEHI4EkmgZQvnGHrpLVzUWk7t4sJCIkVw==

[email protected]:
version "0.6.3"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
Expand Down Expand Up @@ -3162,13 +3137,6 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"

receptacle@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/receptacle/-/receptacle-1.3.2.tgz#a7994c7efafc7a01d0e2041839dab6c4951360d2"
integrity sha512-HrsFvqZZheusncQRiEE7GatOAETrARKV/lnfYicIm8lbvp/JQOdADOfhjBd2DajvoszEyxSM6RlAAIZgEoeu/A==
dependencies:
ms "^2.1.1"

rechoir@^0.7.0:
version "0.7.1"
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686"
Expand Down Expand Up @@ -3727,11 +3695,6 @@ varint@^5.0.2:
resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4"
integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==

varint@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/varint/-/varint-6.0.0.tgz#9881eb0ce8feaea6512439d19ddf84bf551661d0"
integrity sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==

vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
Expand Down
11 changes: 3 additions & 8 deletions packages/network/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@
},
"type": "module",
"types": "./dist/src/index.d.ts",
"files": [
"src",
"dist",
"!dist/test",
"!**/*.tsbuildinfo"
],
"files": ["src", "dist", "!dist/test", "!**/*.tsbuildinfo"],
"exports": {
".": {
"types": "./dist/src/index.d.ts",
Expand All @@ -40,8 +35,8 @@
"@libp2p/pubsub-peer-discovery": "^10.0.2",
"@libp2p/webrtc": "^4.0.33",
"@libp2p/websockets": "^8.0.24",
"@multiformats/multiaddr": "^12.3.0",
"it-pipe": "^3.0.1",
"libp2p": "^1.6.0",
"multiaddr": "^10.0.1"
"libp2p": "^1.6.0"
}
}
21 changes: 11 additions & 10 deletions packages/network/src/node.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { GossipsubEvents, gossipsub } from "@chainsafe/libp2p-gossipsub";
import {
GossipsubEvents,
GossipsubMessage,
gossipsub,
} from "@chainsafe/libp2p-gossipsub";
import { noise } from "@chainsafe/libp2p-noise";
import { yamux } from "@chainsafe/libp2p-yamux";
import { circuitRelayTransport } from "@libp2p/circuit-relay-v2";
Expand All @@ -8,8 +12,8 @@ import { pubsubPeerDiscovery } from "@libp2p/pubsub-peer-discovery";
import { webRTC } from "@libp2p/webrtc";
import { webSockets } from "@libp2p/websockets";
import * as filters from "@libp2p/websockets/filters";
import { multiaddr } from "@multiformats/multiaddr";
import { Libp2p, createLibp2p } from "libp2p";
import { multiaddr } from "multiaddr";
import { stringToStream } from "./stream";

export interface TopologyNetworkNodeConfig {}
Expand Down Expand Up @@ -139,13 +143,13 @@ export class TopologyNetworkNode {
}
}

async sendMessageRandomTopicPeer(
topic: string,
async sendGroupMessageRandomPeer(
group: string,
protocols: string[],
message: string,
) {
try {
const peers = this._pubsub?.getSubscribers(topic);
const peers = this._pubsub?.getSubscribers(group);
if (!peers || peers.length === 0) throw Error("Topic wo/ peers");
const peerId = peers[Math.floor(Math.random() * peers.length)];

Expand All @@ -161,11 +165,8 @@ export class TopologyNetworkNode {
}
}

addPubsubEventListener(
type: keyof GossipsubEvents,
event: EventHandler<CustomEvent<any>>,
) {
this._pubsub?.addEventListener(type, event);
addGroupMessageHandler(handler: EventHandler<CustomEvent<GossipsubMessage>>) {
this._pubsub?.addEventListener("gossipsub:message", handler);
}

addMessageHandler(protocol: string | string[], handler: StreamHandler) {
Expand Down
28 changes: 24 additions & 4 deletions packages/node/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { GossipsubMessage } from "@chainsafe/libp2p-gossipsub";
import { EventHandler, StreamHandler } from "@libp2p/interface";
import {
TopologyNetworkNode,
TopologyNetworkNodeConfig,
Expand Down Expand Up @@ -26,9 +28,9 @@ export class TopologyNode {
async start(): Promise<void> {
await this._networkNode.start();

this._networkNode.addPubsubEventListener("message", (e) => {
if (e.detail.topic === "_peer-discovery._p2p._pubsub") return;

this._networkNode.addGroupMessageHandler((e) => {
if (e.detail.msg.topic === "_peer-discovery._p2p._pubsub") return;
// TODO: add base handler here after July demo
// send the events to the app handler
// const message = JSON.parse(new TextDecoder().decode(e.detail.data));
});
Expand Down Expand Up @@ -92,7 +94,7 @@ export class TopologyNode {
"data": [${uint8ArrayFromString(objectId)}]
}`;

await this._networkNode.sendMessageRandomTopicPeer(
await this._networkNode.sendGroupMessageRandomPeer(
objectId,
["/topology/message/0.0.1"],
message,
Expand All @@ -116,4 +118,22 @@ export class TopologyNode {
uint8ArrayFromString(message),
);
}

addCustomGroup(group: string) {
this._networkNode.subscribe(group);
}

sendGroupMessage(group: string, message: Uint8Array) {
this._networkNode.broadcastMessage(group, message);
}

addCustomGroupMessageHandler(
handler: EventHandler<CustomEvent<GossipsubMessage>>,
) {
this._networkNode.addGroupMessageHandler(handler);
}

addCustomMessageHandler(protocol: string | string[], handler: StreamHandler) {
this._networkNode.addMessageHandler(protocol, handler);
}
}
Loading

0 comments on commit 5c15be3

Please sign in to comment.