react-native-ble-mesh 2.1.0 → 2.1.3
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/package.json +9 -2
- package/src/MeshNetwork.js +48 -46
- package/src/constants/audio.js +4 -4
- package/src/constants/ble.js +1 -1
- package/src/constants/crypto.js +1 -1
- package/src/constants/errors.js +2 -2
- package/src/constants/events.js +1 -1
- package/src/constants/protocol.js +2 -2
- package/src/crypto/AutoCrypto.js +2 -0
- package/src/crypto/CryptoProvider.js +17 -17
- package/src/crypto/providers/ExpoCryptoProvider.js +12 -7
- package/src/crypto/providers/QuickCryptoProvider.js +50 -15
- package/src/crypto/providers/TweetNaClProvider.js +9 -7
- package/src/errors/AudioError.js +2 -1
- package/src/errors/ConnectionError.js +2 -2
- package/src/errors/CryptoError.js +1 -1
- package/src/errors/HandshakeError.js +2 -2
- package/src/errors/MeshError.js +4 -4
- package/src/errors/MessageError.js +2 -2
- package/src/errors/ValidationError.js +3 -3
- package/src/expo/withBLEMesh.js +10 -10
- package/src/hooks/AppStateManager.js +10 -4
- package/src/hooks/useMesh.js +7 -7
- package/src/hooks/useMessages.js +13 -12
- package/src/hooks/usePeers.js +10 -9
- package/src/index.js +2 -2
- package/src/mesh/dedup/BloomFilter.js +1 -0
- package/src/mesh/dedup/DedupManager.js +4 -7
- package/src/mesh/dedup/MessageCache.js +3 -0
- package/src/mesh/fragment/Assembler.js +5 -4
- package/src/mesh/fragment/Fragmenter.js +2 -2
- package/src/mesh/monitor/ConnectionQuality.js +17 -8
- package/src/mesh/monitor/NetworkMonitor.js +22 -15
- package/src/mesh/peer/Peer.js +4 -9
- package/src/mesh/peer/PeerDiscovery.js +18 -19
- package/src/mesh/peer/PeerManager.js +14 -14
- package/src/mesh/router/MessageRouter.js +15 -15
- package/src/mesh/router/PathFinder.js +10 -13
- package/src/mesh/router/RouteTable.js +8 -7
- package/src/mesh/store/StoreAndForwardManager.js +20 -23
- package/src/protocol/message.js +5 -13
- package/src/protocol/serializer.js +4 -4
- package/src/protocol/validator.js +7 -6
- package/src/service/BatteryOptimizer.js +18 -17
- package/src/service/EmergencyManager.js +19 -26
- package/src/service/HandshakeManager.js +100 -2
- package/src/service/MeshService.js +106 -22
- package/src/service/SessionManager.js +38 -3
- package/src/service/audio/AudioManager.js +80 -38
- package/src/service/audio/buffer/FrameBuffer.js +7 -8
- package/src/service/audio/buffer/JitterBuffer.js +1 -1
- package/src/service/audio/codec/LC3Codec.js +22 -20
- package/src/service/audio/codec/LC3Decoder.js +10 -10
- package/src/service/audio/codec/LC3Encoder.js +11 -9
- package/src/service/audio/session/AudioSession.js +14 -17
- package/src/service/audio/session/VoiceMessage.js +15 -22
- package/src/service/audio/transport/AudioFragmenter.js +17 -9
- package/src/service/audio/transport/AudioFramer.js +8 -12
- package/src/service/file/FileAssembler.js +4 -2
- package/src/service/file/FileChunker.js +1 -1
- package/src/service/file/FileManager.js +26 -20
- package/src/service/file/FileMessage.js +7 -12
- package/src/service/text/TextManager.js +55 -28
- package/src/service/text/broadcast/BroadcastManager.js +14 -17
- package/src/service/text/channel/Channel.js +10 -14
- package/src/service/text/channel/ChannelManager.js +10 -10
- package/src/service/text/message/TextMessage.js +12 -19
- package/src/service/text/message/TextSerializer.js +2 -2
- package/src/storage/AsyncStorageAdapter.js +17 -14
- package/src/storage/MemoryStorage.js +11 -8
- package/src/storage/MessageStore.js +22 -30
- package/src/storage/Storage.js +9 -9
- package/src/transport/BLETransport.js +16 -14
- package/src/transport/MockTransport.js +7 -2
- package/src/transport/MultiTransport.js +13 -6
- package/src/transport/Transport.js +9 -9
- package/src/transport/WiFiDirectTransport.js +25 -24
- package/src/transport/adapters/BLEAdapter.js +19 -19
- package/src/transport/adapters/NodeBLEAdapter.js +24 -23
- package/src/transport/adapters/RNBLEAdapter.js +19 -24
- package/src/utils/EventEmitter.js +17 -12
- package/src/utils/LRUCache.js +10 -4
- package/src/utils/RateLimiter.js +1 -1
- package/src/utils/compression.js +6 -8
- package/src/utils/encoding.js +8 -2
- package/src/utils/retry.js +11 -13
- package/src/utils/time.js +9 -4
- package/src/utils/validation.js +1 -1
package/src/index.js
CHANGED
|
@@ -69,7 +69,7 @@ function createMeshNetwork(config) {
|
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* Create a new MeshService instance
|
|
72
|
-
* @param {
|
|
72
|
+
* @param {any} [config] - Configuration options
|
|
73
73
|
* @returns {MeshService}
|
|
74
74
|
*/
|
|
75
75
|
function createMeshService(config) {
|
|
@@ -80,7 +80,7 @@ function createMeshService(config) {
|
|
|
80
80
|
* Create and initialize a MeshService for Node.js usage
|
|
81
81
|
* @param {Object} [options] - Configuration options
|
|
82
82
|
* @param {string} [options.displayName='MeshNode'] - Display name for this node
|
|
83
|
-
* @param {
|
|
83
|
+
* @param {any} [options.storage=null] - Storage adapter (null for MemoryStorage)
|
|
84
84
|
* @returns {Promise<MeshService>} Initialized MeshService
|
|
85
85
|
* @example
|
|
86
86
|
* const mesh = await createNodeMesh({ displayName: 'Alice' });
|
|
@@ -14,6 +14,7 @@ const FNV_PRIME = 0x01000193;
|
|
|
14
14
|
const FNV_OFFSET = 0x811c9dc5;
|
|
15
15
|
|
|
16
16
|
// Cached TextEncoder singleton (avoids per-call allocation)
|
|
17
|
+
/** @type {any} */
|
|
17
18
|
let _encoder = null;
|
|
18
19
|
function _getEncoder() {
|
|
19
20
|
if (!_encoder && typeof TextEncoder !== 'undefined') {
|
|
@@ -29,13 +29,10 @@ const DEFAULT_CONFIG = {
|
|
|
29
29
|
class DedupManager {
|
|
30
30
|
/**
|
|
31
31
|
* Creates a new DedupManager
|
|
32
|
-
* @param {
|
|
33
|
-
* @param {number} [options.bloomFilterSize] - Size of Bloom filter in bits
|
|
34
|
-
* @param {number} [options.bloomHashCount] - Number of hash functions
|
|
35
|
-
* @param {number} [options.cacheSize] - Maximum LRU cache entries
|
|
36
|
-
* @param {number} [options.autoResetThreshold] - Fill ratio for auto reset
|
|
32
|
+
* @param {any} [options] - Configuration options *
|
|
37
33
|
*/
|
|
38
34
|
constructor(options = {}) {
|
|
35
|
+
/** @type {any} */
|
|
39
36
|
const config = { ...DEFAULT_CONFIG, ...options };
|
|
40
37
|
|
|
41
38
|
/**
|
|
@@ -78,7 +75,7 @@ class DedupManager {
|
|
|
78
75
|
|
|
79
76
|
/**
|
|
80
77
|
* Statistics for monitoring
|
|
81
|
-
* @type {
|
|
78
|
+
* @type {any}
|
|
82
79
|
* @private
|
|
83
80
|
*/
|
|
84
81
|
this._stats = {
|
|
@@ -200,7 +197,7 @@ class DedupManager {
|
|
|
200
197
|
|
|
201
198
|
/**
|
|
202
199
|
* Gets deduplication statistics
|
|
203
|
-
* @returns {
|
|
200
|
+
* @returns {any} Statistics object
|
|
204
201
|
*/
|
|
205
202
|
getStats() {
|
|
206
203
|
return {
|
|
@@ -19,7 +19,9 @@ class CacheNode {
|
|
|
19
19
|
constructor(key, timestamp) {
|
|
20
20
|
this.key = key;
|
|
21
21
|
this.timestamp = timestamp;
|
|
22
|
+
/** @type {CacheNode|null} */
|
|
22
23
|
this.prev = null;
|
|
24
|
+
/** @type {CacheNode|null} */
|
|
23
25
|
this.next = null;
|
|
24
26
|
}
|
|
25
27
|
}
|
|
@@ -207,6 +209,7 @@ class MessageCache {
|
|
|
207
209
|
*/
|
|
208
210
|
getAll() {
|
|
209
211
|
const result = [];
|
|
212
|
+
/** @type {CacheNode|null} */
|
|
210
213
|
let node = this._head;
|
|
211
214
|
while (node) {
|
|
212
215
|
result.push(node.key);
|
|
@@ -31,6 +31,7 @@ class PendingFragmentSet {
|
|
|
31
31
|
constructor(messageId, total, timeout) {
|
|
32
32
|
this.messageId = messageId;
|
|
33
33
|
this.total = total;
|
|
34
|
+
/** @type {Map<number, Uint8Array>} */
|
|
34
35
|
this.received = new Map();
|
|
35
36
|
this.createdAt = Date.now();
|
|
36
37
|
this.expiresAt = this.createdAt + timeout;
|
|
@@ -97,7 +98,7 @@ class PendingFragmentSet {
|
|
|
97
98
|
|
|
98
99
|
/**
|
|
99
100
|
* Gets progress information
|
|
100
|
-
* @returns {
|
|
101
|
+
* @returns {any} Progress { received, total, percent }
|
|
101
102
|
*/
|
|
102
103
|
getProgress() {
|
|
103
104
|
return {
|
|
@@ -137,7 +138,7 @@ class Assembler {
|
|
|
137
138
|
|
|
138
139
|
/**
|
|
139
140
|
* Statistics
|
|
140
|
-
* @type {
|
|
141
|
+
* @type {any}
|
|
141
142
|
* @private
|
|
142
143
|
*/
|
|
143
144
|
this._stats = {
|
|
@@ -236,7 +237,7 @@ class Assembler {
|
|
|
236
237
|
/**
|
|
237
238
|
* Gets progress for a pending message
|
|
238
239
|
* @param {string} messageId - Message ID
|
|
239
|
-
* @returns {
|
|
240
|
+
* @returns {any} Progress or null if not found
|
|
240
241
|
*/
|
|
241
242
|
getProgress(messageId) {
|
|
242
243
|
const pendingSet = this._pending.get(messageId);
|
|
@@ -254,7 +255,7 @@ class Assembler {
|
|
|
254
255
|
|
|
255
256
|
/**
|
|
256
257
|
* Gets assembler statistics
|
|
257
|
-
* @returns {
|
|
258
|
+
* @returns {any} Statistics
|
|
258
259
|
*/
|
|
259
260
|
getStats() {
|
|
260
261
|
return {
|
|
@@ -66,7 +66,7 @@ function createFragmentHeader(index, total, payloadLength) {
|
|
|
66
66
|
/**
|
|
67
67
|
* Parses a fragment header
|
|
68
68
|
* @param {Uint8Array} data - Fragment data
|
|
69
|
-
* @returns {
|
|
69
|
+
* @returns {any} Parsed header { index, total, payloadLength }
|
|
70
70
|
*/
|
|
71
71
|
function parseFragmentHeader(data) {
|
|
72
72
|
if (data.length < FRAGMENT_HEADER_SIZE) {
|
|
@@ -139,7 +139,7 @@ function fragment(payload, messageId, maxSize = DEFAULT_FRAGMENT_SIZE) {
|
|
|
139
139
|
/**
|
|
140
140
|
* Gets fragment information without parsing full data
|
|
141
141
|
* @param {Uint8Array} fragmentData - Fragment data
|
|
142
|
-
* @returns {
|
|
142
|
+
* @returns {any} Fragment info { index, total, payloadLength, payload }
|
|
143
143
|
*/
|
|
144
144
|
function getFragmentInfo(fragmentData) {
|
|
145
145
|
const header = parseFragmentHeader(fragmentData);
|
|
@@ -12,7 +12,7 @@ const EventEmitter = require('../../utils/EventEmitter');
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Connection quality levels
|
|
15
|
-
* @constant {
|
|
15
|
+
* @constant {any}
|
|
16
16
|
*/
|
|
17
17
|
const QUALITY_LEVEL = Object.freeze({
|
|
18
18
|
EXCELLENT: 'excellent',
|
|
@@ -24,7 +24,7 @@ const QUALITY_LEVEL = Object.freeze({
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Default quality configuration
|
|
27
|
-
* @constant {
|
|
27
|
+
* @constant {any}
|
|
28
28
|
*/
|
|
29
29
|
const DEFAULT_CONFIG = Object.freeze({
|
|
30
30
|
/** How often to recalculate quality (ms) */
|
|
@@ -50,8 +50,13 @@ const DEFAULT_CONFIG = Object.freeze({
|
|
|
50
50
|
* @class PeerQualityTracker
|
|
51
51
|
*/
|
|
52
52
|
class PeerQualityTracker {
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} peerId
|
|
55
|
+
* @param {any} config
|
|
56
|
+
*/
|
|
53
57
|
constructor(peerId, config) {
|
|
54
58
|
this.peerId = peerId;
|
|
59
|
+
/** @type {any} */
|
|
55
60
|
this._config = config;
|
|
56
61
|
// Circular buffer for RSSI samples
|
|
57
62
|
this._rssiSamples = new Float64Array(config.sampleSize);
|
|
@@ -66,6 +71,7 @@ class PeerQualityTracker {
|
|
|
66
71
|
this._packetsSent = 0;
|
|
67
72
|
this._packetsAcked = 0;
|
|
68
73
|
this._bytesTransferred = 0;
|
|
74
|
+
/** @type {number|null} */
|
|
69
75
|
this._transferStartTime = null;
|
|
70
76
|
this._lastActivity = Date.now();
|
|
71
77
|
this._transport = 'ble';
|
|
@@ -193,7 +199,7 @@ class PeerQualityTracker {
|
|
|
193
199
|
/**
|
|
194
200
|
* Calculates quality score (0-1) for a metric
|
|
195
201
|
* @param {number|null} value - Metric value
|
|
196
|
-
* @param {
|
|
202
|
+
* @param {any} thresholds - {excellent, good, fair}
|
|
197
203
|
* @param {boolean} [higherIsBetter=false]
|
|
198
204
|
* @returns {number}
|
|
199
205
|
*/
|
|
@@ -216,7 +222,7 @@ class PeerQualityTracker {
|
|
|
216
222
|
|
|
217
223
|
/**
|
|
218
224
|
* Calculates overall quality
|
|
219
|
-
* @returns {
|
|
225
|
+
* @returns {any} Quality report
|
|
220
226
|
*/
|
|
221
227
|
calculate() {
|
|
222
228
|
if (this.isTimedOut()) {
|
|
@@ -251,6 +257,7 @@ class PeerQualityTracker {
|
|
|
251
257
|
if (score >= 0.8) { level = QUALITY_LEVEL.EXCELLENT; } else if (score >= 0.6) { level = QUALITY_LEVEL.GOOD; } else if (score >= 0.4) { level = QUALITY_LEVEL.FAIR; } else { level = QUALITY_LEVEL.POOR; }
|
|
252
258
|
|
|
253
259
|
const previousLevel = this._currentLevel;
|
|
260
|
+
// @ts-ignore
|
|
254
261
|
this._currentLevel = level;
|
|
255
262
|
|
|
256
263
|
return {
|
|
@@ -275,13 +282,15 @@ class PeerQualityTracker {
|
|
|
275
282
|
*/
|
|
276
283
|
class ConnectionQuality extends EventEmitter {
|
|
277
284
|
/**
|
|
278
|
-
* @param {
|
|
285
|
+
* @param {any} [config={}]
|
|
279
286
|
*/
|
|
280
287
|
constructor(config = {}) {
|
|
281
288
|
super();
|
|
289
|
+
/** @type {any} */
|
|
282
290
|
this._config = { ...DEFAULT_CONFIG, ...config };
|
|
283
291
|
/** @type {Map<string, PeerQualityTracker>} */
|
|
284
292
|
this._peers = new Map();
|
|
293
|
+
/** @type {any} */
|
|
285
294
|
this._updateTimer = null;
|
|
286
295
|
}
|
|
287
296
|
|
|
@@ -321,7 +330,7 @@ class ConnectionQuality extends EventEmitter {
|
|
|
321
330
|
if (!this._peers.has(peerId)) {
|
|
322
331
|
this._peers.set(peerId, new PeerQualityTracker(peerId, this._config));
|
|
323
332
|
}
|
|
324
|
-
return this._peers.get(peerId);
|
|
333
|
+
return /** @type {PeerQualityTracker} */ (this._peers.get(peerId));
|
|
325
334
|
}
|
|
326
335
|
|
|
327
336
|
/**
|
|
@@ -387,7 +396,7 @@ class ConnectionQuality extends EventEmitter {
|
|
|
387
396
|
/**
|
|
388
397
|
* Gets quality for a specific peer
|
|
389
398
|
* @param {string} peerId
|
|
390
|
-
* @returns {
|
|
399
|
+
* @returns {any}
|
|
391
400
|
*/
|
|
392
401
|
getQuality(peerId) {
|
|
393
402
|
const tracker = this._peers.get(peerId);
|
|
@@ -397,7 +406,7 @@ class ConnectionQuality extends EventEmitter {
|
|
|
397
406
|
|
|
398
407
|
/**
|
|
399
408
|
* Gets quality for all peers
|
|
400
|
-
* @returns {
|
|
409
|
+
* @returns {any[]}
|
|
401
410
|
*/
|
|
402
411
|
getAllQuality() {
|
|
403
412
|
const results = [];
|
|
@@ -12,7 +12,7 @@ const EventEmitter = require('../../utils/EventEmitter');
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Health status levels
|
|
15
|
-
* @constant {
|
|
15
|
+
* @constant {any}
|
|
16
16
|
*/
|
|
17
17
|
const HEALTH_STATUS = Object.freeze({
|
|
18
18
|
GOOD: 'good',
|
|
@@ -23,7 +23,7 @@ const HEALTH_STATUS = Object.freeze({
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Default monitoring configuration
|
|
26
|
-
* @constant {
|
|
26
|
+
* @constant {any}
|
|
27
27
|
*/
|
|
28
28
|
const DEFAULT_CONFIG = Object.freeze({
|
|
29
29
|
/** Sample window size for latency calculations */
|
|
@@ -90,21 +90,21 @@ const DEFAULT_CONFIG = Object.freeze({
|
|
|
90
90
|
class NetworkMonitor extends EventEmitter {
|
|
91
91
|
/**
|
|
92
92
|
* Creates a new NetworkMonitor instance.
|
|
93
|
-
* @param {
|
|
93
|
+
* @param {any} [options={}] - Configuration options
|
|
94
94
|
*/
|
|
95
95
|
constructor(options = {}) {
|
|
96
96
|
super();
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
99
|
* Configuration
|
|
100
|
-
* @type {
|
|
100
|
+
* @type {any}
|
|
101
101
|
* @private
|
|
102
102
|
*/
|
|
103
103
|
this._config = { ...DEFAULT_CONFIG, ...options };
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
106
|
* Node health tracking
|
|
107
|
-
* @type {Map<string,
|
|
107
|
+
* @type {Map<string, any>}
|
|
108
108
|
* @private
|
|
109
109
|
*/
|
|
110
110
|
this._nodes = new Map();
|
|
@@ -146,7 +146,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
* Global statistics
|
|
149
|
-
* @type {
|
|
149
|
+
* @type {any}
|
|
150
150
|
* @private
|
|
151
151
|
*/
|
|
152
152
|
this._stats = {
|
|
@@ -158,7 +158,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
160
|
* Health check timer
|
|
161
|
-
* @type {
|
|
161
|
+
* @type {any}
|
|
162
162
|
* @private
|
|
163
163
|
*/
|
|
164
164
|
this._healthCheckTimer = null;
|
|
@@ -170,6 +170,13 @@ class NetworkMonitor extends EventEmitter {
|
|
|
170
170
|
*/
|
|
171
171
|
this._lastHealthReport = null;
|
|
172
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Previous health status for change detection
|
|
175
|
+
* @type {string|null}
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
this._previousHealth = null;
|
|
179
|
+
|
|
173
180
|
// Start health check timer
|
|
174
181
|
this._startHealthCheck();
|
|
175
182
|
}
|
|
@@ -351,7 +358,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
351
358
|
/**
|
|
352
359
|
* Gets detailed health for a specific node.
|
|
353
360
|
* @param {string} peerId - Peer ID
|
|
354
|
-
* @returns {
|
|
361
|
+
* @returns {any} Node health or null
|
|
355
362
|
*/
|
|
356
363
|
getNodeHealth(peerId) {
|
|
357
364
|
const node = this._nodes.get(peerId);
|
|
@@ -368,13 +375,13 @@ class NetworkMonitor extends EventEmitter {
|
|
|
368
375
|
|
|
369
376
|
/**
|
|
370
377
|
* Gets health information for all nodes.
|
|
371
|
-
* @returns {
|
|
378
|
+
* @returns {any[]} Array of node health
|
|
372
379
|
*/
|
|
373
380
|
getAllNodeHealth() {
|
|
374
381
|
const now = Date.now();
|
|
375
382
|
const timeout = this._config.nodeTimeoutMs;
|
|
376
383
|
|
|
377
|
-
return Array.from(this._nodes.values()).map(node => ({
|
|
384
|
+
return Array.from(this._nodes.values()).map((/** @type {any} */ node) => ({
|
|
378
385
|
...node,
|
|
379
386
|
isActive: (now - node.lastSeen) < timeout
|
|
380
387
|
}));
|
|
@@ -390,7 +397,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
390
397
|
|
|
391
398
|
/**
|
|
392
399
|
* Gets monitoring statistics.
|
|
393
|
-
* @returns {
|
|
400
|
+
* @returns {any} Statistics
|
|
394
401
|
*/
|
|
395
402
|
getStats() {
|
|
396
403
|
return {
|
|
@@ -433,7 +440,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
433
440
|
/**
|
|
434
441
|
* Gets or creates a node entry.
|
|
435
442
|
* @param {string} peerId - Peer ID
|
|
436
|
-
* @returns {
|
|
443
|
+
* @returns {any} Node entry
|
|
437
444
|
* @private
|
|
438
445
|
*/
|
|
439
446
|
_getOrCreateNode(peerId) {
|
|
@@ -474,7 +481,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
474
481
|
|
|
475
482
|
/**
|
|
476
483
|
* Updates node latency with exponential moving average.
|
|
477
|
-
* @param {
|
|
484
|
+
* @param {any} node - Node to update
|
|
478
485
|
* @param {number} latency - New latency sample
|
|
479
486
|
* @private
|
|
480
487
|
*/
|
|
@@ -489,7 +496,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
489
496
|
|
|
490
497
|
/**
|
|
491
498
|
* Updates node packet loss rate.
|
|
492
|
-
* @param {
|
|
499
|
+
* @param {any} node - Node to update
|
|
493
500
|
* @private
|
|
494
501
|
*/
|
|
495
502
|
_updateNodePacketLoss(node) {
|
|
@@ -567,7 +574,7 @@ class NetworkMonitor extends EventEmitter {
|
|
|
567
574
|
this._cleanupPendingMessages();
|
|
568
575
|
const report = this.generateHealthReport();
|
|
569
576
|
this.emit('health-report', report);
|
|
570
|
-
} catch (
|
|
577
|
+
} catch (_error) {
|
|
571
578
|
// Don't let health check errors crash the monitor
|
|
572
579
|
}
|
|
573
580
|
},
|
package/src/mesh/peer/Peer.js
CHANGED
|
@@ -18,12 +18,7 @@ const CONNECTION_STATE_SET = new Set(Object.values(CONNECTION_STATE));
|
|
|
18
18
|
class Peer {
|
|
19
19
|
/**
|
|
20
20
|
* Creates a new Peer
|
|
21
|
-
* @param {
|
|
22
|
-
* @param {string} options.id - Unique peer identifier
|
|
23
|
-
* @param {Uint8Array} [options.publicKey] - Peer's public key
|
|
24
|
-
* @param {string} [options.name] - Display name
|
|
25
|
-
* @param {number} [options.rssi] - Signal strength
|
|
26
|
-
* @param {number} [options.hopCount] - Distance in hops
|
|
21
|
+
* @param {any} options - Peer options *
|
|
27
22
|
*/
|
|
28
23
|
constructor(options) {
|
|
29
24
|
if (!options || typeof options.id !== 'string' || options.id.length === 0) {
|
|
@@ -88,7 +83,7 @@ class Peer {
|
|
|
88
83
|
|
|
89
84
|
/**
|
|
90
85
|
* Additional metadata
|
|
91
|
-
* @type {
|
|
86
|
+
* @type {any}
|
|
92
87
|
*/
|
|
93
88
|
this.metadata = options.metadata || {};
|
|
94
89
|
}
|
|
@@ -201,7 +196,7 @@ class Peer {
|
|
|
201
196
|
|
|
202
197
|
/**
|
|
203
198
|
* Converts peer to a JSON-serializable object
|
|
204
|
-
* @returns {
|
|
199
|
+
* @returns {any} JSON representation
|
|
205
200
|
*/
|
|
206
201
|
toJSON() {
|
|
207
202
|
return {
|
|
@@ -222,7 +217,7 @@ class Peer {
|
|
|
222
217
|
|
|
223
218
|
/**
|
|
224
219
|
* Creates a Peer from JSON data
|
|
225
|
-
* @param {
|
|
220
|
+
* @param {any} data - JSON data
|
|
226
221
|
* @returns {Peer} New Peer instance
|
|
227
222
|
*/
|
|
228
223
|
static fromJSON(data) {
|
|
@@ -16,7 +16,7 @@ const { ValidationError } = require('../../errors');
|
|
|
16
16
|
* @property {string} [name] - Display name
|
|
17
17
|
* @property {number[]} [publicKey] - Public key bytes
|
|
18
18
|
* @property {number} [hopCount] - Hop count
|
|
19
|
-
* @property {
|
|
19
|
+
* @property {any} [capabilities] - Peer capabilities
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -27,10 +27,7 @@ const { ValidationError } = require('../../errors');
|
|
|
27
27
|
class PeerDiscovery extends EventEmitter {
|
|
28
28
|
/**
|
|
29
29
|
* Creates a new PeerDiscovery handler
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {string} options.localPeerId - Local peer's ID
|
|
32
|
-
* @param {Uint8Array} [options.publicKey] - Local peer's public key
|
|
33
|
-
* @param {string} [options.displayName] - Local display name
|
|
30
|
+
* @param {any} options - Configuration options *
|
|
34
31
|
*/
|
|
35
32
|
constructor(options = {}) {
|
|
36
33
|
super();
|
|
@@ -59,13 +56,13 @@ class PeerDiscovery extends EventEmitter {
|
|
|
59
56
|
|
|
60
57
|
/**
|
|
61
58
|
* Capabilities advertised to peers
|
|
62
|
-
* @type {
|
|
59
|
+
* @type {any}
|
|
63
60
|
*/
|
|
64
61
|
this.capabilities = options.capabilities || {};
|
|
65
62
|
|
|
66
63
|
/**
|
|
67
64
|
* Discovery statistics
|
|
68
|
-
* @type {
|
|
65
|
+
* @type {any}
|
|
69
66
|
* @private
|
|
70
67
|
*/
|
|
71
68
|
this._stats = {
|
|
@@ -80,9 +77,10 @@ class PeerDiscovery extends EventEmitter {
|
|
|
80
77
|
|
|
81
78
|
/**
|
|
82
79
|
* Creates an announce message payload
|
|
83
|
-
* @returns {
|
|
80
|
+
* @returns {any} Announce payload
|
|
84
81
|
*/
|
|
85
82
|
createAnnouncePayload() {
|
|
83
|
+
/** @type {any} */
|
|
86
84
|
const payload = {
|
|
87
85
|
peerId: this.localPeerId,
|
|
88
86
|
name: this.displayName,
|
|
@@ -100,8 +98,9 @@ class PeerDiscovery extends EventEmitter {
|
|
|
100
98
|
/**
|
|
101
99
|
* Creates a peer request payload
|
|
102
100
|
* @param {string} [targetPeerId] - Specific peer to request (null for broadcast)
|
|
103
|
-
* @returns {
|
|
101
|
+
* @returns {any} Request payload
|
|
104
102
|
*/
|
|
103
|
+
// @ts-ignore
|
|
105
104
|
createRequestPayload(targetPeerId = null) {
|
|
106
105
|
return {
|
|
107
106
|
requesterId: this.localPeerId,
|
|
@@ -113,7 +112,7 @@ class PeerDiscovery extends EventEmitter {
|
|
|
113
112
|
/**
|
|
114
113
|
* Creates a peer response payload
|
|
115
114
|
* @param {string} requesterId - ID of requesting peer
|
|
116
|
-
* @returns {
|
|
115
|
+
* @returns {any} Response payload
|
|
117
116
|
*/
|
|
118
117
|
createResponsePayload(requesterId) {
|
|
119
118
|
return {
|
|
@@ -129,9 +128,9 @@ class PeerDiscovery extends EventEmitter {
|
|
|
129
128
|
/**
|
|
130
129
|
* Processes an incoming discovery message
|
|
131
130
|
* @param {number} type - Message type
|
|
132
|
-
* @param {
|
|
131
|
+
* @param {any} payload - Message payload
|
|
133
132
|
* @param {string} sourcePeerId - Source peer ID
|
|
134
|
-
* @returns {
|
|
133
|
+
* @returns {any} Response to send, or null
|
|
135
134
|
*/
|
|
136
135
|
processMessage(type, payload, sourcePeerId) {
|
|
137
136
|
// Ignore our own messages
|
|
@@ -158,7 +157,7 @@ class PeerDiscovery extends EventEmitter {
|
|
|
158
157
|
|
|
159
158
|
/**
|
|
160
159
|
* Handles a peer announce message
|
|
161
|
-
* @param {
|
|
160
|
+
* @param {any} payload - Announce payload
|
|
162
161
|
* @param {string} sourcePeerId - Source peer ID
|
|
163
162
|
* @returns {null} No response needed
|
|
164
163
|
* @private
|
|
@@ -181,9 +180,9 @@ class PeerDiscovery extends EventEmitter {
|
|
|
181
180
|
|
|
182
181
|
/**
|
|
183
182
|
* Handles a peer request message
|
|
184
|
-
* @param {
|
|
185
|
-
* @param {string}
|
|
186
|
-
* @returns {
|
|
183
|
+
* @param {any} payload - Request payload
|
|
184
|
+
* @param {string} _sourcePeerId - Source peer ID
|
|
185
|
+
* @returns {any} Response payload or null
|
|
187
186
|
* @private
|
|
188
187
|
*/
|
|
189
188
|
_handleRequest(payload, _sourcePeerId) {
|
|
@@ -203,7 +202,7 @@ class PeerDiscovery extends EventEmitter {
|
|
|
203
202
|
|
|
204
203
|
/**
|
|
205
204
|
* Handles a peer response message
|
|
206
|
-
* @param {
|
|
205
|
+
* @param {any} payload - Response payload
|
|
207
206
|
* @param {string} sourcePeerId - Source peer ID
|
|
208
207
|
* @returns {null} No response needed
|
|
209
208
|
* @private
|
|
@@ -230,7 +229,7 @@ class PeerDiscovery extends EventEmitter {
|
|
|
230
229
|
|
|
231
230
|
/**
|
|
232
231
|
* Updates local peer information
|
|
233
|
-
* @param {
|
|
232
|
+
* @param {any} info - New info
|
|
234
233
|
*/
|
|
235
234
|
updateLocalInfo(info) {
|
|
236
235
|
if (info.displayName !== undefined) { this.displayName = info.displayName; }
|
|
@@ -242,7 +241,7 @@ class PeerDiscovery extends EventEmitter {
|
|
|
242
241
|
|
|
243
242
|
/**
|
|
244
243
|
* Gets discovery statistics
|
|
245
|
-
* @returns {
|
|
244
|
+
* @returns {any} Statistics
|
|
246
245
|
*/
|
|
247
246
|
getStats() {
|
|
248
247
|
return { ...this._stats };
|
|
@@ -18,9 +18,9 @@ const { ValidationError, ConnectionError } = require('../../errors');
|
|
|
18
18
|
class PeerManager extends EventEmitter {
|
|
19
19
|
/**
|
|
20
20
|
* Creates a new PeerManager
|
|
21
|
-
* @param {
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* @param {any} [options] - Configuration options
|
|
22
|
+
*
|
|
23
|
+
*
|
|
24
24
|
*/
|
|
25
25
|
constructor(options = {}) {
|
|
26
26
|
super();
|
|
@@ -39,7 +39,7 @@ class PeerManager extends EventEmitter {
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Peers by ID
|
|
42
|
-
* @type {Map<string,
|
|
42
|
+
* @type {Map<string, any>}
|
|
43
43
|
* @private
|
|
44
44
|
*/
|
|
45
45
|
this._peers = new Map();
|
|
@@ -54,8 +54,8 @@ class PeerManager extends EventEmitter {
|
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Adds or updates a peer
|
|
57
|
-
* @param {
|
|
58
|
-
* @returns {
|
|
57
|
+
* @param {any} info - Peer information
|
|
58
|
+
* @returns {any} The added or updated peer
|
|
59
59
|
*/
|
|
60
60
|
addPeer(info) {
|
|
61
61
|
if (!info || typeof info.id !== 'string') {
|
|
@@ -90,7 +90,7 @@ class PeerManager extends EventEmitter {
|
|
|
90
90
|
/**
|
|
91
91
|
* Gets a peer by ID
|
|
92
92
|
* @param {string} id - Peer ID
|
|
93
|
-
* @returns {
|
|
93
|
+
* @returns {any} The peer or undefined
|
|
94
94
|
*/
|
|
95
95
|
getPeer(id) {
|
|
96
96
|
return this._peers.get(id);
|
|
@@ -98,7 +98,7 @@ class PeerManager extends EventEmitter {
|
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
100
|
* Gets all peers
|
|
101
|
-
* @returns {
|
|
101
|
+
* @returns {any[]} Array of all peers
|
|
102
102
|
*/
|
|
103
103
|
getAllPeers() {
|
|
104
104
|
return Array.from(this._peers.values());
|
|
@@ -106,7 +106,7 @@ class PeerManager extends EventEmitter {
|
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* Gets connected peers
|
|
109
|
-
* @returns {
|
|
109
|
+
* @returns {any[]} Array of connected peers
|
|
110
110
|
*/
|
|
111
111
|
getConnectedPeers() {
|
|
112
112
|
const result = [];
|
|
@@ -118,7 +118,7 @@ class PeerManager extends EventEmitter {
|
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* Gets peers with secure sessions
|
|
121
|
-
* @returns {
|
|
121
|
+
* @returns {any[]} Array of secured peers
|
|
122
122
|
*/
|
|
123
123
|
getSecuredPeers() {
|
|
124
124
|
const result = [];
|
|
@@ -130,7 +130,7 @@ class PeerManager extends EventEmitter {
|
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* Gets directly connected peers
|
|
133
|
-
* @returns {
|
|
133
|
+
* @returns {any[]} Array of direct peers
|
|
134
134
|
*/
|
|
135
135
|
getDirectPeers() {
|
|
136
136
|
const result = [];
|
|
@@ -144,7 +144,7 @@ class PeerManager extends EventEmitter {
|
|
|
144
144
|
* Updates a peer's connection state
|
|
145
145
|
* @param {string} id - Peer ID
|
|
146
146
|
* @param {string} state - New connection state
|
|
147
|
-
* @returns {
|
|
147
|
+
* @returns {any} Updated peer or undefined
|
|
148
148
|
*/
|
|
149
149
|
updateConnectionState(id, state) {
|
|
150
150
|
const peer = this._peers.get(id);
|
|
@@ -166,7 +166,7 @@ class PeerManager extends EventEmitter {
|
|
|
166
166
|
/**
|
|
167
167
|
* Marks a peer as secured
|
|
168
168
|
* @param {string} id - Peer ID
|
|
169
|
-
* @returns {
|
|
169
|
+
* @returns {any} Updated peer or undefined
|
|
170
170
|
*/
|
|
171
171
|
markSecured(id) {
|
|
172
172
|
const peer = this._peers.get(id);
|
|
@@ -237,7 +237,7 @@ class PeerManager extends EventEmitter {
|
|
|
237
237
|
/**
|
|
238
238
|
* Cleans up stale peers
|
|
239
239
|
* @param {number} [maxAge] - Maximum age in ms, defaults to peerTimeout
|
|
240
|
-
* @returns {
|
|
240
|
+
* @returns {any[]} Array of removed peers
|
|
241
241
|
*/
|
|
242
242
|
cleanup(maxAge = this.peerTimeout) {
|
|
243
243
|
const removed = [];
|