bitchat-node 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +223 -0
- package/dist/bin/bitchat.d.ts +7 -0
- package/dist/bin/bitchat.d.ts.map +1 -0
- package/dist/bin/bitchat.js +69 -0
- package/dist/bin/bitchat.js.map +1 -0
- package/dist/client.d.ts +77 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +411 -0
- package/dist/client.js.map +1 -0
- package/dist/crypto/index.d.ts +6 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +6 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/crypto/noise.d.ts +72 -0
- package/dist/crypto/noise.d.ts.map +1 -0
- package/dist/crypto/noise.js +470 -0
- package/dist/crypto/noise.js.map +1 -0
- package/dist/crypto/signing.d.ts +34 -0
- package/dist/crypto/signing.d.ts.map +1 -0
- package/dist/crypto/signing.js +56 -0
- package/dist/crypto/signing.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/mesh/deduplicator.d.ts +48 -0
- package/dist/mesh/deduplicator.d.ts.map +1 -0
- package/dist/mesh/deduplicator.js +107 -0
- package/dist/mesh/deduplicator.js.map +1 -0
- package/dist/mesh/index.d.ts +6 -0
- package/dist/mesh/index.d.ts.map +1 -0
- package/dist/mesh/index.js +6 -0
- package/dist/mesh/index.js.map +1 -0
- package/dist/mesh/router.d.ts +90 -0
- package/dist/mesh/router.d.ts.map +1 -0
- package/dist/mesh/router.js +204 -0
- package/dist/mesh/router.js.map +1 -0
- package/dist/protocol/binary.d.ts +37 -0
- package/dist/protocol/binary.d.ts.map +1 -0
- package/dist/protocol/binary.js +310 -0
- package/dist/protocol/binary.js.map +1 -0
- package/dist/protocol/constants.d.ts +30 -0
- package/dist/protocol/constants.d.ts.map +1 -0
- package/dist/protocol/constants.js +37 -0
- package/dist/protocol/constants.js.map +1 -0
- package/dist/protocol/index.d.ts +8 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +8 -0
- package/dist/protocol/index.js.map +1 -0
- package/dist/protocol/packets.d.ts +38 -0
- package/dist/protocol/packets.d.ts.map +1 -0
- package/dist/protocol/packets.js +177 -0
- package/dist/protocol/packets.js.map +1 -0
- package/dist/protocol/types.d.ts +134 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +108 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +5 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +113 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +371 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/transport/ble.d.ts +92 -0
- package/dist/transport/ble.d.ts.map +1 -0
- package/dist/transport/ble.js +434 -0
- package/dist/transport/ble.js.map +1 -0
- package/dist/transport/index.d.ts +5 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +5 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +2 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/server.d.ts +16 -0
- package/dist/ui/server.d.ts.map +1 -0
- package/dist/ui/server.js +510 -0
- package/dist/ui/server.js.map +1 -0
- package/package.json +79 -0
- package/src/bin/bitchat.ts +87 -0
- package/src/client.ts +519 -0
- package/src/crypto/index.ts +22 -0
- package/src/crypto/noise.ts +574 -0
- package/src/crypto/signing.ts +66 -0
- package/src/index.ts +95 -0
- package/src/mesh/deduplicator.ts +129 -0
- package/src/mesh/index.ts +6 -0
- package/src/mesh/router.ts +258 -0
- package/src/protocol/binary.ts +345 -0
- package/src/protocol/constants.ts +43 -0
- package/src/protocol/index.ts +15 -0
- package/src/protocol/packets.ts +223 -0
- package/src/protocol/types.ts +182 -0
- package/src/session/index.ts +9 -0
- package/src/session/manager.ts +476 -0
- package/src/transport/ble.ts +553 -0
- package/src/transport/index.ts +10 -0
- package/src/ui/index.ts +1 -0
- package/src/ui/server.ts +569 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bitchat-node
|
|
3
|
+
* Node.js implementation of the Bitchat BLE mesh protocol
|
|
4
|
+
*
|
|
5
|
+
* Compatible with Jack Dorsey's Bitchat app.
|
|
6
|
+
* @see https://github.com/permissionlesstech/bitchat
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { BitchatClient } from 'bitchat-node';
|
|
11
|
+
*
|
|
12
|
+
* const client = new BitchatClient({ nickname: 'my-node' });
|
|
13
|
+
*
|
|
14
|
+
* client.on('message', (message) => {
|
|
15
|
+
* console.log(`${message.senderNickname}: ${message.content}`);
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* client.on('peer:connected', (peer) => {
|
|
19
|
+
* console.log(`Connected to ${peer.nickname}`);
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* await client.start();
|
|
23
|
+
* await client.sendPublicMessage('Hello mesh!');
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
// Main client
|
|
27
|
+
export { BitchatClient } from './client.js';
|
|
28
|
+
// Crypto
|
|
29
|
+
export {
|
|
30
|
+
// Noise protocol
|
|
31
|
+
CipherState, fingerprint, formatFingerprint, generateKeyPair,
|
|
32
|
+
// Signing
|
|
33
|
+
generateSigningKeyPair, HandshakeState as NoiseHandshakeState, NoiseSession, sha256, sign, verify, } from './crypto/index.js';
|
|
34
|
+
// Mesh
|
|
35
|
+
export { MeshRouter, MessageDeduplicator, } from './mesh/index.js';
|
|
36
|
+
// Protocol
|
|
37
|
+
export { CHARACTERISTIC_UUID, DEFAULT_TTL, decode,
|
|
38
|
+
// Binary encoding
|
|
39
|
+
encode, encodeForSigning, HandshakeState, MAX_MESSAGE_LENGTH, MAX_TTL,
|
|
40
|
+
// Types
|
|
41
|
+
MessageType, makeDeduplicationID, NoisePayloadType, PacketFlags, PeerID,
|
|
42
|
+
// Constants
|
|
43
|
+
SERVICE_UUID, SERVICE_UUID_TESTNET, } from './protocol/index.js';
|
|
44
|
+
// Sessions
|
|
45
|
+
export { SessionManager, } from './session/index.js';
|
|
46
|
+
// Transport
|
|
47
|
+
export { BLELink, BLETransport, } from './transport/index.js';
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,cAAc;AACd,OAAO,EAAE,aAAa,EAAsD,MAAM,aAAa,CAAC;AAChG,SAAS;AACT,OAAO;AACL,iBAAiB;AACjB,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,eAAe;AACf,UAAU;AACV,sBAAsB,EACtB,cAAc,IAAI,mBAAmB,EAGrC,YAAY,EAEZ,MAAM,EACN,IAAI,EACJ,MAAM,GACP,MAAM,mBAAmB,CAAC;AAC3B,OAAO;AACP,OAAO,EAGL,UAAU,EACV,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AACzB,WAAW;AACX,OAAO,EAEL,mBAAmB,EAEnB,WAAW,EAEX,MAAM;AACN,kBAAkB;AAClB,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,OAAO;AACP,QAAQ;AACR,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,MAAM;AAGN,YAAY;AACZ,YAAY,EACZ,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,WAAW;AACX,OAAO,EACL,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAE5B,YAAY;AACZ,OAAO,EACL,OAAO,EACP,YAAY,GAGb,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Deduplicator
|
|
3
|
+
* Prevents processing the same message multiple times in the mesh
|
|
4
|
+
* Uses a simple bloom-filter-like approach with time-based expiry
|
|
5
|
+
*/
|
|
6
|
+
export interface DeduplicatorConfig {
|
|
7
|
+
maxSize: number;
|
|
8
|
+
maxAgeMs: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Efficient message deduplication for mesh networks
|
|
12
|
+
*/
|
|
13
|
+
export declare class MessageDeduplicator {
|
|
14
|
+
private seen;
|
|
15
|
+
private readonly config;
|
|
16
|
+
private cleanupTimer?;
|
|
17
|
+
constructor(config?: Partial<DeduplicatorConfig>);
|
|
18
|
+
/**
|
|
19
|
+
* Check if message was seen and mark it as seen
|
|
20
|
+
* Returns true if this is a NEW message (not seen before)
|
|
21
|
+
*/
|
|
22
|
+
markSeen(id: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Check if message was seen (without marking)
|
|
25
|
+
*/
|
|
26
|
+
hasSeen(id: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Remove expired entries
|
|
29
|
+
*/
|
|
30
|
+
private cleanup;
|
|
31
|
+
/**
|
|
32
|
+
* Trim oldest entries when size limit exceeded
|
|
33
|
+
*/
|
|
34
|
+
private trimOldest;
|
|
35
|
+
/**
|
|
36
|
+
* Clear all entries
|
|
37
|
+
*/
|
|
38
|
+
reset(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Stop cleanup timer
|
|
41
|
+
*/
|
|
42
|
+
destroy(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Get current size
|
|
45
|
+
*/
|
|
46
|
+
get size(): number;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=deduplicator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deduplicator.d.ts","sourceRoot":"","sources":["../../src/mesh/deduplicator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAOD;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,YAAY,CAAC,CAAiC;gBAE1C,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAOpD;;;OAGG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IA0B7B;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAa5B;;OAEG;IACH,OAAO,CAAC,OAAO;IAWf;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message Deduplicator
|
|
3
|
+
* Prevents processing the same message multiple times in the mesh
|
|
4
|
+
* Uses a simple bloom-filter-like approach with time-based expiry
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
maxSize: 10000,
|
|
8
|
+
maxAgeMs: 5 * 60 * 1000, // 5 minutes
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Efficient message deduplication for mesh networks
|
|
12
|
+
*/
|
|
13
|
+
export class MessageDeduplicator {
|
|
14
|
+
seen = new Map();
|
|
15
|
+
config;
|
|
16
|
+
cleanupTimer;
|
|
17
|
+
constructor(config = {}) {
|
|
18
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
19
|
+
// Periodic cleanup
|
|
20
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), 60000);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if message was seen and mark it as seen
|
|
24
|
+
* Returns true if this is a NEW message (not seen before)
|
|
25
|
+
*/
|
|
26
|
+
markSeen(id) {
|
|
27
|
+
const now = Date.now();
|
|
28
|
+
// Check if already seen
|
|
29
|
+
const existingTimestamp = this.seen.get(id);
|
|
30
|
+
if (existingTimestamp !== undefined) {
|
|
31
|
+
// Already seen - check if expired
|
|
32
|
+
if (now - existingTimestamp > this.config.maxAgeMs) {
|
|
33
|
+
// Expired, treat as new
|
|
34
|
+
this.seen.set(id, now);
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
// New message - add to seen set
|
|
40
|
+
this.seen.set(id, now);
|
|
41
|
+
// Trim if too large
|
|
42
|
+
if (this.seen.size > this.config.maxSize) {
|
|
43
|
+
this.trimOldest();
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if message was seen (without marking)
|
|
49
|
+
*/
|
|
50
|
+
hasSeen(id) {
|
|
51
|
+
const timestamp = this.seen.get(id);
|
|
52
|
+
if (timestamp === undefined)
|
|
53
|
+
return false;
|
|
54
|
+
// Check expiry
|
|
55
|
+
if (Date.now() - timestamp > this.config.maxAgeMs) {
|
|
56
|
+
this.seen.delete(id);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Remove expired entries
|
|
63
|
+
*/
|
|
64
|
+
cleanup() {
|
|
65
|
+
const now = Date.now();
|
|
66
|
+
const maxAge = this.config.maxAgeMs;
|
|
67
|
+
for (const [id, timestamp] of this.seen) {
|
|
68
|
+
if (now - timestamp > maxAge) {
|
|
69
|
+
this.seen.delete(id);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Trim oldest entries when size limit exceeded
|
|
75
|
+
*/
|
|
76
|
+
trimOldest() {
|
|
77
|
+
// Convert to array, sort by timestamp, keep newest half
|
|
78
|
+
const entries = Array.from(this.seen.entries()).sort((a, b) => a[1] - b[1]);
|
|
79
|
+
const toRemove = Math.floor(entries.length / 2);
|
|
80
|
+
for (let i = 0; i < toRemove; i++) {
|
|
81
|
+
this.seen.delete(entries[i][0]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Clear all entries
|
|
86
|
+
*/
|
|
87
|
+
reset() {
|
|
88
|
+
this.seen.clear();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Stop cleanup timer
|
|
92
|
+
*/
|
|
93
|
+
destroy() {
|
|
94
|
+
if (this.cleanupTimer) {
|
|
95
|
+
clearInterval(this.cleanupTimer);
|
|
96
|
+
this.cleanupTimer = undefined;
|
|
97
|
+
}
|
|
98
|
+
this.seen.clear();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get current size
|
|
102
|
+
*/
|
|
103
|
+
get size() {
|
|
104
|
+
return this.seen.size;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=deduplicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deduplicator.js","sourceRoot":"","sources":["../../src/mesh/deduplicator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mesh/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAE,KAAK,IAAI,EAAE,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mesh/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAA2B,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,EAAa,UAAU,EAAwC,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mesh Router
|
|
3
|
+
* Handles TTL-based message flooding and routing decisions
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from 'node:events';
|
|
6
|
+
import { type BitchatPacket, type PeerID } from '../protocol/types.js';
|
|
7
|
+
export interface RouterConfig {
|
|
8
|
+
maxTTL: number;
|
|
9
|
+
defaultTTL: number;
|
|
10
|
+
probabilisticRelay: boolean;
|
|
11
|
+
relayProbability: number;
|
|
12
|
+
}
|
|
13
|
+
export interface Link {
|
|
14
|
+
id: string;
|
|
15
|
+
send(data: Uint8Array): Promise<void>;
|
|
16
|
+
peerID?: PeerID;
|
|
17
|
+
}
|
|
18
|
+
export interface RouterEvents {
|
|
19
|
+
packet: (packet: BitchatPacket, fromLink: Link | null) => void;
|
|
20
|
+
forward: (packet: BitchatPacket, toLinks: Link[]) => void;
|
|
21
|
+
drop: (packet: BitchatPacket, reason: string) => void;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Mesh message router with TTL-based flooding
|
|
25
|
+
*/
|
|
26
|
+
export declare class MeshRouter extends EventEmitter {
|
|
27
|
+
private readonly config;
|
|
28
|
+
private readonly deduplicator;
|
|
29
|
+
private readonly links;
|
|
30
|
+
private myPeerID;
|
|
31
|
+
private ingressLinks;
|
|
32
|
+
constructor(config?: Partial<RouterConfig>);
|
|
33
|
+
/**
|
|
34
|
+
* Set our own peer ID (to avoid processing our own messages)
|
|
35
|
+
*/
|
|
36
|
+
setMyPeerID(peerID: PeerID): void;
|
|
37
|
+
/**
|
|
38
|
+
* Get our own peer ID
|
|
39
|
+
*/
|
|
40
|
+
getMyPeerID(): PeerID | null;
|
|
41
|
+
/**
|
|
42
|
+
* Add a link (connection to another peer)
|
|
43
|
+
*/
|
|
44
|
+
addLink(link: Link): void;
|
|
45
|
+
/**
|
|
46
|
+
* Remove a link
|
|
47
|
+
*/
|
|
48
|
+
removeLink(linkId: string): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get all active links
|
|
51
|
+
*/
|
|
52
|
+
getLinks(): Link[];
|
|
53
|
+
/**
|
|
54
|
+
* Get peer IDs of all connected links
|
|
55
|
+
*/
|
|
56
|
+
getConnectedPeerIDs(): PeerID[];
|
|
57
|
+
/**
|
|
58
|
+
* Handle an incoming packet
|
|
59
|
+
*/
|
|
60
|
+
handlePacket(packet: BitchatPacket, fromLink: Link | null): Promise<boolean>;
|
|
61
|
+
/**
|
|
62
|
+
* Send a new packet (originated by us)
|
|
63
|
+
*/
|
|
64
|
+
sendPacket(packet: BitchatPacket): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Check if packet should be forwarded
|
|
67
|
+
*/
|
|
68
|
+
private shouldForward;
|
|
69
|
+
/**
|
|
70
|
+
* Forward a packet (decrement TTL, send to other links)
|
|
71
|
+
*/
|
|
72
|
+
private forward;
|
|
73
|
+
/**
|
|
74
|
+
* Broadcast to all links
|
|
75
|
+
*/
|
|
76
|
+
private broadcast;
|
|
77
|
+
/**
|
|
78
|
+
* Send packet to specific links
|
|
79
|
+
*/
|
|
80
|
+
private sendToLinks;
|
|
81
|
+
/**
|
|
82
|
+
* Send to a specific peer (if we have a direct link)
|
|
83
|
+
*/
|
|
84
|
+
sendToPeer(packet: BitchatPacket, peerID: PeerID): Promise<boolean>;
|
|
85
|
+
/**
|
|
86
|
+
* Clean up
|
|
87
|
+
*/
|
|
88
|
+
destroy(): void;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/mesh/router.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,KAAK,aAAa,EAAe,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGpF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AASD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/D,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAC1D,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAED;;GAEG;AACH,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IACjD,OAAO,CAAC,QAAQ,CAAuB;IAGvC,OAAO,CAAC,YAAY,CAA6B;gBAErC,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAM9C;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIjC;;OAEG;IACH,WAAW,IAAI,MAAM,GAAG,IAAI;IAI5B;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAIzB;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAUhC;;OAEG;IACH,QAAQ,IAAI,IAAI,EAAE;IAIlB;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;IAM/B;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IA+BlF;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD;;OAEG;IACH,OAAO,CAAC,aAAa;IAuBrB;;OAEG;YACW,OAAO;IAqBrB;;OAEG;YACW,SAAS;IAKvB;;OAEG;YACW,WAAW;IAgBzB;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBzE;;OAEG;IACH,OAAO,IAAI,IAAI;CAMhB"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mesh Router
|
|
3
|
+
* Handles TTL-based message flooding and routing decisions
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from 'node:events';
|
|
6
|
+
import { makeDeduplicationID } from '../protocol/binary.js';
|
|
7
|
+
import { DEFAULT_TTL, MAX_TTL } from '../protocol/constants.js';
|
|
8
|
+
import { MessageType } from '../protocol/types.js';
|
|
9
|
+
import { MessageDeduplicator } from './deduplicator.js';
|
|
10
|
+
const DEFAULT_ROUTER_CONFIG = {
|
|
11
|
+
maxTTL: MAX_TTL,
|
|
12
|
+
defaultTTL: DEFAULT_TTL,
|
|
13
|
+
probabilisticRelay: false,
|
|
14
|
+
relayProbability: 0.8,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Mesh message router with TTL-based flooding
|
|
18
|
+
*/
|
|
19
|
+
export class MeshRouter extends EventEmitter {
|
|
20
|
+
config;
|
|
21
|
+
deduplicator;
|
|
22
|
+
links = new Map();
|
|
23
|
+
myPeerID = null;
|
|
24
|
+
// Track ingress link for each message to avoid echo
|
|
25
|
+
ingressLinks = new Map();
|
|
26
|
+
constructor(config = {}) {
|
|
27
|
+
super();
|
|
28
|
+
this.config = { ...DEFAULT_ROUTER_CONFIG, ...config };
|
|
29
|
+
this.deduplicator = new MessageDeduplicator();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Set our own peer ID (to avoid processing our own messages)
|
|
33
|
+
*/
|
|
34
|
+
setMyPeerID(peerID) {
|
|
35
|
+
this.myPeerID = peerID;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get our own peer ID
|
|
39
|
+
*/
|
|
40
|
+
getMyPeerID() {
|
|
41
|
+
return this.myPeerID;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Add a link (connection to another peer)
|
|
45
|
+
*/
|
|
46
|
+
addLink(link) {
|
|
47
|
+
this.links.set(link.id, link);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Remove a link
|
|
51
|
+
*/
|
|
52
|
+
removeLink(linkId) {
|
|
53
|
+
this.links.delete(linkId);
|
|
54
|
+
// Clean up any ingress tracking
|
|
55
|
+
for (const [msgId, ingressLinkId] of this.ingressLinks) {
|
|
56
|
+
if (ingressLinkId === linkId) {
|
|
57
|
+
this.ingressLinks.delete(msgId);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get all active links
|
|
63
|
+
*/
|
|
64
|
+
getLinks() {
|
|
65
|
+
return Array.from(this.links.values());
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get peer IDs of all connected links
|
|
69
|
+
*/
|
|
70
|
+
getConnectedPeerIDs() {
|
|
71
|
+
return Array.from(this.links.values())
|
|
72
|
+
.filter((link) => link.peerID !== undefined)
|
|
73
|
+
.map((link) => link.peerID);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Handle an incoming packet
|
|
77
|
+
*/
|
|
78
|
+
async handlePacket(packet, fromLink) {
|
|
79
|
+
const dedupID = makeDeduplicationID(packet);
|
|
80
|
+
// Check deduplication
|
|
81
|
+
if (!this.deduplicator.markSeen(dedupID)) {
|
|
82
|
+
this.emit('drop', packet, 'duplicate');
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
// Track ingress link
|
|
86
|
+
if (fromLink) {
|
|
87
|
+
this.ingressLinks.set(dedupID, fromLink.id);
|
|
88
|
+
}
|
|
89
|
+
// Validate TTL
|
|
90
|
+
if (packet.ttl > this.config.maxTTL) {
|
|
91
|
+
this.emit('drop', packet, 'ttl_exceeded');
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
// Emit packet for processing
|
|
95
|
+
this.emit('packet', packet, fromLink);
|
|
96
|
+
// Decide whether to forward
|
|
97
|
+
if (this.shouldForward(packet)) {
|
|
98
|
+
await this.forward(packet, fromLink?.id);
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Send a new packet (originated by us)
|
|
104
|
+
*/
|
|
105
|
+
async sendPacket(packet) {
|
|
106
|
+
const dedupID = makeDeduplicationID(packet);
|
|
107
|
+
// Mark as seen to avoid processing our own relayed copy
|
|
108
|
+
this.deduplicator.markSeen(dedupID);
|
|
109
|
+
// Broadcast to all links
|
|
110
|
+
await this.broadcast(packet);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if packet should be forwarded
|
|
114
|
+
*/
|
|
115
|
+
shouldForward(packet) {
|
|
116
|
+
// Don't forward if TTL exhausted
|
|
117
|
+
if (packet.ttl <= 0)
|
|
118
|
+
return false;
|
|
119
|
+
// Don't forward certain message types
|
|
120
|
+
switch (packet.type) {
|
|
121
|
+
case MessageType.REQUEST_SYNC:
|
|
122
|
+
// Sync requests are local-only
|
|
123
|
+
return false;
|
|
124
|
+
default:
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
// Probabilistic relay under high load
|
|
128
|
+
if (this.config.probabilisticRelay) {
|
|
129
|
+
if (Math.random() > this.config.relayProbability) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Forward a packet (decrement TTL, send to other links)
|
|
137
|
+
*/
|
|
138
|
+
async forward(packet, excludeLinkId) {
|
|
139
|
+
// Decrement TTL
|
|
140
|
+
const forwardPacket = {
|
|
141
|
+
...packet,
|
|
142
|
+
ttl: packet.ttl - 1,
|
|
143
|
+
};
|
|
144
|
+
// Get links to forward to (excluding ingress)
|
|
145
|
+
const dedupID = makeDeduplicationID(packet);
|
|
146
|
+
const ingressLinkId = excludeLinkId ?? this.ingressLinks.get(dedupID);
|
|
147
|
+
const targetLinks = Array.from(this.links.values()).filter((link) => link.id !== ingressLinkId);
|
|
148
|
+
if (targetLinks.length === 0)
|
|
149
|
+
return;
|
|
150
|
+
this.emit('forward', forwardPacket, targetLinks);
|
|
151
|
+
// Send to all target links
|
|
152
|
+
await this.sendToLinks(forwardPacket, targetLinks);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Broadcast to all links
|
|
156
|
+
*/
|
|
157
|
+
async broadcast(packet) {
|
|
158
|
+
const targetLinks = Array.from(this.links.values());
|
|
159
|
+
await this.sendToLinks(packet, targetLinks);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Send packet to specific links
|
|
163
|
+
*/
|
|
164
|
+
async sendToLinks(packet, links) {
|
|
165
|
+
const { encode } = await import('../protocol/binary.js');
|
|
166
|
+
const data = encode(packet);
|
|
167
|
+
const sendPromises = links.map(async (link) => {
|
|
168
|
+
try {
|
|
169
|
+
await link.send(data);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
// Log error but don't fail the whole broadcast
|
|
173
|
+
console.error(`Failed to send to link ${link.id}:`, error);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
await Promise.allSettled(sendPromises);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Send to a specific peer (if we have a direct link)
|
|
180
|
+
*/
|
|
181
|
+
async sendToPeer(packet, peerID) {
|
|
182
|
+
// Find link for this peer
|
|
183
|
+
const link = Array.from(this.links.values()).find((l) => l.peerID?.equals(peerID));
|
|
184
|
+
if (!link) {
|
|
185
|
+
// No direct link - broadcast and hope for relay
|
|
186
|
+
await this.sendPacket(packet);
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
const { encode } = await import('../protocol/binary.js');
|
|
190
|
+
const data = encode(packet);
|
|
191
|
+
await link.send(data);
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Clean up
|
|
196
|
+
*/
|
|
197
|
+
destroy() {
|
|
198
|
+
this.deduplicator.destroy();
|
|
199
|
+
this.links.clear();
|
|
200
|
+
this.ingressLinks.clear();
|
|
201
|
+
this.removeAllListeners();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/mesh/router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary Protocol Encoder/Decoder
|
|
3
|
+
* From: bitchat/Protocols/BinaryProtocol.swift
|
|
4
|
+
*
|
|
5
|
+
* Wire format:
|
|
6
|
+
* Header (14 bytes for v1, 16 bytes for v2):
|
|
7
|
+
* +--------+------+-----+-----------+-------+------------------+
|
|
8
|
+
* |Version | Type | TTL | Timestamp | Flags | PayloadLength |
|
|
9
|
+
* |1 byte |1 byte|1byte| 8 bytes | 1 byte| 2 or 4 bytes |
|
|
10
|
+
* +--------+------+-----+-----------+-------+------------------+
|
|
11
|
+
*
|
|
12
|
+
* Variable sections:
|
|
13
|
+
* +----------+-------------+---------+------------+
|
|
14
|
+
* | SenderID | RecipientID | Payload | Signature |
|
|
15
|
+
* | 8 bytes | 8 bytes* | Variable| 64 bytes* |
|
|
16
|
+
* +----------+-------------+---------+------------+
|
|
17
|
+
*/
|
|
18
|
+
import { type BitchatPacket } from './types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Encode a BitchatPacket to binary wire format
|
|
21
|
+
*/
|
|
22
|
+
export declare function encode(packet: BitchatPacket, options?: {
|
|
23
|
+
padding?: boolean;
|
|
24
|
+
}): Uint8Array;
|
|
25
|
+
/**
|
|
26
|
+
* Decode binary wire format to BitchatPacket
|
|
27
|
+
*/
|
|
28
|
+
export declare function decode(data: Uint8Array): BitchatPacket | null;
|
|
29
|
+
/**
|
|
30
|
+
* Create binary representation for signing (without signature, TTL=0)
|
|
31
|
+
*/
|
|
32
|
+
export declare function encodeForSigning(packet: BitchatPacket): Uint8Array;
|
|
33
|
+
/**
|
|
34
|
+
* Create message deduplication ID
|
|
35
|
+
*/
|
|
36
|
+
export declare function makeDeduplicationID(packet: BitchatPacket): string;
|
|
37
|
+
//# sourceMappingURL=binary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary.d.ts","sourceRoot":"","sources":["../../src/protocol/binary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAWH,OAAO,EAAE,KAAK,aAAa,EAAyC,MAAM,YAAY,CAAC;AA0CvF;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,UAAU,CAyG7F;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI,CAY7D;AAmID;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CASlE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAEjE"}
|