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.
Files changed (102) hide show
  1. package/README.md +223 -0
  2. package/dist/bin/bitchat.d.ts +7 -0
  3. package/dist/bin/bitchat.d.ts.map +1 -0
  4. package/dist/bin/bitchat.js +69 -0
  5. package/dist/bin/bitchat.js.map +1 -0
  6. package/dist/client.d.ts +77 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +411 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/crypto/index.d.ts +6 -0
  11. package/dist/crypto/index.d.ts.map +1 -0
  12. package/dist/crypto/index.js +6 -0
  13. package/dist/crypto/index.js.map +1 -0
  14. package/dist/crypto/noise.d.ts +72 -0
  15. package/dist/crypto/noise.d.ts.map +1 -0
  16. package/dist/crypto/noise.js +470 -0
  17. package/dist/crypto/noise.js.map +1 -0
  18. package/dist/crypto/signing.d.ts +34 -0
  19. package/dist/crypto/signing.d.ts.map +1 -0
  20. package/dist/crypto/signing.js +56 -0
  21. package/dist/crypto/signing.js.map +1 -0
  22. package/dist/index.d.ts +32 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +48 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/mesh/deduplicator.d.ts +48 -0
  27. package/dist/mesh/deduplicator.d.ts.map +1 -0
  28. package/dist/mesh/deduplicator.js +107 -0
  29. package/dist/mesh/deduplicator.js.map +1 -0
  30. package/dist/mesh/index.d.ts +6 -0
  31. package/dist/mesh/index.d.ts.map +1 -0
  32. package/dist/mesh/index.js +6 -0
  33. package/dist/mesh/index.js.map +1 -0
  34. package/dist/mesh/router.d.ts +90 -0
  35. package/dist/mesh/router.d.ts.map +1 -0
  36. package/dist/mesh/router.js +204 -0
  37. package/dist/mesh/router.js.map +1 -0
  38. package/dist/protocol/binary.d.ts +37 -0
  39. package/dist/protocol/binary.d.ts.map +1 -0
  40. package/dist/protocol/binary.js +310 -0
  41. package/dist/protocol/binary.js.map +1 -0
  42. package/dist/protocol/constants.d.ts +30 -0
  43. package/dist/protocol/constants.d.ts.map +1 -0
  44. package/dist/protocol/constants.js +37 -0
  45. package/dist/protocol/constants.js.map +1 -0
  46. package/dist/protocol/index.d.ts +8 -0
  47. package/dist/protocol/index.d.ts.map +1 -0
  48. package/dist/protocol/index.js +8 -0
  49. package/dist/protocol/index.js.map +1 -0
  50. package/dist/protocol/packets.d.ts +38 -0
  51. package/dist/protocol/packets.d.ts.map +1 -0
  52. package/dist/protocol/packets.js +177 -0
  53. package/dist/protocol/packets.js.map +1 -0
  54. package/dist/protocol/types.d.ts +134 -0
  55. package/dist/protocol/types.d.ts.map +1 -0
  56. package/dist/protocol/types.js +108 -0
  57. package/dist/protocol/types.js.map +1 -0
  58. package/dist/session/index.d.ts +5 -0
  59. package/dist/session/index.d.ts.map +1 -0
  60. package/dist/session/index.js +5 -0
  61. package/dist/session/index.js.map +1 -0
  62. package/dist/session/manager.d.ts +113 -0
  63. package/dist/session/manager.d.ts.map +1 -0
  64. package/dist/session/manager.js +371 -0
  65. package/dist/session/manager.js.map +1 -0
  66. package/dist/transport/ble.d.ts +92 -0
  67. package/dist/transport/ble.d.ts.map +1 -0
  68. package/dist/transport/ble.js +434 -0
  69. package/dist/transport/ble.js.map +1 -0
  70. package/dist/transport/index.d.ts +5 -0
  71. package/dist/transport/index.d.ts.map +1 -0
  72. package/dist/transport/index.js +5 -0
  73. package/dist/transport/index.js.map +1 -0
  74. package/dist/ui/index.d.ts +2 -0
  75. package/dist/ui/index.d.ts.map +1 -0
  76. package/dist/ui/index.js +2 -0
  77. package/dist/ui/index.js.map +1 -0
  78. package/dist/ui/server.d.ts +16 -0
  79. package/dist/ui/server.d.ts.map +1 -0
  80. package/dist/ui/server.js +510 -0
  81. package/dist/ui/server.js.map +1 -0
  82. package/package.json +79 -0
  83. package/src/bin/bitchat.ts +87 -0
  84. package/src/client.ts +519 -0
  85. package/src/crypto/index.ts +22 -0
  86. package/src/crypto/noise.ts +574 -0
  87. package/src/crypto/signing.ts +66 -0
  88. package/src/index.ts +95 -0
  89. package/src/mesh/deduplicator.ts +129 -0
  90. package/src/mesh/index.ts +6 -0
  91. package/src/mesh/router.ts +258 -0
  92. package/src/protocol/binary.ts +345 -0
  93. package/src/protocol/constants.ts +43 -0
  94. package/src/protocol/index.ts +15 -0
  95. package/src/protocol/packets.ts +223 -0
  96. package/src/protocol/types.ts +182 -0
  97. package/src/session/index.ts +9 -0
  98. package/src/session/manager.ts +476 -0
  99. package/src/transport/ble.ts +553 -0
  100. package/src/transport/index.ts +10 -0
  101. package/src/ui/index.ts +1 -0
  102. package/src/ui/server.ts +569 -0
