react-native-ble-mesh 1.1.1 → 2.0.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 +288 -172
- package/docs/IOS-BACKGROUND-BLE.md +231 -0
- package/docs/OPTIMIZATION.md +70 -0
- package/docs/SPEC-v2.1.md +308 -0
- package/package.json +1 -1
- package/src/MeshNetwork.js +659 -465
- package/src/constants/index.js +1 -0
- package/src/crypto/AutoCrypto.js +79 -0
- package/src/crypto/CryptoProvider.js +99 -0
- package/src/crypto/index.js +15 -63
- package/src/crypto/providers/ExpoCryptoProvider.js +125 -0
- package/src/crypto/providers/QuickCryptoProvider.js +134 -0
- package/src/crypto/providers/TweetNaClProvider.js +124 -0
- package/src/crypto/providers/index.js +11 -0
- package/src/errors/MeshError.js +2 -1
- package/src/expo/withBLEMesh.js +102 -0
- package/src/hooks/useMesh.js +30 -9
- package/src/hooks/useMessages.js +2 -0
- package/src/index.js +23 -8
- package/src/mesh/dedup/DedupManager.js +36 -10
- package/src/mesh/fragment/Assembler.js +5 -0
- package/src/mesh/index.js +1 -1
- package/src/mesh/monitor/ConnectionQuality.js +408 -0
- package/src/mesh/monitor/NetworkMonitor.js +327 -316
- package/src/mesh/monitor/index.js +7 -3
- package/src/mesh/peer/PeerManager.js +6 -1
- package/src/mesh/router/MessageRouter.js +26 -15
- package/src/mesh/router/RouteTable.js +7 -1
- package/src/mesh/store/StoreAndForwardManager.js +295 -297
- package/src/mesh/store/index.js +1 -1
- package/src/service/BatteryOptimizer.js +282 -278
- package/src/service/EmergencyManager.js +224 -214
- package/src/service/HandshakeManager.js +167 -13
- package/src/service/MeshService.js +72 -6
- package/src/service/SessionManager.js +77 -2
- package/src/service/audio/AudioManager.js +8 -2
- package/src/service/file/FileAssembler.js +106 -0
- package/src/service/file/FileChunker.js +79 -0
- package/src/service/file/FileManager.js +307 -0
- package/src/service/file/FileMessage.js +122 -0
- package/src/service/file/index.js +15 -0
- package/src/service/text/broadcast/BroadcastManager.js +16 -0
- package/src/transport/BLETransport.js +131 -9
- package/src/transport/MockTransport.js +1 -1
- package/src/transport/MultiTransport.js +305 -0
- package/src/transport/WiFiDirectTransport.js +295 -0
- package/src/transport/adapters/NodeBLEAdapter.js +34 -0
- package/src/transport/adapters/RNBLEAdapter.js +56 -1
- package/src/transport/index.js +6 -0
- package/src/utils/compression.js +291 -291
- package/src/crypto/aead.js +0 -189
- package/src/crypto/chacha20.js +0 -181
- package/src/crypto/hkdf.js +0 -187
- package/src/crypto/hmac.js +0 -143
- package/src/crypto/keys/KeyManager.js +0 -271
- package/src/crypto/keys/KeyPair.js +0 -216
- package/src/crypto/keys/SecureStorage.js +0 -219
- package/src/crypto/keys/index.js +0 -32
- package/src/crypto/noise/handshake.js +0 -410
- package/src/crypto/noise/index.js +0 -27
- package/src/crypto/noise/session.js +0 -253
- package/src/crypto/noise/state.js +0 -268
- package/src/crypto/poly1305.js +0 -113
- package/src/crypto/sha256.js +0 -240
- package/src/crypto/x25519.js +0 -154
|
@@ -6,9 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const { NetworkMonitor, HEALTH_STATUS, DEFAULT_CONFIG } = require('./NetworkMonitor');
|
|
9
|
+
const { ConnectionQuality, PeerQualityTracker, QUALITY_LEVEL } = require('./ConnectionQuality');
|
|
9
10
|
|
|
10
11
|
module.exports = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
NetworkMonitor,
|
|
13
|
+
HEALTH_STATUS,
|
|
14
|
+
DEFAULT_CONFIG,
|
|
15
|
+
ConnectionQuality,
|
|
16
|
+
PeerQualityTracker,
|
|
17
|
+
QUALITY_LEVEL
|
|
14
18
|
};
|
|
@@ -230,7 +230,12 @@ class PeerManager extends EventEmitter {
|
|
|
230
230
|
cleanup(maxAge = this.peerTimeout) {
|
|
231
231
|
const removed = [];
|
|
232
232
|
for (const [id, peer] of this._peers) {
|
|
233
|
-
|
|
233
|
+
// Don't remove peers that are actively connecting or connected
|
|
234
|
+
if (peer.isConnected() || peer.connectionState === CONNECTION_STATE.CONNECTING) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (peer.isStale(maxAge)) {
|
|
234
239
|
this._peers.delete(id);
|
|
235
240
|
removed.push(peer);
|
|
236
241
|
this.emit(EVENTS.PEER_LOST, peer);
|
|
@@ -22,7 +22,8 @@ function generateUUID() {
|
|
|
22
22
|
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
23
23
|
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
24
24
|
const hex = Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
25
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}
|
|
25
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-` +
|
|
26
|
+
`${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/**
|
|
@@ -148,8 +149,8 @@ class MessageRouter extends EventEmitter {
|
|
|
148
149
|
return null;
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
// Check hop count
|
|
152
|
-
if (hopCount
|
|
152
|
+
// Check hop count (allow delivery at exactly maxHops, just don't relay further)
|
|
153
|
+
if (hopCount > (maxHops || MESH_CONFIG.MAX_HOPS)) {
|
|
153
154
|
this._stats.maxHopsDropped++;
|
|
154
155
|
this.emit(EVENTS.MESSAGE_DROPPED, { messageId, reason: 'max_hops' });
|
|
155
156
|
return null;
|
|
@@ -165,17 +166,18 @@ class MessageRouter extends EventEmitter {
|
|
|
165
166
|
this._routeTable.addRoute(sourcePeerId, sourcePeerId, 0);
|
|
166
167
|
|
|
167
168
|
// Check if message is for us
|
|
168
|
-
const isForUs = !message.recipientId ||
|
|
169
|
-
|
|
170
|
-
(message.flags & MESSAGE_FLAGS.IS_BROADCAST);
|
|
169
|
+
const isForUs = !message.recipientId || message.recipientId === this.localPeerId;
|
|
170
|
+
const isBroadcast = (message.flags & MESSAGE_FLAGS.IS_BROADCAST) !== 0;
|
|
171
171
|
|
|
172
|
-
if
|
|
172
|
+
// Deliver locally if for us or broadcast
|
|
173
|
+
if (isForUs || isBroadcast) {
|
|
173
174
|
this.emit(EVENTS.MESSAGE_RECEIVED, message);
|
|
174
175
|
}
|
|
175
176
|
|
|
176
|
-
// Relay if
|
|
177
|
-
const shouldRelay =
|
|
178
|
-
|
|
177
|
+
// Relay decision: only relay if TTL allows AND message isn't exclusively for us
|
|
178
|
+
const shouldRelay = isBroadcast
|
|
179
|
+
? (message.hopCount < (maxHops || MESH_CONFIG.MAX_HOPS)) // Broadcasts relay if hops remain
|
|
180
|
+
: (!isForUs); // Unicast only relays if not for us
|
|
179
181
|
|
|
180
182
|
if (shouldRelay) {
|
|
181
183
|
this._relayMessage(message, sourcePeerId);
|
|
@@ -237,8 +239,11 @@ class MessageRouter extends EventEmitter {
|
|
|
237
239
|
return [nextHop];
|
|
238
240
|
}
|
|
239
241
|
|
|
240
|
-
// No known route,
|
|
241
|
-
|
|
242
|
+
// No known route - use limited flooding (max 3 peers, prefer recently active)
|
|
243
|
+
const allPeers = Array.from(this._peers.keys()).filter(id => id !== excludePeerId);
|
|
244
|
+
// Limit flood scope to prevent network storms
|
|
245
|
+
const maxFloodPeers = Math.min(3, allPeers.length);
|
|
246
|
+
return allPeers.slice(0, maxFloodPeers);
|
|
242
247
|
}
|
|
243
248
|
|
|
244
249
|
/**
|
|
@@ -270,25 +275,31 @@ class MessageRouter extends EventEmitter {
|
|
|
270
275
|
expiresAt: now + MESH_CONFIG.MESSAGE_TTL_MS
|
|
271
276
|
};
|
|
272
277
|
|
|
273
|
-
this._dedupManager.markSeen(messageId);
|
|
274
|
-
this._stats.messagesSent++;
|
|
275
|
-
|
|
276
278
|
// Determine targets
|
|
277
279
|
const targets = recipientId
|
|
278
280
|
? [this._routeTable.getNextHop(recipientId) || recipientId]
|
|
279
281
|
: Array.from(this._peers.keys());
|
|
280
282
|
|
|
283
|
+
// Send to targets
|
|
284
|
+
let anySent = false;
|
|
281
285
|
for (const peerId of targets) {
|
|
282
286
|
const sendFn = this._peers.get(peerId);
|
|
283
287
|
if (sendFn) {
|
|
284
288
|
try {
|
|
285
289
|
sendFn(message);
|
|
290
|
+
anySent = true;
|
|
286
291
|
} catch (err) {
|
|
287
292
|
this.emit(EVENTS.ERROR, err);
|
|
288
293
|
}
|
|
289
294
|
}
|
|
290
295
|
}
|
|
291
296
|
|
|
297
|
+
// Only mark as seen AFTER successful send
|
|
298
|
+
if (anySent) {
|
|
299
|
+
this._dedupManager.markSeen(messageId);
|
|
300
|
+
this._stats.messagesSent++;
|
|
301
|
+
}
|
|
302
|
+
|
|
292
303
|
this.emit(EVENTS.MESSAGE_SENT, message);
|
|
293
304
|
return messageId;
|
|
294
305
|
}
|
|
@@ -99,7 +99,13 @@ class RouteTable {
|
|
|
99
99
|
|
|
100
100
|
// Enforce max routes limit
|
|
101
101
|
if (!existingRoute && this._routes.size >= this.maxRoutes) {
|
|
102
|
-
|
|
102
|
+
// First try to clean up expired routes before evicting valid ones
|
|
103
|
+
this.cleanup();
|
|
104
|
+
|
|
105
|
+
// If still at capacity after cleanup, evict oldest
|
|
106
|
+
if (this._routes.size >= this.maxRoutes) {
|
|
107
|
+
this._evictOldestRoute();
|
|
108
|
+
}
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
const route = {
|