react-native-ble-mesh 1.0.1
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/CHANGELOG.md +151 -0
- package/LICENSE +21 -0
- package/README.md +706 -0
- package/docs/API.md +462 -0
- package/docs/ARCHITECTURE.md +384 -0
- package/docs/CONTRIBUTING.md +244 -0
- package/docs/NODE_QUICKSTART.md +259 -0
- package/docs/PROTOCOL.md +195 -0
- package/docs/REACT_NATIVE.md +315 -0
- package/docs/SECURITY.md +152 -0
- package/docs/api/constants_audio.js.html +184 -0
- package/docs/api/constants_ble.js.html +165 -0
- package/docs/api/constants_crypto.js.html +107 -0
- package/docs/api/constants_errors.js.html +256 -0
- package/docs/api/constants_events.js.html +148 -0
- package/docs/api/constants_index.js.html +76 -0
- package/docs/api/constants_protocol.js.html +205 -0
- package/docs/api/crypto_aead.js.html +243 -0
- package/docs/api/crypto_chacha20.js.html +235 -0
- package/docs/api/crypto_hkdf.js.html +241 -0
- package/docs/api/crypto_hmac.js.html +197 -0
- package/docs/api/crypto_index.js.html +126 -0
- package/docs/api/crypto_keys_KeyManager.js.html +325 -0
- package/docs/api/crypto_keys_KeyPair.js.html +270 -0
- package/docs/api/crypto_keys_SecureStorage.js.html +273 -0
- package/docs/api/crypto_keys_index.js.html +86 -0
- package/docs/api/crypto_noise_handshake.js.html +464 -0
- package/docs/api/crypto_noise_index.js.html +81 -0
- package/docs/api/crypto_noise_session.js.html +307 -0
- package/docs/api/crypto_noise_state.js.html +322 -0
- package/docs/api/crypto_poly1305.js.html +167 -0
- package/docs/api/crypto_sha256.js.html +294 -0
- package/docs/api/crypto_x25519.js.html +208 -0
- package/docs/api/errors_AudioError.js.html +218 -0
- package/docs/api/errors_ConnectionError.js.html +163 -0
- package/docs/api/errors_CryptoError.js.html +157 -0
- package/docs/api/errors_HandshakeError.js.html +176 -0
- package/docs/api/errors_MeshError.js.html +154 -0
- package/docs/api/errors_MessageError.js.html +183 -0
- package/docs/api/errors_ValidationError.js.html +204 -0
- package/docs/api/errors_index.js.html +78 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.svg +1830 -0
- package/docs/api/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Light-webfont.svg +1831 -0
- package/docs/api/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
- package/docs/api/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.svg +1831 -0
- package/docs/api/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/api/hooks_AppStateManager.js.html +233 -0
- package/docs/api/hooks_index.js.html +87 -0
- package/docs/api/hooks_useMesh.js.html +213 -0
- package/docs/api/hooks_useMessages.js.html +263 -0
- package/docs/api/hooks_usePeers.js.html +165 -0
- package/docs/api/index.html +868 -0
- package/docs/api/index.js.html +236 -0
- package/docs/api/mesh_dedup_BloomFilter.js.html +261 -0
- package/docs/api/mesh_dedup_DedupManager.js.html +266 -0
- package/docs/api/mesh_dedup_MessageCache.js.html +273 -0
- package/docs/api/mesh_dedup_index.js.html +70 -0
- package/docs/api/mesh_fragment_Assembler.js.html +335 -0
- package/docs/api/mesh_fragment_Fragmenter.js.html +230 -0
- package/docs/api/mesh_fragment_index.js.html +75 -0
- package/docs/api/mesh_index.js.html +72 -0
- package/docs/api/mesh_peer_Peer.js.html +296 -0
- package/docs/api/mesh_peer_PeerDiscovery.js.html +334 -0
- package/docs/api/mesh_peer_PeerManager.js.html +320 -0
- package/docs/api/mesh_peer_index.js.html +70 -0
- package/docs/api/mesh_router_MessageRouter.js.html +411 -0
- package/docs/api/mesh_router_PathFinder.js.html +386 -0
- package/docs/api/mesh_router_RouteTable.js.html +346 -0
- package/docs/api/mesh_router_index.js.html +70 -0
- package/docs/api/module-audio_buffer.html +168 -0
- package/docs/api/module-audio_buffer_FrameBuffer-FrameBuffer.html +2971 -0
- package/docs/api/module-audio_buffer_FrameBuffer.html +178 -0
- package/docs/api/module-audio_buffer_JitterBuffer-JitterBuffer.html +2761 -0
- package/docs/api/module-audio_buffer_JitterBuffer.html +178 -0
- package/docs/api/module-audio_codec.html +168 -0
- package/docs/api/module-audio_codec_LC3Codec-LC3Codec.html +2876 -0
- package/docs/api/module-audio_codec_LC3Codec.html +178 -0
- package/docs/api/module-audio_codec_LC3Decoder-LC3Decoder.html +1788 -0
- package/docs/api/module-audio_codec_LC3Decoder.html +178 -0
- package/docs/api/module-audio_codec_LC3Encoder-LC3Encoder.html +1512 -0
- package/docs/api/module-audio_codec_LC3Encoder.html +178 -0
- package/docs/api/module-audio_session.html +168 -0
- package/docs/api/module-audio_session_AudioSession-AudioSession.html +3922 -0
- package/docs/api/module-audio_session_AudioSession.html +178 -0
- package/docs/api/module-audio_session_VoiceMessage-VoiceMessage.html +3690 -0
- package/docs/api/module-audio_session_VoiceMessage-VoiceMessageRecorder.html +1780 -0
- package/docs/api/module-audio_session_VoiceMessage.html +332 -0
- package/docs/api/module-audio_transport.html +168 -0
- package/docs/api/module-audio_transport_AudioFragmenter-AudioAssembler.html +1545 -0
- package/docs/api/module-audio_transport_AudioFragmenter-AudioFragmenter.html +658 -0
- package/docs/api/module-audio_transport_AudioFragmenter.html +181 -0
- package/docs/api/module-audio_transport_AudioFramer.html +1414 -0
- package/docs/api/module-constants.html +168 -0
- package/docs/api/module-constants_audio.html +1782 -0
- package/docs/api/module-constants_ble.html +940 -0
- package/docs/api/module-constants_crypto.html +823 -0
- package/docs/api/module-constants_errors.html +316 -0
- package/docs/api/module-constants_events.html +244 -0
- package/docs/api/module-constants_protocol.html +1534 -0
- package/docs/api/module-crypto.html +169 -0
- package/docs/api/module-crypto_aead.html +1625 -0
- package/docs/api/module-crypto_chacha20.html +1440 -0
- package/docs/api/module-crypto_hkdf.html +1421 -0
- package/docs/api/module-crypto_hmac.html +828 -0
- package/docs/api/module-crypto_keys.html +169 -0
- package/docs/api/module-crypto_keys_KeyManager-KeyManager.html +2364 -0
- package/docs/api/module-crypto_keys_KeyManager.html +252 -0
- package/docs/api/module-crypto_keys_KeyPair.html +245 -0
- package/docs/api/module-crypto_keys_SecureStorage-MemorySecureStorage.html +923 -0
- package/docs/api/module-crypto_keys_SecureStorage-SecureStorage.html +942 -0
- package/docs/api/module-crypto_keys_SecureStorage.html +516 -0
- package/docs/api/module-crypto_noise.html +169 -0
- package/docs/api/module-crypto_noise_handshake-NoiseHandshake.html +2240 -0
- package/docs/api/module-crypto_noise_handshake.html +782 -0
- package/docs/api/module-crypto_noise_session-NoiseSession.html +1804 -0
- package/docs/api/module-crypto_noise_session.html +325 -0
- package/docs/api/module-crypto_noise_state-SymmetricState.html +1387 -0
- package/docs/api/module-crypto_noise_state.html +324 -0
- package/docs/api/module-crypto_poly1305.html +884 -0
- package/docs/api/module-crypto_sha256-HashContext.html +447 -0
- package/docs/api/module-crypto_sha256.html +942 -0
- package/docs/api/module-crypto_x25519.html +1503 -0
- package/docs/api/module-errors.html +168 -0
- package/docs/api/module-errors_AudioError-AudioError.html +4711 -0
- package/docs/api/module-errors_AudioError.html +178 -0
- package/docs/api/module-errors_ConnectionError-ConnectionError.html +3649 -0
- package/docs/api/module-errors_ConnectionError.html +178 -0
- package/docs/api/module-errors_CryptoError-CryptoError.html +3453 -0
- package/docs/api/module-errors_CryptoError.html +178 -0
- package/docs/api/module-errors_HandshakeError-HandshakeError.html +4261 -0
- package/docs/api/module-errors_HandshakeError.html +178 -0
- package/docs/api/module-errors_MeshError-MeshError.html +2155 -0
- package/docs/api/module-errors_MeshError.html +178 -0
- package/docs/api/module-errors_MessageError-MessageError.html +4545 -0
- package/docs/api/module-errors_MessageError.html +178 -0
- package/docs/api/module-errors_ValidationError-ValidationError.html +3432 -0
- package/docs/api/module-errors_ValidationError.html +178 -0
- package/docs/api/module-hooks.html +182 -0
- package/docs/api/module-hooks_AppStateManager-AppStateManager.html +1620 -0
- package/docs/api/module-hooks_AppStateManager.html +178 -0
- package/docs/api/module-hooks_useMesh.html +457 -0
- package/docs/api/module-hooks_useMessages.html +466 -0
- package/docs/api/module-hooks_usePeers.html +348 -0
- package/docs/api/module-mesh.html +168 -0
- package/docs/api/module-mesh_dedup.html +168 -0
- package/docs/api/module-mesh_dedup_BloomFilter-BloomFilter.html +2158 -0
- package/docs/api/module-mesh_dedup_BloomFilter.html +178 -0
- package/docs/api/module-mesh_dedup_DedupManager-DedupManager.html +2880 -0
- package/docs/api/module-mesh_dedup_DedupManager.html +178 -0
- package/docs/api/module-mesh_dedup_MessageCache-CacheNode.html +246 -0
- package/docs/api/module-mesh_dedup_MessageCache-MessageCache.html +2314 -0
- package/docs/api/module-mesh_dedup_MessageCache.html +181 -0
- package/docs/api/module-mesh_fragment.html +168 -0
- package/docs/api/module-mesh_fragment_Assembler-Assembler.html +2869 -0
- package/docs/api/module-mesh_fragment_Assembler-PendingFragmentSet.html +895 -0
- package/docs/api/module-mesh_fragment_Assembler.html +181 -0
- package/docs/api/module-mesh_fragment_Fragmenter.html +1084 -0
- package/docs/api/module-mesh_peer.html +168 -0
- package/docs/api/module-mesh_peer_Peer-Peer.html +4986 -0
- package/docs/api/module-mesh_peer_Peer.html +178 -0
- package/docs/api/module-mesh_peer_PeerDiscovery-PeerDiscovery.html +3423 -0
- package/docs/api/module-mesh_peer_PeerDiscovery.html +438 -0
- package/docs/api/module-mesh_peer_PeerManager-PeerManager.html +5258 -0
- package/docs/api/module-mesh_peer_PeerManager.html +178 -0
- package/docs/api/module-mesh_router.html +168 -0
- package/docs/api/module-mesh_router_MessageRouter-MessageRouter.html +3285 -0
- package/docs/api/module-mesh_router_MessageRouter.html +178 -0
- package/docs/api/module-mesh_router_PathFinder-PathFinder.html +3323 -0
- package/docs/api/module-mesh_router_PathFinder.html +421 -0
- package/docs/api/module-mesh_router_RouteTable-RouteTable.html +4115 -0
- package/docs/api/module-mesh_router_RouteTable.html +421 -0
- package/docs/api/module-protocol.html +169 -0
- package/docs/api/module-protocol_crc32.html +815 -0
- package/docs/api/module-protocol_deserializer.html +1393 -0
- package/docs/api/module-protocol_header-MessageHeader.html +2879 -0
- package/docs/api/module-protocol_header.html +892 -0
- package/docs/api/module-protocol_message-Message.html +4682 -0
- package/docs/api/module-protocol_message.html +178 -0
- package/docs/api/module-protocol_serializer.html +911 -0
- package/docs/api/module-protocol_validator.html +1396 -0
- package/docs/api/module-rn-ble-mesh.html +866 -0
- package/docs/api/module-service.html +168 -0
- package/docs/api/module-service_HandshakeManager-HandshakeManager.html +185 -0
- package/docs/api/module-service_HandshakeManager.html +175 -0
- package/docs/api/module-service_MeshService-MeshService.html +185 -0
- package/docs/api/module-service_MeshService.html +175 -0
- package/docs/api/module-service_SessionManager-SessionManager.html +174 -0
- package/docs/api/module-service_SessionManager.html +175 -0
- package/docs/api/module-service_audio.html +168 -0
- package/docs/api/module-service_audio_AudioManager-AudioManager.html +4653 -0
- package/docs/api/module-service_audio_AudioManager.html +254 -0
- package/docs/api/module-service_text.html +168 -0
- package/docs/api/module-service_text_TextManager-TextManager.html +6104 -0
- package/docs/api/module-service_text_TextManager.html +254 -0
- package/docs/api/module-service_text_broadcast.html +168 -0
- package/docs/api/module-service_text_broadcast_BroadcastManager-BroadcastManager.html +2434 -0
- package/docs/api/module-service_text_broadcast_BroadcastManager.html +254 -0
- package/docs/api/module-service_text_channel.html +168 -0
- package/docs/api/module-service_text_channel_Channel-Channel.html +4337 -0
- package/docs/api/module-service_text_channel_Channel.html +178 -0
- package/docs/api/module-service_text_channel_ChannelManager-ChannelManager.html +1927 -0
- package/docs/api/module-service_text_channel_ChannelManager.html +175 -0
- package/docs/api/module-service_text_message.html +168 -0
- package/docs/api/module-service_text_message_TextMessage-TextMessage.html +4162 -0
- package/docs/api/module-service_text_message_TextMessage.html +178 -0
- package/docs/api/module-service_text_message_TextSerializer.html +1725 -0
- package/docs/api/module-storage.html +168 -0
- package/docs/api/module-storage_AsyncStorageAdapter-AsyncStorageAdapter.html +4159 -0
- package/docs/api/module-storage_AsyncStorageAdapter.html +178 -0
- package/docs/api/module-storage_MemoryStorage-MemoryStorage.html +3154 -0
- package/docs/api/module-storage_MemoryStorage.html +178 -0
- package/docs/api/module-storage_MessageStore-MessageStore.html +5299 -0
- package/docs/api/module-storage_MessageStore.html +178 -0
- package/docs/api/module-storage_Storage-Storage.html +4169 -0
- package/docs/api/module-storage_Storage.html +178 -0
- package/docs/api/module-transport.html +168 -0
- package/docs/api/module-transport_BLEAdapter-BLEAdapter.html +4724 -0
- package/docs/api/module-transport_BLEAdapter.html +178 -0
- package/docs/api/module-transport_BLETransport-BLETransport.html +3263 -0
- package/docs/api/module-transport_BLETransport.html +178 -0
- package/docs/api/module-transport_MockTransport-MockTransport.html +3947 -0
- package/docs/api/module-transport_MockTransport.html +178 -0
- package/docs/api/module-transport_NodeBLEAdapter-NodeBLEAdapter.html +3216 -0
- package/docs/api/module-transport_NodeBLEAdapter.html +178 -0
- package/docs/api/module-transport_RNBLEAdapter-RNBLEAdapter.html +3216 -0
- package/docs/api/module-transport_RNBLEAdapter.html +178 -0
- package/docs/api/module-transport_Transport-Transport.html +4071 -0
- package/docs/api/module-transport_Transport.html +254 -0
- package/docs/api/module-transport_adapters.html +168 -0
- package/docs/api/module-transport_adapters_BLEAdapter-BLEAdapter.html +4724 -0
- package/docs/api/module-transport_adapters_BLEAdapter.html +178 -0
- package/docs/api/module-transport_adapters_NodeBLEAdapter-NodeBLEAdapter.html +3216 -0
- package/docs/api/module-transport_adapters_NodeBLEAdapter.html +178 -0
- package/docs/api/module-transport_adapters_RNBLEAdapter-RNBLEAdapter.html +3216 -0
- package/docs/api/module-transport_adapters_RNBLEAdapter.html +178 -0
- package/docs/api/module-utils.html +168 -0
- package/docs/api/module-utils_BoundedMap-BoundedMap.html +3301 -0
- package/docs/api/module-utils_BoundedMap.html +178 -0
- package/docs/api/module-utils_EventEmitter-EventEmitter.html +3358 -0
- package/docs/api/module-utils_EventEmitter.html +178 -0
- package/docs/api/module-utils_LRUCache-LRUCache.html +4134 -0
- package/docs/api/module-utils_LRUCache.html +178 -0
- package/docs/api/module-utils_RateLimiter-RateLimiter.html +2176 -0
- package/docs/api/module-utils_RateLimiter.html +500 -0
- package/docs/api/module-utils_TimeoutManager-TimeoutManager.html +1781 -0
- package/docs/api/module-utils_TimeoutManager.html +175 -0
- package/docs/api/module-utils_bytes.html +1789 -0
- package/docs/api/module-utils_debug.html +837 -0
- package/docs/api/module-utils_encoding.html +1184 -0
- package/docs/api/module-utils_retry.html +1457 -0
- package/docs/api/module-utils_time.html +1665 -0
- package/docs/api/module-utils_uuid.html +1269 -0
- package/docs/api/module-utils_validation.html +2176 -0
- package/docs/api/protocol_crc32.js.html +147 -0
- package/docs/api/protocol_deserializer.js.html +295 -0
- package/docs/api/protocol_header.js.html +276 -0
- package/docs/api/protocol_index.js.html +120 -0
- package/docs/api/protocol_message.js.html +287 -0
- package/docs/api/protocol_serializer.js.html +240 -0
- package/docs/api/protocol_validator.js.html +330 -0
- package/docs/api/scripts/linenumber.js +25 -0
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/prettify/lang-css.js +2 -0
- package/docs/api/scripts/prettify/prettify.js +28 -0
- package/docs/api/service_HandshakeManager.js.html +232 -0
- package/docs/api/service_MeshService.js.html +371 -0
- package/docs/api/service_SessionManager.js.html +153 -0
- package/docs/api/service_audio_AudioManager.js.html +541 -0
- package/docs/api/service_audio_buffer_FrameBuffer.js.html +223 -0
- package/docs/api/service_audio_buffer_JitterBuffer.js.html +244 -0
- package/docs/api/service_audio_buffer_index.js.html +68 -0
- package/docs/api/service_audio_codec_LC3Codec.js.html +345 -0
- package/docs/api/service_audio_codec_LC3Decoder.js.html +185 -0
- package/docs/api/service_audio_codec_LC3Encoder.js.html +194 -0
- package/docs/api/service_audio_codec_index.js.html +70 -0
- package/docs/api/service_audio_index.js.html +96 -0
- package/docs/api/service_audio_session_AudioSession.js.html +348 -0
- package/docs/api/service_audio_session_VoiceMessage.js.html +432 -0
- package/docs/api/service_audio_session_index.js.html +70 -0
- package/docs/api/service_audio_transport_AudioFragmenter.js.html +314 -0
- package/docs/api/service_audio_transport_AudioFramer.js.html +236 -0
- package/docs/api/service_audio_transport_index.js.html +69 -0
- package/docs/api/service_index.js.html +93 -0
- package/docs/api/service_text_TextManager.js.html +578 -0
- package/docs/api/service_text_broadcast_BroadcastManager.js.html +276 -0
- package/docs/api/service_text_broadcast_index.js.html +66 -0
- package/docs/api/service_text_channel_Channel.js.html +280 -0
- package/docs/api/service_text_channel_ChannelManager.js.html +225 -0
- package/docs/api/service_text_channel_index.js.html +68 -0
- package/docs/api/service_text_index.js.html +85 -0
- package/docs/api/service_text_message_TextMessage.js.html +350 -0
- package/docs/api/service_text_message_TextSerializer.js.html +218 -0
- package/docs/api/service_text_message_index.js.html +68 -0
- package/docs/api/storage_AsyncStorageAdapter.js.html +357 -0
- package/docs/api/storage_MemoryStorage.js.html +279 -0
- package/docs/api/storage_MessageStore.js.html +369 -0
- package/docs/api/storage_Storage.js.html +214 -0
- package/docs/api/storage_index.js.html +72 -0
- package/docs/api/styles/jsdoc-default.css +358 -0
- package/docs/api/styles/prettify-jsdoc.css +111 -0
- package/docs/api/styles/prettify-tomorrow.css +132 -0
- package/docs/api/transport_BLEAdapter.js.html +231 -0
- package/docs/api/transport_BLETransport.js.html +411 -0
- package/docs/api/transport_MockTransport.js.html +339 -0
- package/docs/api/transport_NodeBLEAdapter.js.html +479 -0
- package/docs/api/transport_RNBLEAdapter.js.html +382 -0
- package/docs/api/transport_Transport.js.html +242 -0
- package/docs/api/transport_adapters_BLEAdapter.js.html +231 -0
- package/docs/api/transport_adapters_NodeBLEAdapter.js.html +479 -0
- package/docs/api/transport_adapters_RNBLEAdapter.js.html +382 -0
- package/docs/api/transport_adapters_index.js.html +70 -0
- package/docs/api/transport_index.js.html +87 -0
- package/docs/api/utils_BoundedMap.js.html +205 -0
- package/docs/api/utils_EventEmitter.js.html +259 -0
- package/docs/api/utils_LRUCache.js.html +256 -0
- package/docs/api/utils_RateLimiter.js.html +256 -0
- package/docs/api/utils_TimeoutManager.js.html +218 -0
- package/docs/api/utils_base64%0A%0AThis%20implementation%20avoids%20string%20concatenation%20in%20loops%20which%20is%20O(n%C2%B2).%0AUses%20array%20building%20which%20is%20O(n)%20-%20critical%20for%20React%20Native%20performance.module_.html +717 -0
- package/docs/api/utils_base64.js.html +205 -0
- package/docs/api/utils_bytes.js.html +241 -0
- package/docs/api/utils_debug.js.html +205 -0
- package/docs/api/utils_encoding.js.html +302 -0
- package/docs/api/utils_index.js.html +160 -0
- package/docs/api/utils_retry.js.html +200 -0
- package/docs/api/utils_time.js.html +220 -0
- package/docs/api/utils_uuid.js.html +199 -0
- package/docs/api/utils_validation.js.html +259 -0
- package/examples/node-chat/chat.js +220 -0
- package/examples/node-quickstart/index.js +94 -0
- package/examples/testing/test-helper.js +182 -0
- package/package.json +111 -0
- package/src/constants/audio.js +130 -0
- package/src/constants/ble.js +111 -0
- package/src/constants/crypto.js +53 -0
- package/src/constants/errors.js +202 -0
- package/src/constants/events.js +94 -0
- package/src/constants/index.js +22 -0
- package/src/constants/protocol.js +151 -0
- package/src/crypto/aead.js +189 -0
- package/src/crypto/chacha20.js +181 -0
- package/src/crypto/hkdf.js +187 -0
- package/src/crypto/hmac.js +143 -0
- package/src/crypto/index.js +72 -0
- package/src/crypto/keys/KeyManager.js +271 -0
- package/src/crypto/keys/KeyPair.js +216 -0
- package/src/crypto/keys/SecureStorage.js +219 -0
- package/src/crypto/keys/index.js +32 -0
- package/src/crypto/noise/handshake.js +410 -0
- package/src/crypto/noise/index.js +27 -0
- package/src/crypto/noise/session.js +253 -0
- package/src/crypto/noise/state.js +268 -0
- package/src/crypto/poly1305.js +113 -0
- package/src/crypto/sha256.js +240 -0
- package/src/crypto/x25519.js +154 -0
- package/src/errors/AudioError.js +164 -0
- package/src/errors/ConnectionError.js +109 -0
- package/src/errors/CryptoError.js +103 -0
- package/src/errors/HandshakeError.js +122 -0
- package/src/errors/MeshError.js +100 -0
- package/src/errors/MessageError.js +129 -0
- package/src/errors/ValidationError.js +150 -0
- package/src/errors/index.js +24 -0
- package/src/hooks/AppStateManager.js +179 -0
- package/src/hooks/index.js +33 -0
- package/src/hooks/useMesh.js +159 -0
- package/src/hooks/useMessages.js +209 -0
- package/src/hooks/usePeers.js +111 -0
- package/src/index.d.ts +494 -0
- package/src/index.js +182 -0
- package/src/index.mjs +62 -0
- package/src/mesh/dedup/BloomFilter.js +207 -0
- package/src/mesh/dedup/DedupManager.js +212 -0
- package/src/mesh/dedup/MessageCache.js +219 -0
- package/src/mesh/dedup/index.js +16 -0
- package/src/mesh/fragment/Assembler.js +281 -0
- package/src/mesh/fragment/Fragmenter.js +176 -0
- package/src/mesh/fragment/index.js +21 -0
- package/src/mesh/index.js +18 -0
- package/src/mesh/peer/Peer.js +242 -0
- package/src/mesh/peer/PeerDiscovery.js +280 -0
- package/src/mesh/peer/PeerManager.js +266 -0
- package/src/mesh/peer/index.js +16 -0
- package/src/mesh/router/MessageRouter.js +357 -0
- package/src/mesh/router/PathFinder.js +332 -0
- package/src/mesh/router/RouteTable.js +292 -0
- package/src/mesh/router/index.js +16 -0
- package/src/protocol/crc32.js +93 -0
- package/src/protocol/deserializer.js +241 -0
- package/src/protocol/header.js +222 -0
- package/src/protocol/index.js +66 -0
- package/src/protocol/message.js +233 -0
- package/src/protocol/serializer.js +186 -0
- package/src/protocol/validator.js +276 -0
- package/src/service/HandshakeManager.js +178 -0
- package/src/service/MeshService.js +317 -0
- package/src/service/SessionManager.js +99 -0
- package/src/service/audio/AudioManager.js +487 -0
- package/src/service/audio/buffer/FrameBuffer.js +169 -0
- package/src/service/audio/buffer/JitterBuffer.js +190 -0
- package/src/service/audio/buffer/index.js +14 -0
- package/src/service/audio/codec/LC3Codec.js +291 -0
- package/src/service/audio/codec/LC3Decoder.js +131 -0
- package/src/service/audio/codec/LC3Encoder.js +140 -0
- package/src/service/audio/codec/index.js +16 -0
- package/src/service/audio/index.js +42 -0
- package/src/service/audio/session/AudioSession.js +294 -0
- package/src/service/audio/session/VoiceMessage.js +378 -0
- package/src/service/audio/session/index.js +16 -0
- package/src/service/audio/transport/AudioFragmenter.js +260 -0
- package/src/service/audio/transport/AudioFramer.js +182 -0
- package/src/service/audio/transport/index.js +15 -0
- package/src/service/index.js +39 -0
- package/src/service/text/TextManager.js +524 -0
- package/src/service/text/broadcast/BroadcastManager.js +222 -0
- package/src/service/text/broadcast/index.js +12 -0
- package/src/service/text/channel/Channel.js +226 -0
- package/src/service/text/channel/ChannelManager.js +171 -0
- package/src/service/text/channel/index.js +14 -0
- package/src/service/text/index.js +31 -0
- package/src/service/text/message/TextMessage.js +296 -0
- package/src/service/text/message/TextSerializer.js +164 -0
- package/src/service/text/message/index.js +14 -0
- package/src/storage/AsyncStorageAdapter.js +303 -0
- package/src/storage/MemoryStorage.js +225 -0
- package/src/storage/MessageStore.js +315 -0
- package/src/storage/Storage.js +160 -0
- package/src/storage/index.js +18 -0
- package/src/transport/BLEAdapter.js +177 -0
- package/src/transport/BLETransport.js +357 -0
- package/src/transport/MockTransport.js +285 -0
- package/src/transport/NodeBLEAdapter.js +425 -0
- package/src/transport/RNBLEAdapter.js +328 -0
- package/src/transport/Transport.js +188 -0
- package/src/transport/adapters/BLEAdapter.js +177 -0
- package/src/transport/adapters/NodeBLEAdapter.js +425 -0
- package/src/transport/adapters/RNBLEAdapter.js +328 -0
- package/src/transport/adapters/index.js +16 -0
- package/src/transport/index.js +33 -0
- package/src/utils/BoundedMap.js +151 -0
- package/src/utils/EventEmitter.js +205 -0
- package/src/utils/LRUCache.js +202 -0
- package/src/utils/RateLimiter.js +202 -0
- package/src/utils/TimeoutManager.js +164 -0
- package/src/utils/base64.js +151 -0
- package/src/utils/bytes.js +187 -0
- package/src/utils/debug.js +151 -0
- package/src/utils/encoding.js +248 -0
- package/src/utils/index.js +106 -0
- package/src/utils/retry.js +146 -0
- package/src/utils/time.js +166 -0
- package/src/utils/uuid.js +145 -0
- package/src/utils/validation.js +205 -0
package/src/index.mjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview BLE Mesh Network Library - ESM Entry Point
|
|
3
|
+
* @module rn-ble-mesh
|
|
4
|
+
* @description Production-ready BLE Mesh Network with Noise Protocol security
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Import CJS module and re-export as ESM
|
|
8
|
+
import cjs from './index.js';
|
|
9
|
+
|
|
10
|
+
// Named exports
|
|
11
|
+
export const {
|
|
12
|
+
// Factory functions
|
|
13
|
+
createMeshService,
|
|
14
|
+
createNodeMesh,
|
|
15
|
+
createTestMesh,
|
|
16
|
+
|
|
17
|
+
// Main service class
|
|
18
|
+
MeshService,
|
|
19
|
+
|
|
20
|
+
// Transport classes
|
|
21
|
+
BLETransport,
|
|
22
|
+
MockTransport,
|
|
23
|
+
Transport,
|
|
24
|
+
|
|
25
|
+
// Storage classes
|
|
26
|
+
MemoryStorage,
|
|
27
|
+
AsyncStorageAdapter,
|
|
28
|
+
Storage,
|
|
29
|
+
MessageStore,
|
|
30
|
+
|
|
31
|
+
// Constants
|
|
32
|
+
PROTOCOL_VERSION,
|
|
33
|
+
MESSAGE_TYPE,
|
|
34
|
+
MESSAGE_FLAGS,
|
|
35
|
+
CONNECTION_STATE,
|
|
36
|
+
SERVICE_STATE,
|
|
37
|
+
POWER_MODE,
|
|
38
|
+
BLE_SERVICE_UUID,
|
|
39
|
+
BLE_CHARACTERISTIC_TX,
|
|
40
|
+
BLE_CHARACTERISTIC_RX,
|
|
41
|
+
MESH_CONFIG,
|
|
42
|
+
CRYPTO_CONFIG,
|
|
43
|
+
|
|
44
|
+
// Error classes
|
|
45
|
+
MeshError,
|
|
46
|
+
CryptoError,
|
|
47
|
+
ConnectionError,
|
|
48
|
+
HandshakeError,
|
|
49
|
+
MessageError,
|
|
50
|
+
ValidationError,
|
|
51
|
+
|
|
52
|
+
// Module namespaces
|
|
53
|
+
crypto,
|
|
54
|
+
protocol,
|
|
55
|
+
mesh,
|
|
56
|
+
transport,
|
|
57
|
+
storage,
|
|
58
|
+
utils
|
|
59
|
+
} = cjs;
|
|
60
|
+
|
|
61
|
+
// Default export for convenience
|
|
62
|
+
export default cjs;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Bloom filter for efficient duplicate detection
|
|
5
|
+
* @module mesh/dedup/BloomFilter
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* FNV-1a hash parameters
|
|
10
|
+
* @constant
|
|
11
|
+
* @private
|
|
12
|
+
*/
|
|
13
|
+
const FNV_PRIME = 0x01000193;
|
|
14
|
+
const FNV_OFFSET = 0x811c9dc5;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Bloom filter for probabilistic set membership testing
|
|
18
|
+
* @class BloomFilter
|
|
19
|
+
*/
|
|
20
|
+
class BloomFilter {
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new BloomFilter
|
|
23
|
+
* @param {number} [size=2048] - Size of the bit array in bits
|
|
24
|
+
* @param {number} [hashCount=7] - Number of hash functions to use
|
|
25
|
+
*/
|
|
26
|
+
constructor(size = 2048, hashCount = 7) {
|
|
27
|
+
if (!Number.isInteger(size) || size <= 0) {
|
|
28
|
+
throw new Error('Size must be a positive integer');
|
|
29
|
+
}
|
|
30
|
+
if (!Number.isInteger(hashCount) || hashCount <= 0) {
|
|
31
|
+
throw new Error('Hash count must be a positive integer');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Size of the bit array in bits
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
38
|
+
this.size = size;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Number of hash functions
|
|
42
|
+
* @type {number}
|
|
43
|
+
*/
|
|
44
|
+
this.hashCount = hashCount;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Bit array storage (using Uint8Array for efficiency)
|
|
48
|
+
* @type {Uint8Array}
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
this._bits = new Uint8Array(Math.ceil(size / 8));
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Number of items added
|
|
55
|
+
* @type {number}
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
this._count = 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Computes FNV-1a hash of input data
|
|
63
|
+
* @param {Uint8Array} data - Data to hash
|
|
64
|
+
* @param {number} seed - Seed for variation
|
|
65
|
+
* @returns {number} Hash value
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
_fnv1a(data, seed) {
|
|
69
|
+
let hash = FNV_OFFSET ^ seed;
|
|
70
|
+
// Handle empty data by mixing in the seed and length
|
|
71
|
+
if (data.length === 0) {
|
|
72
|
+
hash ^= seed;
|
|
73
|
+
hash = Math.imul(hash, FNV_PRIME) >>> 0;
|
|
74
|
+
}
|
|
75
|
+
for (let i = 0; i < data.length; i++) {
|
|
76
|
+
hash ^= data[i];
|
|
77
|
+
hash = Math.imul(hash, FNV_PRIME) >>> 0;
|
|
78
|
+
}
|
|
79
|
+
return hash;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Converts input to Uint8Array
|
|
84
|
+
* @param {string|Uint8Array} item - Item to convert
|
|
85
|
+
* @returns {Uint8Array} Byte array
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
_toBytes(item) {
|
|
89
|
+
if (item instanceof Uint8Array) {
|
|
90
|
+
return item;
|
|
91
|
+
}
|
|
92
|
+
if (typeof item === 'string') {
|
|
93
|
+
const encoder = new TextEncoder();
|
|
94
|
+
return encoder.encode(item);
|
|
95
|
+
}
|
|
96
|
+
throw new Error('Item must be string or Uint8Array');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Computes hash positions for an item
|
|
101
|
+
* @param {string|Uint8Array} item - Item to hash
|
|
102
|
+
* @returns {number[]} Array of bit positions
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
_getPositions(item) {
|
|
106
|
+
const data = this._toBytes(item);
|
|
107
|
+
const positions = [];
|
|
108
|
+
for (let i = 0; i < this.hashCount; i++) {
|
|
109
|
+
const hash = this._fnv1a(data, i);
|
|
110
|
+
positions.push(hash % this.size);
|
|
111
|
+
}
|
|
112
|
+
return positions;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Sets a bit at the given position
|
|
117
|
+
* @param {number} position - Bit position
|
|
118
|
+
* @private
|
|
119
|
+
*/
|
|
120
|
+
_setBit(position) {
|
|
121
|
+
const byteIndex = Math.floor(position / 8);
|
|
122
|
+
const bitIndex = position % 8;
|
|
123
|
+
this._bits[byteIndex] |= (1 << bitIndex);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Gets a bit at the given position
|
|
128
|
+
* @param {number} position - Bit position
|
|
129
|
+
* @returns {boolean} True if bit is set
|
|
130
|
+
* @private
|
|
131
|
+
*/
|
|
132
|
+
_getBit(position) {
|
|
133
|
+
const byteIndex = Math.floor(position / 8);
|
|
134
|
+
const bitIndex = position % 8;
|
|
135
|
+
return (this._bits[byteIndex] & (1 << bitIndex)) !== 0;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Adds an item to the filter
|
|
140
|
+
* @param {string|Uint8Array} item - Item to add
|
|
141
|
+
*/
|
|
142
|
+
add(item) {
|
|
143
|
+
const positions = this._getPositions(item);
|
|
144
|
+
for (const pos of positions) {
|
|
145
|
+
this._setBit(pos);
|
|
146
|
+
}
|
|
147
|
+
this._count++;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Tests if an item might be in the filter
|
|
152
|
+
* @param {string|Uint8Array} item - Item to test
|
|
153
|
+
* @returns {boolean} True if item might be present, false if definitely absent
|
|
154
|
+
*/
|
|
155
|
+
mightContain(item) {
|
|
156
|
+
const positions = this._getPositions(item);
|
|
157
|
+
for (const pos of positions) {
|
|
158
|
+
if (!this._getBit(pos)) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Clears all items from the filter
|
|
167
|
+
*/
|
|
168
|
+
clear() {
|
|
169
|
+
this._bits.fill(0);
|
|
170
|
+
this._count = 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Gets the fill ratio of the filter
|
|
175
|
+
* @returns {number} Ratio of set bits to total bits (0-1)
|
|
176
|
+
*/
|
|
177
|
+
getFillRatio() {
|
|
178
|
+
let setBits = 0;
|
|
179
|
+
for (let i = 0; i < this._bits.length; i++) {
|
|
180
|
+
let byte = this._bits[i];
|
|
181
|
+
while (byte) {
|
|
182
|
+
setBits += byte & 1;
|
|
183
|
+
byte >>>= 1;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return setBits / this.size;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Gets the number of items added
|
|
191
|
+
* @returns {number} Count of items added
|
|
192
|
+
*/
|
|
193
|
+
getCount() {
|
|
194
|
+
return this._count;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Estimates false positive rate based on current fill
|
|
199
|
+
* @returns {number} Estimated false positive probability
|
|
200
|
+
*/
|
|
201
|
+
getEstimatedFalsePositiveRate() {
|
|
202
|
+
const fillRatio = this.getFillRatio();
|
|
203
|
+
return Math.pow(fillRatio, this.hashCount);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = BloomFilter;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Combined deduplication manager using Bloom filter and LRU cache
|
|
5
|
+
* @module mesh/dedup/DedupManager
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const BloomFilter = require('./BloomFilter');
|
|
9
|
+
const MessageCache = require('./MessageCache');
|
|
10
|
+
const { MESH_CONFIG } = require('../../constants');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Default configuration for deduplication
|
|
14
|
+
* @constant
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
const DEFAULT_CONFIG = {
|
|
18
|
+
bloomFilterSize: MESH_CONFIG.BLOOM_FILTER_SIZE,
|
|
19
|
+
bloomHashCount: MESH_CONFIG.BLOOM_HASH_COUNT,
|
|
20
|
+
cacheSize: 1024,
|
|
21
|
+
autoResetThreshold: 0.75
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Deduplication manager combining Bloom filter and LRU cache
|
|
26
|
+
* Uses Bloom filter for fast probabilistic checks with LRU cache as backup
|
|
27
|
+
* @class DedupManager
|
|
28
|
+
*/
|
|
29
|
+
class DedupManager {
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new DedupManager
|
|
32
|
+
* @param {Object} [options] - Configuration options
|
|
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
|
|
37
|
+
*/
|
|
38
|
+
constructor(options = {}) {
|
|
39
|
+
const config = { ...DEFAULT_CONFIG, ...options };
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Bloom filter for fast duplicate detection
|
|
43
|
+
* @type {BloomFilter}
|
|
44
|
+
* @private
|
|
45
|
+
*/
|
|
46
|
+
this._bloomFilter = new BloomFilter(
|
|
47
|
+
config.bloomFilterSize,
|
|
48
|
+
config.bloomHashCount
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* LRU cache for precise duplicate detection
|
|
53
|
+
* @type {MessageCache}
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
this._cache = new MessageCache(config.cacheSize);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Auto-reset threshold for Bloom filter
|
|
60
|
+
* @type {number}
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
63
|
+
this._autoResetThreshold = config.autoResetThreshold;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Statistics for monitoring
|
|
67
|
+
* @type {Object}
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
this._stats = {
|
|
71
|
+
checks: 0,
|
|
72
|
+
bloomPositives: 0,
|
|
73
|
+
cacheHits: 0,
|
|
74
|
+
duplicates: 0,
|
|
75
|
+
added: 0,
|
|
76
|
+
resets: 0
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Checks if a message ID has been seen before
|
|
82
|
+
* @param {string} messageId - Message ID to check
|
|
83
|
+
* @returns {boolean} True if message is a duplicate
|
|
84
|
+
*/
|
|
85
|
+
isDuplicate(messageId) {
|
|
86
|
+
this._stats.checks++;
|
|
87
|
+
|
|
88
|
+
// Quick check with Bloom filter
|
|
89
|
+
if (!this._bloomFilter.mightContain(messageId)) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
this._stats.bloomPositives++;
|
|
93
|
+
|
|
94
|
+
// Confirm with exact cache lookup (handles false positives)
|
|
95
|
+
if (this._cache.has(messageId)) {
|
|
96
|
+
this._stats.cacheHits++;
|
|
97
|
+
this._stats.duplicates++;
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Bloom filter false positive
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Marks a message ID as seen
|
|
107
|
+
* @param {string} messageId - Message ID to mark
|
|
108
|
+
*/
|
|
109
|
+
markSeen(messageId) {
|
|
110
|
+
this._bloomFilter.add(messageId);
|
|
111
|
+
this._cache.add(messageId);
|
|
112
|
+
this._stats.added++;
|
|
113
|
+
|
|
114
|
+
// Auto-reset Bloom filter if too full
|
|
115
|
+
if (this._bloomFilter.getFillRatio() >= this._autoResetThreshold) {
|
|
116
|
+
this._resetBloomFilter();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Checks and marks a message in one operation
|
|
122
|
+
* @param {string} messageId - Message ID to check and mark
|
|
123
|
+
* @returns {boolean} True if message was a duplicate
|
|
124
|
+
*/
|
|
125
|
+
checkAndMark(messageId) {
|
|
126
|
+
if (this.isDuplicate(messageId)) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
this.markSeen(messageId);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Resets the Bloom filter while preserving cache entries
|
|
135
|
+
* @private
|
|
136
|
+
*/
|
|
137
|
+
_resetBloomFilter() {
|
|
138
|
+
this._bloomFilter.clear();
|
|
139
|
+
this._stats.resets++;
|
|
140
|
+
|
|
141
|
+
// Re-add all cached entries to Bloom filter
|
|
142
|
+
const entries = this._cache.getAll();
|
|
143
|
+
for (const messageId of entries) {
|
|
144
|
+
this._bloomFilter.add(messageId);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Resets both the Bloom filter and cache
|
|
150
|
+
*/
|
|
151
|
+
reset() {
|
|
152
|
+
this._bloomFilter.clear();
|
|
153
|
+
this._cache.clear();
|
|
154
|
+
this._stats.resets++;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Gets deduplication statistics
|
|
159
|
+
* @returns {Object} Statistics object
|
|
160
|
+
*/
|
|
161
|
+
getStats() {
|
|
162
|
+
return {
|
|
163
|
+
...this._stats,
|
|
164
|
+
bloomFillRatio: this._bloomFilter.getFillRatio(),
|
|
165
|
+
bloomCount: this._bloomFilter.getCount(),
|
|
166
|
+
cacheSize: this._cache.size,
|
|
167
|
+
estimatedFalsePositiveRate: this._bloomFilter.getEstimatedFalsePositiveRate()
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Resets statistics counters
|
|
173
|
+
*/
|
|
174
|
+
resetStats() {
|
|
175
|
+
this._stats = {
|
|
176
|
+
checks: 0,
|
|
177
|
+
bloomPositives: 0,
|
|
178
|
+
cacheHits: 0,
|
|
179
|
+
duplicates: 0,
|
|
180
|
+
added: 0,
|
|
181
|
+
resets: 0
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Gets the number of unique messages seen
|
|
187
|
+
* @returns {number} Count of unique messages in cache
|
|
188
|
+
*/
|
|
189
|
+
getUniqueCount() {
|
|
190
|
+
return this._cache.size;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Checks if a specific message ID is in the exact cache
|
|
195
|
+
* @param {string} messageId - Message ID to check
|
|
196
|
+
* @returns {boolean} True if in cache
|
|
197
|
+
*/
|
|
198
|
+
isInCache(messageId) {
|
|
199
|
+
return this._cache.has(messageId);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Gets when a message was first seen
|
|
204
|
+
* @param {string} messageId - Message ID to look up
|
|
205
|
+
* @returns {number|null} Timestamp or null if not found
|
|
206
|
+
*/
|
|
207
|
+
getSeenTimestamp(messageId) {
|
|
208
|
+
return this._cache.getTimestamp(messageId);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
module.exports = DedupManager;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview LRU message cache for duplicate detection backup
|
|
5
|
+
* @module mesh/dedup/MessageCache
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* LRU Cache node for doubly-linked list
|
|
10
|
+
* @class CacheNode
|
|
11
|
+
* @private
|
|
12
|
+
*/
|
|
13
|
+
class CacheNode {
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new CacheNode
|
|
16
|
+
* @param {string} key - Message ID
|
|
17
|
+
* @param {number} timestamp - When the message was seen
|
|
18
|
+
*/
|
|
19
|
+
constructor(key, timestamp) {
|
|
20
|
+
this.key = key;
|
|
21
|
+
this.timestamp = timestamp;
|
|
22
|
+
this.prev = null;
|
|
23
|
+
this.next = null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* LRU message cache for storing recently seen message IDs
|
|
29
|
+
* Uses doubly-linked list for O(1) operations
|
|
30
|
+
* @class MessageCache
|
|
31
|
+
*/
|
|
32
|
+
class MessageCache {
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new MessageCache
|
|
35
|
+
* @param {number} maxSize - Maximum number of message IDs to store
|
|
36
|
+
*/
|
|
37
|
+
constructor(maxSize) {
|
|
38
|
+
if (!Number.isInteger(maxSize) || maxSize <= 0) {
|
|
39
|
+
throw new Error('Max size must be a positive integer');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Maximum number of entries
|
|
44
|
+
* @type {number}
|
|
45
|
+
*/
|
|
46
|
+
this.maxSize = maxSize;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Map of message IDs to cache nodes
|
|
50
|
+
* @type {Map<string, CacheNode>}
|
|
51
|
+
* @private
|
|
52
|
+
*/
|
|
53
|
+
this._map = new Map();
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Head of the LRU list (most recently used)
|
|
57
|
+
* @type {CacheNode|null}
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
this._head = null;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Tail of the LRU list (least recently used)
|
|
64
|
+
* @type {CacheNode|null}
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
this._tail = null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Moves a node to the head of the list
|
|
72
|
+
* @param {CacheNode} node - Node to move
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
_moveToHead(node) {
|
|
76
|
+
if (node === this._head) { return; }
|
|
77
|
+
|
|
78
|
+
// Remove from current position
|
|
79
|
+
if (node.prev) { node.prev.next = node.next; }
|
|
80
|
+
if (node.next) { node.next.prev = node.prev; }
|
|
81
|
+
if (node === this._tail) { this._tail = node.prev; }
|
|
82
|
+
|
|
83
|
+
// Move to head
|
|
84
|
+
node.prev = null;
|
|
85
|
+
node.next = this._head;
|
|
86
|
+
if (this._head) { this._head.prev = node; }
|
|
87
|
+
this._head = node;
|
|
88
|
+
if (!this._tail) { this._tail = node; }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Removes the tail node (least recently used)
|
|
93
|
+
* @returns {string|null} Removed message ID or null
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
_removeTail() {
|
|
97
|
+
if (!this._tail) { return null; }
|
|
98
|
+
|
|
99
|
+
const key = this._tail.key;
|
|
100
|
+
this._map.delete(key);
|
|
101
|
+
|
|
102
|
+
if (this._head === this._tail) {
|
|
103
|
+
this._head = null;
|
|
104
|
+
this._tail = null;
|
|
105
|
+
} else {
|
|
106
|
+
this._tail = this._tail.prev;
|
|
107
|
+
if (this._tail) { this._tail.next = null; }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return key;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Adds a message ID to the cache
|
|
115
|
+
* @param {string} messageId - Message ID to add
|
|
116
|
+
* @returns {boolean} True if newly added, false if already present
|
|
117
|
+
*/
|
|
118
|
+
add(messageId) {
|
|
119
|
+
if (typeof messageId !== 'string' || messageId.length === 0) {
|
|
120
|
+
throw new Error('Message ID must be a non-empty string');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check if already exists
|
|
124
|
+
const existing = this._map.get(messageId);
|
|
125
|
+
if (existing) {
|
|
126
|
+
existing.timestamp = Date.now();
|
|
127
|
+
this._moveToHead(existing);
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Create new node
|
|
132
|
+
const node = new CacheNode(messageId, Date.now());
|
|
133
|
+
this._map.set(messageId, node);
|
|
134
|
+
|
|
135
|
+
// Add to head
|
|
136
|
+
node.next = this._head;
|
|
137
|
+
if (this._head) { this._head.prev = node; }
|
|
138
|
+
this._head = node;
|
|
139
|
+
if (!this._tail) { this._tail = node; }
|
|
140
|
+
|
|
141
|
+
// Evict if over capacity
|
|
142
|
+
if (this._map.size > this.maxSize) {
|
|
143
|
+
this._removeTail();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Checks if a message ID is in the cache
|
|
151
|
+
* @param {string} messageId - Message ID to check
|
|
152
|
+
* @returns {boolean} True if present
|
|
153
|
+
*/
|
|
154
|
+
has(messageId) {
|
|
155
|
+
return this._map.has(messageId);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Gets the timestamp when a message was first seen
|
|
160
|
+
* @param {string} messageId - Message ID to look up
|
|
161
|
+
* @returns {number|null} Timestamp or null if not found
|
|
162
|
+
*/
|
|
163
|
+
getTimestamp(messageId) {
|
|
164
|
+
const node = this._map.get(messageId);
|
|
165
|
+
return node ? node.timestamp : null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Removes a message ID from the cache
|
|
170
|
+
* @param {string} messageId - Message ID to remove
|
|
171
|
+
* @returns {boolean} True if removed, false if not found
|
|
172
|
+
*/
|
|
173
|
+
delete(messageId) {
|
|
174
|
+
const node = this._map.get(messageId);
|
|
175
|
+
if (!node) { return false; }
|
|
176
|
+
|
|
177
|
+
// Update linked list
|
|
178
|
+
if (node.prev) { node.prev.next = node.next; }
|
|
179
|
+
if (node.next) { node.next.prev = node.prev; }
|
|
180
|
+
if (node === this._head) { this._head = node.next; }
|
|
181
|
+
if (node === this._tail) { this._tail = node.prev; }
|
|
182
|
+
|
|
183
|
+
this._map.delete(messageId);
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Clears all entries from the cache
|
|
189
|
+
*/
|
|
190
|
+
clear() {
|
|
191
|
+
this._map.clear();
|
|
192
|
+
this._head = null;
|
|
193
|
+
this._tail = null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Gets the current number of entries
|
|
198
|
+
* @returns {number} Number of cached message IDs
|
|
199
|
+
*/
|
|
200
|
+
get size() {
|
|
201
|
+
return this._map.size;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Gets all message IDs in the cache (most recent first)
|
|
206
|
+
* @returns {string[]} Array of message IDs
|
|
207
|
+
*/
|
|
208
|
+
getAll() {
|
|
209
|
+
const result = [];
|
|
210
|
+
let node = this._head;
|
|
211
|
+
while (node) {
|
|
212
|
+
result.push(node.key);
|
|
213
|
+
node = node.next;
|
|
214
|
+
}
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
module.exports = MessageCache;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Deduplication module exports
|
|
5
|
+
* @module mesh/dedup
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const BloomFilter = require('./BloomFilter');
|
|
9
|
+
const MessageCache = require('./MessageCache');
|
|
10
|
+
const DedupManager = require('./DedupManager');
|
|
11
|
+
|
|
12
|
+
module.exports = {
|
|
13
|
+
BloomFilter,
|
|
14
|
+
MessageCache,
|
|
15
|
+
DedupManager
|
|
16
|
+
};
|