@@ -0,0 +1,310 @@
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 { MAX_FRAMED_FILE_BYTES, PADDING_BLOCK_SIZES, RECIPIENT_ID_SIZE, SENDER_ID_SIZE, SIGNATURE_SIZE, V1_HEADER_SIZE, V2_HEADER_SIZE, } from './constants.js';
19
+ import { PacketFlags, PeerID } from './types.js';
20
+ /**
21
+ * Calculate optimal padding size for traffic analysis resistance
22
+ */
23
+ function optimalBlockSize(dataLength) {
24
+ for (const size of PADDING_BLOCK_SIZES) {
25
+ if (dataLength <= size - 1)
26
+ return size;
27
+ }
28
+ return Math.ceil((dataLength + 1) / 256) * 256;
29
+ }
30
+ /**
31
+ * PKCS#7 style padding
32
+ */
33
+ function pad(data, targetSize) {
34
+ const paddingLength = targetSize - data.length;
35
+ if (paddingLength <= 0)
36
+ return data;
37
+ const padded = new Uint8Array(targetSize);
38
+ padded.set(data);
39
+ padded.fill(paddingLength, data.length);
40
+ return padded;
41
+ }
42
+ /**
43
+ * Remove PKCS#7 padding
44
+ */
45
+ function unpad(data) {
46
+ if (data.length === 0)
47
+ return data;
48
+ const paddingLength = data[data.length - 1];
49
+ if (paddingLength === 0 || paddingLength > data.length)
50
+ return data;
51
+ // Verify padding is consistent
52
+ for (let i = data.length - paddingLength; i < data.length; i++) {
53
+ if (data[i] !== paddingLength)
54
+ return data;
55
+ }
56
+ return data.subarray(0, data.length - paddingLength);
57
+ }
58
+ /**
59
+ * Encode a BitchatPacket to binary wire format
60
+ */
61
+ export function encode(packet, options = {}) {
62
+ const { padding = true } = options;
63
+ const version = packet.version;
64
+ if (version !== 1 && version !== 2) {
65
+ throw new Error(`Unsupported protocol version: ${version}`);
66
+ }
67
+ const headerSize = version === 2 ? V2_HEADER_SIZE : V1_HEADER_SIZE;
68
+ // Build flags
69
+ let flags = 0;
70
+ if (packet.recipientID && !packet.recipientID.isEmpty)
71
+ flags |= PacketFlags.HAS_RECIPIENT;
72
+ if (packet.signature)
73
+ flags |= PacketFlags.HAS_SIGNATURE;
74
+ if (packet.route && packet.route.length > 0 && version >= 2)
75
+ flags |= PacketFlags.HAS_ROUTE;
76
+ if (packet.isRSR)
77
+ flags |= PacketFlags.IS_RSR;
78
+ // TODO: compression flag
79
+ // Calculate sizes
80
+ const hasRecipient = (flags & PacketFlags.HAS_RECIPIENT) !== 0;
81
+ const hasSignature = (flags & PacketFlags.HAS_SIGNATURE) !== 0;
82
+ const hasRoute = (flags & PacketFlags.HAS_ROUTE) !== 0;
83
+ const routeLength = hasRoute ? 1 + (packet.route?.length ?? 0) * SENDER_ID_SIZE : 0;
84
+ const payloadSize = packet.payload.length;
85
+ // Validate sizes
86
+ if (version === 1 && payloadSize > 0xffff) {
87
+ throw new Error('Payload too large for v1 packet');
88
+ }
89
+ if (version === 2 && payloadSize > 0xffffffff) {
90
+ throw new Error('Payload too large for v2 packet');
91
+ }
92
+ // Calculate total size
93
+ const totalSize = headerSize +
94
+ SENDER_ID_SIZE +
95
+ (hasRecipient ? RECIPIENT_ID_SIZE : 0) +
96
+ routeLength +
97
+ payloadSize +
98
+ (hasSignature ? SIGNATURE_SIZE : 0);
99
+ const buffer = new Uint8Array(totalSize);
100
+ const view = new DataView(buffer.buffer);
101
+ let offset = 0;
102
+ // Header
103
+ buffer[offset++] = version;
104
+ buffer[offset++] = packet.type;
105
+ buffer[offset++] = packet.ttl;
106
+ // Timestamp (8 bytes big-endian)
107
+ view.setBigUint64(offset, packet.timestamp, false);
108
+ offset += 8;
109
+ // Flags
110
+ buffer[offset++] = flags;
111
+ // Payload length
112
+ if (version === 2) {
113
+ view.setUint32(offset, payloadSize, false);
114
+ offset += 4;
115
+ }
116
+ else {
117
+ view.setUint16(offset, payloadSize, false);
118
+ offset += 2;
119
+ }
120
+ // Sender ID
121
+ const senderBytes = packet.senderID.toBytes();
122
+ buffer.set(senderBytes, offset);
123
+ offset += SENDER_ID_SIZE;
124
+ // Recipient ID (optional)
125
+ if (hasRecipient && packet.recipientID) {
126
+ const recipientBytes = packet.recipientID.toBytes();
127
+ buffer.set(recipientBytes, offset);
128
+ offset += RECIPIENT_ID_SIZE;
129
+ }
130
+ // Route (optional, v2+)
131
+ if (hasRoute && packet.route) {
132
+ buffer[offset++] = packet.route.length;
133
+ for (const hop of packet.route) {
134
+ buffer.set(hop.toBytes(), offset);
135
+ offset += SENDER_ID_SIZE;
136
+ }
137
+ }
138
+ // Payload
139
+ buffer.set(packet.payload, offset);
140
+ offset += payloadSize;
141
+ // Signature (optional)
142
+ if (hasSignature && packet.signature) {
143
+ buffer.set(packet.signature.subarray(0, SIGNATURE_SIZE), offset);
144
+ offset += SIGNATURE_SIZE;
145
+ }
146
+ if (padding) {
147
+ const targetSize = optimalBlockSize(buffer.length);
148
+ return pad(buffer, targetSize);
149
+ }
150
+ return buffer;
151
+ }
152
+ /**
153
+ * Decode binary wire format to BitchatPacket
154
+ */
155
+ export function decode(data) {
156
+ // Try decode as-is first
157
+ let packet = decodeCore(data);
158
+ if (packet)
159
+ return packet;
160
+ // Try after removing padding
161
+ const unpaddedData = unpad(data);
162
+ if (unpaddedData.length !== data.length) {
163
+ packet = decodeCore(unpaddedData);
164
+ }
165
+ return packet;
166
+ }
167
+ function decodeCore(data) {
168
+ if (data.length < V1_HEADER_SIZE + SENDER_ID_SIZE) {
169
+ return null;
170
+ }
171
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
172
+ let offset = 0;
173
+ const version = data[offset++];
174
+ if (version !== 1 && version !== 2)
175
+ return null;
176
+ const headerSize = version === 2 ? V2_HEADER_SIZE : V1_HEADER_SIZE;
177
+ if (data.length < headerSize + SENDER_ID_SIZE)
178
+ return null;
179
+ const type = data[offset++];
180
+ const ttl = data[offset++];
181
+ // Timestamp (8 bytes big-endian)
182
+ const timestamp = view.getBigUint64(offset, false);
183
+ offset += 8;
184
+ const flags = data[offset++];
185
+ const hasRecipient = (flags & PacketFlags.HAS_RECIPIENT) !== 0;
186
+ const hasSignature = (flags & PacketFlags.HAS_SIGNATURE) !== 0;
187
+ const isCompressed = (flags & PacketFlags.IS_COMPRESSED) !== 0;
188
+ const hasRoute = version >= 2 && (flags & PacketFlags.HAS_ROUTE) !== 0;
189
+ const isRSR = (flags & PacketFlags.IS_RSR) !== 0;
190
+ // Payload length
191
+ let payloadLength;
192
+ if (version === 2) {
193
+ payloadLength = view.getUint32(offset, false);
194
+ offset += 4;
195
+ }
196
+ else {
197
+ payloadLength = view.getUint16(offset, false);
198
+ offset += 2;
199
+ }
200
+ // Validate
201
+ if (payloadLength < 0 || payloadLength > MAX_FRAMED_FILE_BYTES)
202
+ return null;
203
+ // Sender ID
204
+ if (offset + SENDER_ID_SIZE > data.length)
205
+ return null;
206
+ const senderID = new PeerID(data.subarray(offset, offset + SENDER_ID_SIZE));
207
+ offset += SENDER_ID_SIZE;
208
+ // Recipient ID
209
+ let recipientID;
210
+ if (hasRecipient) {
211
+ if (offset + RECIPIENT_ID_SIZE > data.length)
212
+ return null;
213
+ recipientID = new PeerID(data.subarray(offset, offset + RECIPIENT_ID_SIZE));
214
+ offset += RECIPIENT_ID_SIZE;
215
+ }
216
+ // Route
217
+ let route;
218
+ if (hasRoute) {
219
+ if (offset >= data.length)
220
+ return null;
221
+ const routeCount = data[offset++];
222
+ if (routeCount > 0) {
223
+ route = [];
224
+ for (let i = 0; i < routeCount; i++) {
225
+ if (offset + SENDER_ID_SIZE > data.length)
226
+ return null;
227
+ route.push(new PeerID(data.subarray(offset, offset + SENDER_ID_SIZE)));
228
+ offset += SENDER_ID_SIZE;
229
+ }
230
+ }
231
+ }
232
+ // Payload
233
+ if (isCompressed) {
234
+ // TODO: Handle compression
235
+ // For now, just read the raw bytes
236
+ const lengthFieldSize = version === 2 ? 4 : 2;
237
+ if (payloadLength < lengthFieldSize)
238
+ return null;
239
+ // Skip original size field
240
+ offset += lengthFieldSize;
241
+ const compressedSize = payloadLength - lengthFieldSize;
242
+ if (offset + compressedSize > data.length)
243
+ return null;
244
+ // Return compressed data as-is for now
245
+ const payload = new Uint8Array(data.subarray(offset, offset + compressedSize));
246
+ offset += compressedSize;
247
+ // Signature
248
+ let signature;
249
+ if (hasSignature) {
250
+ if (offset + SIGNATURE_SIZE > data.length)
251
+ return null;
252
+ signature = new Uint8Array(data.subarray(offset, offset + SIGNATURE_SIZE));
253
+ }
254
+ return {
255
+ version,
256
+ type,
257
+ ttl,
258
+ timestamp,
259
+ senderID,
260
+ recipientID,
261
+ payload,
262
+ signature,
263
+ route,
264
+ isRSR,
265
+ };
266
+ }
267
+ if (offset + payloadLength > data.length)
268
+ return null;
269
+ const payload = new Uint8Array(data.subarray(offset, offset + payloadLength));
270
+ offset += payloadLength;
271
+ // Signature
272
+ let signature;
273
+ if (hasSignature) {
274
+ if (offset + SIGNATURE_SIZE > data.length)
275
+ return null;
276
+ signature = new Uint8Array(data.subarray(offset, offset + SIGNATURE_SIZE));
277
+ }
278
+ return {
279
+ version,
280
+ type,
281
+ ttl,
282
+ timestamp,
283
+ senderID,
284
+ recipientID,
285
+ payload,
286
+ signature,
287
+ route,
288
+ isRSR,
289
+ };
290
+ }
291
+ /**
292
+ * Create binary representation for signing (without signature, TTL=0)
293
+ */
294
+ export function encodeForSigning(packet) {
295
+ const unsigned = {
296
+ ...packet,
297
+ signature: undefined,
298
+ ttl: 0,
299
+ isRSR: false,
300
+ };
301
+ // Must use padding: true to match Swift's toBinaryDataForSigning()
302
+ return encode(unsigned, { padding: true });
303
+ }
304
+ /**
305
+ * Create message deduplication ID
306
+ */
307
+ export function makeDeduplicationID(packet) {
308
+ return `${packet.senderID.toHex()}-${packet.timestamp}-${packet.type}`;
309
+ }
310
+ //# sourceMappingURL=binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary.js","sourceRoot":"","sources":["../../src/protocol/binary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Bitchat Protocol Constants
3
+ * From: bitchat/Protocols/BitchatProtocol.swift
4
+ * bitchat/Services/BLE/BLEService.swift
5
+ */
6
+ export declare const SERVICE_UUID = "f47b5e2d-4a9e-4c5a-9b3f-8e1d2c3a4b5c";
7
+ export declare const SERVICE_UUID_TESTNET = "f47b5e2d-4a9e-4c5a-9b3f-8e1d2c3a4b5a";
8
+ export declare const CHARACTERISTIC_UUID = "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d";
9
+ export declare const SENDER_ID_SIZE = 8;
10
+ export declare const RECIPIENT_ID_SIZE = 8;
11
+ export declare const SIGNATURE_SIZE = 64;
12
+ export declare const V1_HEADER_SIZE = 14;
13
+ export declare const V2_HEADER_SIZE = 16;
14
+ export declare const DEFAULT_TTL = 7;
15
+ export declare const MAX_TTL = 7;
16
+ export declare const MAX_MESSAGE_LENGTH = 4096;
17
+ export declare const MAX_FRAMED_FILE_BYTES: number;
18
+ export declare const BLE_DEFAULT_FRAGMENT_SIZE = 182;
19
+ export declare const BLE_MAX_MTU = 512;
20
+ export declare const PADDING_BLOCK_SIZES: readonly [256, 512, 1024, 2048];
21
+ export declare const ANNOUNCE_MIN_INTERVAL_MS = 5000;
22
+ export declare const MAINTENANCE_INTERVAL_MS = 30000;
23
+ export declare const CONNECT_RATE_LIMIT_INTERVAL_MS = 1000;
24
+ export declare const REACHABILITY_RETENTION_VERIFIED_MS = 300000;
25
+ export declare const REACHABILITY_RETENTION_UNVERIFIED_MS = 60000;
26
+ export declare const MAX_CENTRAL_LINKS = 7;
27
+ export declare const MAX_IN_FLIGHT_ASSEMBLIES = 10;
28
+ export declare const HIGH_DEGREE_THRESHOLD = 5;
29
+ export declare const COMPRESSION_THRESHOLD = 256;
30
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,eAAO,MAAM,YAAY,yCAAyC,CAAC;AACnE,eAAO,MAAM,oBAAoB,yCAAyC,CAAC;AAC3E,eAAO,MAAM,mBAAmB,yCAAyC,CAAC;AAG1E,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,cAAc,KAAK,CAAC;AAGjC,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,kBAAkB,OAAO,CAAC;AACvC,eAAO,MAAM,qBAAqB,QAAmB,CAAC;AACtD,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,WAAW,MAAM,CAAC;AAG/B,eAAO,MAAM,mBAAmB,iCAAkC,CAAC;AAGnE,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,uBAAuB,QAAQ,CAAC;AAC7C,eAAO,MAAM,8BAA8B,OAAO,CAAC;AACnD,eAAO,MAAM,kCAAkC,SAAS,CAAC;AACzD,eAAO,MAAM,oCAAoC,QAAQ,CAAC;AAG1D,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAGvC,eAAO,MAAM,qBAAqB,MAAM,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Bitchat Protocol Constants
3
+ * From: bitchat/Protocols/BitchatProtocol.swift
4
+ * bitchat/Services/BLE/BLEService.swift
5
+ */
6
+ // BLE Service and Characteristic UUIDs
7
+ export const SERVICE_UUID = 'f47b5e2d-4a9e-4c5a-9b3f-8e1d2c3a4b5c'; // mainnet
8
+ export const SERVICE_UUID_TESTNET = 'f47b5e2d-4a9e-4c5a-9b3f-8e1d2c3a4b5a';
9
+ export const CHARACTERISTIC_UUID = 'a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d';
10
+ // Binary protocol sizes
11
+ export const SENDER_ID_SIZE = 8;
12
+ export const RECIPIENT_ID_SIZE = 8;
13
+ export const SIGNATURE_SIZE = 64;
14
+ export const V1_HEADER_SIZE = 14;
15
+ export const V2_HEADER_SIZE = 16;
16
+ // Protocol limits
17
+ export const DEFAULT_TTL = 7;
18
+ export const MAX_TTL = 7;
19
+ export const MAX_MESSAGE_LENGTH = 4096;
20
+ export const MAX_FRAMED_FILE_BYTES = 10 * 1024 * 1024; // 10MB
21
+ export const BLE_DEFAULT_FRAGMENT_SIZE = 182;
22
+ export const BLE_MAX_MTU = 512;
23
+ // Padding block sizes for traffic analysis resistance
24
+ export const PADDING_BLOCK_SIZES = [256, 512, 1024, 2048];
25
+ // Timing constants (milliseconds)
26
+ export const ANNOUNCE_MIN_INTERVAL_MS = 5000;
27
+ export const MAINTENANCE_INTERVAL_MS = 30000;
28
+ export const CONNECT_RATE_LIMIT_INTERVAL_MS = 1000;
29
+ export const REACHABILITY_RETENTION_VERIFIED_MS = 300000; // 5 min
30
+ export const REACHABILITY_RETENTION_UNVERIFIED_MS = 60000; // 1 min
31
+ // Connection limits
32
+ export const MAX_CENTRAL_LINKS = 7;
33
+ export const MAX_IN_FLIGHT_ASSEMBLIES = 10;
34
+ export const HIGH_DEGREE_THRESHOLD = 5;
35
+ // Compression threshold
36
+ export const COMPRESSION_THRESHOLD = 256;
37
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/protocol/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,uCAAuC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,sCAAsC,CAAC,CAAC,UAAU;AAC9E,MAAM,CAAC,MAAM,oBAAoB,GAAG,sCAAsC,CAAC;AAC3E,MAAM,CAAC,MAAM,mBAAmB,GAAG,sCAAsC,CAAC;AAE1E,wBAAwB;AACxB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,kBAAkB;AAClB,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAC7B,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAC9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAE/B,sDAAsD;AACtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAEnE,kCAAkC;AAClC,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,uBAAuB,GAAG,KAAK,CAAC;AAC7C,MAAM,CAAC,MAAM,8BAA8B,GAAG,IAAI,CAAC;AACnD,MAAM,CAAC,MAAM,kCAAkC,GAAG,MAAM,CAAC,CAAC,QAAQ;AAClE,MAAM,CAAC,MAAM,oCAAoC,GAAG,KAAK,CAAC,CAAC,QAAQ;AAEnE,oBAAoB;AACpB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AACnC,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAC3C,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC,wBAAwB;AACxB,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Protocol module exports
3
+ */
4
+ export { decode, encode, encodeForSigning, makeDeduplicationID } from './binary.js';
5
+ export * from './constants.js';
6
+ export { type AnnouncementData, decodeAnnouncement, decodePrivateMessage, encodeAnnouncement, encodePrivateMessage, type PrivateMessageData, } from './packets.js';
7
+ export * from './types.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/protocol/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACpF,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,kBAAkB,GACxB,MAAM,cAAc,CAAC;AACtB,cAAc,YAAY,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Protocol module exports
3
+ */
4
+ export { decode, encode, encodeForSigning, makeDeduplicationID } from './binary.js';
5
+ export * from './constants.js';
6
+ export { decodeAnnouncement, decodePrivateMessage, encodeAnnouncement, encodePrivateMessage, } from './packets.js';
7
+ export * from './types.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/protocol/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACpF,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAEL,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,GAErB,MAAM,cAAc,CAAC;AACtB,cAAc,YAAY,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Packet Payload Encoders/Decoders
3
+ * TLV (Type-Length-Value) format for announce and private message payloads
4
+ * From: bitchat/Protocols/Packets.swift
5
+ */
6
+ /**
7
+ * Announcement payload data
8
+ */
9
+ export interface AnnouncementData {
10
+ nickname: string;
11
+ noisePublicKey?: Uint8Array;
12
+ signingPublicKey?: Uint8Array;
13
+ directNeighbors?: Uint8Array[];
14
+ }
15
+ /**
16
+ * Private message payload data
17
+ */
18
+ export interface PrivateMessageData {
19
+ messageID: string;
20
+ content: string;
21
+ }
22
+ /**
23
+ * Encode announcement payload as TLV
24
+ */
25
+ export declare function encodeAnnouncement(data: AnnouncementData): Uint8Array;
26
+ /**
27
+ * Decode announcement payload from TLV
28
+ */
29
+ export declare function decodeAnnouncement(data: Uint8Array): AnnouncementData | null;
30
+ /**
31
+ * Encode private message payload as TLV
32
+ */
33
+ export declare function encodePrivateMessage(data: PrivateMessageData): Uint8Array;
34
+ /**
35
+ * Decode private message payload from TLV
36
+ */
37
+ export declare function decodePrivateMessage(data: Uint8Array): PrivateMessageData | null;
38
+ //# sourceMappingURL=packets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packets.d.ts","sourceRoot":"","sources":["../../src/protocol/packets.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,UAAU,CAAC;IAC5B,gBAAgB,CAAC,EAAE,UAAU,CAAC;IAC9B,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,UAAU,CA6CrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,gBAAgB,GAAG,IAAI,CAgD5E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,UAAU,CAiCzE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,kBAAkB,GAAG,IAAI,CAwChF"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Packet Payload Encoders/Decoders
3
+ * TLV (Type-Length-Value) format for announce and private message payloads
4
+ * From: bitchat/Protocols/Packets.swift
5
+ */
6
+ // TLV Types for Announcement
7
+ const AnnounceType = {
8
+ NICKNAME: 0x01,
9
+ NOISE_PUBLIC_KEY: 0x02,
10
+ SIGNING_PUBLIC_KEY: 0x03,
11
+ DIRECT_NEIGHBORS: 0x04,
12
+ };
13
+ // TLV Types for Private Message
14
+ const PrivateMessageType = {
15
+ MESSAGE_ID: 0x00,
16
+ CONTENT: 0x01,
17
+ };
18
+ /**
19
+ * Encode announcement payload as TLV
20
+ */
21
+ export function encodeAnnouncement(data) {
22
+ const parts = [];
23
+ // Nickname TLV
24
+ const nicknameBytes = new TextEncoder().encode(data.nickname);
25
+ if (nicknameBytes.length > 255) {
26
+ throw new Error('Nickname too long');
27
+ }
28
+ parts.push(new Uint8Array([AnnounceType.NICKNAME, nicknameBytes.length]));
29
+ parts.push(nicknameBytes);
30
+ // Noise public key TLV
31
+ if (data.noisePublicKey && data.noisePublicKey.length > 0) {
32
+ parts.push(new Uint8Array([AnnounceType.NOISE_PUBLIC_KEY, data.noisePublicKey.length]));
33
+ parts.push(data.noisePublicKey);
34
+ }
35
+ // Signing public key TLV
36
+ if (data.signingPublicKey && data.signingPublicKey.length > 0) {
37
+ parts.push(new Uint8Array([AnnounceType.SIGNING_PUBLIC_KEY, data.signingPublicKey.length]));
38
+ parts.push(data.signingPublicKey);
39
+ }
40
+ // Direct neighbors TLV
41
+ if (data.directNeighbors && data.directNeighbors.length > 0) {
42
+ const neighborsData = new Uint8Array(data.directNeighbors.length * 8);
43
+ let offset = 0;
44
+ for (const neighbor of data.directNeighbors) {
45
+ neighborsData.set(neighbor.subarray(0, 8), offset);
46
+ offset += 8;
47
+ }
48
+ parts.push(new Uint8Array([AnnounceType.DIRECT_NEIGHBORS, neighborsData.length]));
49
+ parts.push(neighborsData);
50
+ }
51
+ // Concatenate all parts
52
+ const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
53
+ const result = new Uint8Array(totalLength);
54
+ let offset = 0;
55
+ for (const part of parts) {
56
+ result.set(part, offset);
57
+ offset += part.length;
58
+ }
59
+ return result;
60
+ }
61
+ /**
62
+ * Decode announcement payload from TLV
63
+ */
64
+ export function decodeAnnouncement(data) {
65
+ let offset = 0;
66
+ let nickname;
67
+ let noisePublicKey;
68
+ let signingPublicKey;
69
+ let directNeighbors;
70
+ while (offset + 2 <= data.length) {
71
+ const type = data[offset++];
72
+ const length = data[offset++];
73
+ if (offset + length > data.length) {
74
+ return null; // Truncated
75
+ }
76
+ const value = data.subarray(offset, offset + length);
77
+ offset += length;
78
+ switch (type) {
79
+ case AnnounceType.NICKNAME:
80
+ nickname = new TextDecoder().decode(value);
81
+ break;
82
+ case AnnounceType.NOISE_PUBLIC_KEY:
83
+ noisePublicKey = Uint8Array.from(value);
84
+ break;
85
+ case AnnounceType.SIGNING_PUBLIC_KEY:
86
+ signingPublicKey = Uint8Array.from(value);
87
+ break;
88
+ case AnnounceType.DIRECT_NEIGHBORS:
89
+ directNeighbors = [];
90
+ for (let i = 0; i + 8 <= value.length; i += 8) {
91
+ directNeighbors.push(Uint8Array.from(value.subarray(i, i + 8)));
92
+ }
93
+ break;
94
+ // Unknown types are ignored
95
+ }
96
+ }
97
+ if (!nickname) {
98
+ return null; // Nickname is required
99
+ }
100
+ return {
101
+ nickname,
102
+ noisePublicKey,
103
+ signingPublicKey,
104
+ directNeighbors,
105
+ };
106
+ }
107
+ /**
108
+ * Encode private message payload as TLV
109
+ */
110
+ export function encodePrivateMessage(data) {
111
+ const parts = [];
112
+ // Message ID TLV
113
+ const idBytes = new TextEncoder().encode(data.messageID);
114
+ parts.push(new Uint8Array([PrivateMessageType.MESSAGE_ID, idBytes.length]));
115
+ parts.push(idBytes);
116
+ // Content TLV
117
+ const contentBytes = new TextEncoder().encode(data.content);
118
+ if (contentBytes.length > 65535) {
119
+ throw new Error('Content too long');
120
+ }
121
+ // For content, use 2-byte length since it can be long
122
+ parts.push(new Uint8Array([
123
+ PrivateMessageType.CONTENT,
124
+ (contentBytes.length >> 8) & 0xff,
125
+ contentBytes.length & 0xff,
126
+ ]));
127
+ parts.push(contentBytes);
128
+ // Concatenate
129
+ const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
130
+ const result = new Uint8Array(totalLength);
131
+ let offset = 0;
132
+ for (const part of parts) {
133
+ result.set(part, offset);
134
+ offset += part.length;
135
+ }
136
+ return result;
137
+ }
138
+ /**
139
+ * Decode private message payload from TLV
140
+ */
141
+ export function decodePrivateMessage(data) {
142
+ let offset = 0;
143
+ let messageID;
144
+ let content;
145
+ while (offset + 2 <= data.length) {
146
+ const type = data[offset++];
147
+ // Content uses 2-byte length
148
+ let length;
149
+ if (type === PrivateMessageType.CONTENT) {
150
+ if (offset + 2 > data.length)
151
+ return null;
152
+ length = (data[offset] << 8) | data[offset + 1];
153
+ offset += 2;
154
+ }
155
+ else {
156
+ length = data[offset++];
157
+ }
158
+ if (offset + length > data.length) {
159
+ return null;
160
+ }
161
+ const value = data.subarray(offset, offset + length);
162
+ offset += length;
163
+ switch (type) {
164
+ case PrivateMessageType.MESSAGE_ID:
165
+ messageID = new TextDecoder().decode(value);
166
+ break;
167
+ case PrivateMessageType.CONTENT:
168
+ content = new TextDecoder().decode(value);
169
+ break;
170
+ }
171
+ }
172
+ if (!messageID || !content) {
173
+ return null;
174
+ }
175
+ return { messageID, content };
176
+ }
177
+ //# sourceMappingURL=packets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packets.js","sourceRoot":"","sources":["../../src/protocol/packets.ts"],"names":[],"mappings":"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"}