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
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview CRC32 checksum implementation using standard polynomial.
|
|
5
|
+
* @module protocol/crc32
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CRC32 polynomial (IEEE 802.3 standard, reversed).
|
|
10
|
+
* @constant {number}
|
|
11
|
+
*/
|
|
12
|
+
const CRC32_POLYNOMIAL = 0xEDB88320;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Pre-computed CRC32 lookup table.
|
|
16
|
+
* @type {Uint32Array}
|
|
17
|
+
*/
|
|
18
|
+
const CRC32_TABLE = buildTable();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Builds the CRC32 lookup table.
|
|
22
|
+
* @returns {Uint32Array} 256-entry lookup table
|
|
23
|
+
*/
|
|
24
|
+
function buildTable() {
|
|
25
|
+
const table = new Uint32Array(256);
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < 256; i++) {
|
|
28
|
+
let crc = i;
|
|
29
|
+
for (let j = 0; j < 8; j++) {
|
|
30
|
+
if (crc & 1) {
|
|
31
|
+
crc = (crc >>> 1) ^ CRC32_POLYNOMIAL;
|
|
32
|
+
} else {
|
|
33
|
+
crc = crc >>> 1;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
table[i] = crc >>> 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return table;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Calculates CRC32 checksum of the given data.
|
|
44
|
+
* Uses the standard CRC32 polynomial (0xEDB88320) with the IEEE algorithm.
|
|
45
|
+
*
|
|
46
|
+
* @param {Uint8Array} data - Input data to compute checksum for
|
|
47
|
+
* @returns {number} 32-bit unsigned CRC32 checksum
|
|
48
|
+
* @throws {TypeError} If data is not a Uint8Array
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]); // "Hello"
|
|
52
|
+
* const checksum = crc32(data);
|
|
53
|
+
* console.log(checksum.toString(16)); // "f7d18982"
|
|
54
|
+
*/
|
|
55
|
+
function crc32(data) {
|
|
56
|
+
if (!(data instanceof Uint8Array)) {
|
|
57
|
+
throw new TypeError('Data must be a Uint8Array');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let crc = 0xFFFFFFFF;
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < data.length; i++) {
|
|
63
|
+
const byte = data[i];
|
|
64
|
+
const tableIndex = (crc ^ byte) & 0xFF;
|
|
65
|
+
crc = (crc >>> 8) ^ CRC32_TABLE[tableIndex];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Return inverted result as unsigned 32-bit integer
|
|
69
|
+
return (crc ^ 0xFFFFFFFF) >>> 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Verifies that data matches an expected CRC32 checksum.
|
|
74
|
+
*
|
|
75
|
+
* @param {Uint8Array} data - Input data to verify
|
|
76
|
+
* @param {number} expectedCrc - Expected CRC32 checksum
|
|
77
|
+
* @returns {boolean} True if checksum matches
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
|
|
81
|
+
* const isValid = verifyCrc32(data, 0xf7d18982);
|
|
82
|
+
* console.log(isValid); // true
|
|
83
|
+
*/
|
|
84
|
+
function verifyCrc32(data, expectedCrc) {
|
|
85
|
+
const actualCrc = crc32(data);
|
|
86
|
+
return actualCrc === (expectedCrc >>> 0);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = {
|
|
90
|
+
crc32,
|
|
91
|
+
verifyCrc32,
|
|
92
|
+
CRC32_POLYNOMIAL
|
|
93
|
+
};
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Binary deserialization for mesh protocol messages.
|
|
5
|
+
* @module protocol/deserializer
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { MessageHeader, HEADER_SIZE } = require('./header');
|
|
9
|
+
const { Message } = require('./message');
|
|
10
|
+
const { crc32 } = require('./crc32');
|
|
11
|
+
const { MessageError } = require('../errors');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Deserializes a message header from bytes.
|
|
15
|
+
* Validates minimum length and verifies checksum.
|
|
16
|
+
*
|
|
17
|
+
* @param {Uint8Array} data - Raw header bytes (minimum 48 bytes)
|
|
18
|
+
* @returns {MessageHeader} Parsed header
|
|
19
|
+
* @throws {MessageError} If data is invalid or checksum fails
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const header = deserializeHeader(headerBytes);
|
|
23
|
+
* console.log(header.type, header.messageId);
|
|
24
|
+
*/
|
|
25
|
+
function deserializeHeader(data) {
|
|
26
|
+
// Validate input type
|
|
27
|
+
if (!(data instanceof Uint8Array)) {
|
|
28
|
+
throw MessageError.invalidFormat(null, {
|
|
29
|
+
reason: 'Data must be a Uint8Array'
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Validate minimum length
|
|
34
|
+
if (data.length < HEADER_SIZE) {
|
|
35
|
+
throw MessageError.invalidFormat(null, {
|
|
36
|
+
reason: 'Data too short for header',
|
|
37
|
+
expected: HEADER_SIZE,
|
|
38
|
+
actual: data.length
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const headerData = data.slice(0, HEADER_SIZE);
|
|
43
|
+
const view = new DataView(headerData.buffer, headerData.byteOffset, HEADER_SIZE);
|
|
44
|
+
|
|
45
|
+
// Extract checksum from bytes 44-47 (big-endian)
|
|
46
|
+
const storedChecksum = view.getUint32(44, false);
|
|
47
|
+
|
|
48
|
+
// Calculate checksum over bytes 0-43
|
|
49
|
+
const checksumData = headerData.slice(0, 44);
|
|
50
|
+
const calculatedChecksum = crc32(checksumData);
|
|
51
|
+
|
|
52
|
+
// Verify checksum
|
|
53
|
+
if (storedChecksum !== calculatedChecksum) {
|
|
54
|
+
throw MessageError.invalidChecksum(null, {
|
|
55
|
+
stored: storedChecksum.toString(16),
|
|
56
|
+
calculated: calculatedChecksum.toString(16)
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Parse header fields
|
|
61
|
+
const header = new MessageHeader({
|
|
62
|
+
version: headerData[0],
|
|
63
|
+
type: headerData[1],
|
|
64
|
+
flags: headerData[2],
|
|
65
|
+
hopCount: headerData[3],
|
|
66
|
+
maxHops: headerData[4],
|
|
67
|
+
// bytes 5-7 are reserved
|
|
68
|
+
messageId: headerData.slice(8, 24),
|
|
69
|
+
timestamp: readUint64BE(view, 24),
|
|
70
|
+
expiresAt: readUint64BE(view, 32),
|
|
71
|
+
payloadLength: view.getUint16(40, false),
|
|
72
|
+
fragmentIndex: headerData[42],
|
|
73
|
+
fragmentTotal: headerData[43],
|
|
74
|
+
checksum: storedChecksum
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return header;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Deserializes a complete message (header + payload) from bytes.
|
|
82
|
+
* Validates header checksum and payload length.
|
|
83
|
+
*
|
|
84
|
+
* @param {Uint8Array} data - Raw message bytes
|
|
85
|
+
* @returns {Message} Parsed message
|
|
86
|
+
* @throws {MessageError} If data is invalid
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* const message = deserialize(rawBytes);
|
|
90
|
+
* console.log(message.getContent());
|
|
91
|
+
*/
|
|
92
|
+
function deserialize(data) {
|
|
93
|
+
// Validate input type
|
|
94
|
+
if (!(data instanceof Uint8Array)) {
|
|
95
|
+
throw MessageError.invalidFormat(null, {
|
|
96
|
+
reason: 'Data must be a Uint8Array'
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Validate minimum length for header
|
|
101
|
+
if (data.length < HEADER_SIZE) {
|
|
102
|
+
throw MessageError.invalidFormat(null, {
|
|
103
|
+
reason: 'Data too short for message',
|
|
104
|
+
minSize: HEADER_SIZE,
|
|
105
|
+
actual: data.length
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Parse header first
|
|
110
|
+
const header = deserializeHeader(data);
|
|
111
|
+
|
|
112
|
+
// Validate total message length
|
|
113
|
+
const expectedLength = HEADER_SIZE + header.payloadLength;
|
|
114
|
+
|
|
115
|
+
if (data.length < expectedLength) {
|
|
116
|
+
throw MessageError.invalidFormat(header.getMessageIdHex(), {
|
|
117
|
+
reason: 'Incomplete payload',
|
|
118
|
+
expected: expectedLength,
|
|
119
|
+
actual: data.length
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Extract payload
|
|
124
|
+
const payload = data.slice(HEADER_SIZE, HEADER_SIZE + header.payloadLength);
|
|
125
|
+
|
|
126
|
+
return new Message(header, payload);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Attempts to deserialize a message, returning null on failure.
|
|
131
|
+
* Useful when processing potentially malformed data.
|
|
132
|
+
*
|
|
133
|
+
* @param {Uint8Array} data - Raw message bytes
|
|
134
|
+
* @returns {Message|null} Parsed message or null if invalid
|
|
135
|
+
*/
|
|
136
|
+
function tryDeserialize(data) {
|
|
137
|
+
try {
|
|
138
|
+
return deserialize(data);
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Deserializes multiple messages from a concatenated buffer.
|
|
146
|
+
* Stops at first invalid message.
|
|
147
|
+
*
|
|
148
|
+
* @param {Uint8Array} data - Buffer containing multiple messages
|
|
149
|
+
* @returns {Array<Message>} Array of parsed messages
|
|
150
|
+
*/
|
|
151
|
+
function deserializeBatch(data) {
|
|
152
|
+
if (!(data instanceof Uint8Array)) {
|
|
153
|
+
throw MessageError.invalidFormat(null, {
|
|
154
|
+
reason: 'Data must be a Uint8Array'
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const messages = [];
|
|
159
|
+
let offset = 0;
|
|
160
|
+
|
|
161
|
+
while (offset < data.length) {
|
|
162
|
+
// Need at least header size remaining
|
|
163
|
+
if (data.length - offset < HEADER_SIZE) {
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Peek at payload length to know full message size
|
|
168
|
+
const view = new DataView(data.buffer, data.byteOffset + offset, HEADER_SIZE);
|
|
169
|
+
const payloadLength = view.getUint16(40, false);
|
|
170
|
+
const messageLength = HEADER_SIZE + payloadLength;
|
|
171
|
+
|
|
172
|
+
// Check if we have the complete message
|
|
173
|
+
if (data.length - offset < messageLength) {
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Extract and deserialize this message
|
|
178
|
+
const messageData = data.slice(offset, offset + messageLength);
|
|
179
|
+
|
|
180
|
+
try {
|
|
181
|
+
const message = deserialize(messageData);
|
|
182
|
+
messages.push(message);
|
|
183
|
+
offset += messageLength;
|
|
184
|
+
} catch (error) {
|
|
185
|
+
// Stop on first error
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return messages;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Reads a 64-bit unsigned integer in big-endian format.
|
|
195
|
+
* JavaScript numbers can safely represent integers up to 2^53.
|
|
196
|
+
*
|
|
197
|
+
* @param {DataView} view - DataView to read from
|
|
198
|
+
* @param {number} offset - Byte offset
|
|
199
|
+
* @returns {number} 64-bit value
|
|
200
|
+
*/
|
|
201
|
+
function readUint64BE(view, offset) {
|
|
202
|
+
const high = view.getUint32(offset, false);
|
|
203
|
+
const low = view.getUint32(offset + 4, false);
|
|
204
|
+
return high * 0x100000000 + low;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Peeks at message type without full deserialization.
|
|
209
|
+
* Useful for routing decisions.
|
|
210
|
+
*
|
|
211
|
+
* @param {Uint8Array} data - Raw message bytes
|
|
212
|
+
* @returns {number|null} Message type or null if invalid
|
|
213
|
+
*/
|
|
214
|
+
function peekMessageType(data) {
|
|
215
|
+
if (!(data instanceof Uint8Array) || data.length < 2) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
return data[1];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Peeks at message ID without full deserialization.
|
|
223
|
+
*
|
|
224
|
+
* @param {Uint8Array} data - Raw message bytes
|
|
225
|
+
* @returns {Uint8Array|null} 16-byte message ID or null if invalid
|
|
226
|
+
*/
|
|
227
|
+
function peekMessageId(data) {
|
|
228
|
+
if (!(data instanceof Uint8Array) || data.length < 24) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
return data.slice(8, 24);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
module.exports = {
|
|
235
|
+
deserialize,
|
|
236
|
+
deserializeHeader,
|
|
237
|
+
tryDeserialize,
|
|
238
|
+
deserializeBatch,
|
|
239
|
+
peekMessageType,
|
|
240
|
+
peekMessageId
|
|
241
|
+
};
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Message header structure and serialization (48 bytes).
|
|
5
|
+
* @module protocol/header
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { crc32 } = require('./crc32');
|
|
9
|
+
const { PROTOCOL_VERSION, MESSAGE_FLAGS, MESH_CONFIG } = require('../constants');
|
|
10
|
+
const { MessageError } = require('../errors');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Header size in bytes.
|
|
14
|
+
* @constant {number}
|
|
15
|
+
*/
|
|
16
|
+
const HEADER_SIZE = 48;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Message header class representing the 48-byte header structure.
|
|
20
|
+
* @class MessageHeader
|
|
21
|
+
*/
|
|
22
|
+
class MessageHeader {
|
|
23
|
+
/**
|
|
24
|
+
* Creates a new MessageHeader instance.
|
|
25
|
+
* @param {Object} options - Header options
|
|
26
|
+
* @param {number} [options.version=1] - Protocol version
|
|
27
|
+
* @param {number} options.type - Message type from MESSAGE_TYPE
|
|
28
|
+
* @param {number} [options.flags=0] - Message flags
|
|
29
|
+
* @param {number} [options.hopCount=0] - Current hop count
|
|
30
|
+
* @param {number} [options.maxHops=7] - Maximum hops allowed
|
|
31
|
+
* @param {Uint8Array} options.messageId - 16-byte UUID
|
|
32
|
+
* @param {number} options.timestamp - Unix timestamp in ms
|
|
33
|
+
* @param {number} options.expiresAt - Expiration timestamp in ms
|
|
34
|
+
* @param {number} options.payloadLength - Payload size in bytes
|
|
35
|
+
* @param {number} [options.fragmentIndex=0] - Fragment index (0-based)
|
|
36
|
+
* @param {number} [options.fragmentTotal=1] - Total fragments
|
|
37
|
+
* @param {number} [options.checksum=0] - CRC32 checksum
|
|
38
|
+
*/
|
|
39
|
+
constructor(options) {
|
|
40
|
+
this.version = options.version ?? PROTOCOL_VERSION;
|
|
41
|
+
this.type = options.type;
|
|
42
|
+
this.flags = options.flags ?? MESSAGE_FLAGS.NONE;
|
|
43
|
+
this.hopCount = options.hopCount ?? 0;
|
|
44
|
+
this.maxHops = options.maxHops ?? MESH_CONFIG.MAX_HOPS;
|
|
45
|
+
this.reserved = new Uint8Array(3);
|
|
46
|
+
this.messageId = options.messageId;
|
|
47
|
+
this.timestamp = options.timestamp;
|
|
48
|
+
this.expiresAt = options.expiresAt;
|
|
49
|
+
this.payloadLength = options.payloadLength;
|
|
50
|
+
this.fragmentIndex = options.fragmentIndex ?? 0;
|
|
51
|
+
this.fragmentTotal = options.fragmentTotal ?? 1;
|
|
52
|
+
this.checksum = options.checksum ?? 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new MessageHeader with generated UUID and timestamps.
|
|
57
|
+
* @param {Object} options - Header creation options
|
|
58
|
+
* @param {number} options.type - Message type
|
|
59
|
+
* @param {number} [options.flags=0] - Message flags
|
|
60
|
+
* @param {number} [options.maxHops=7] - Maximum hops
|
|
61
|
+
* @param {number} options.payloadLength - Payload size
|
|
62
|
+
* @param {number} [options.fragmentIndex=0] - Fragment index
|
|
63
|
+
* @param {number} [options.fragmentTotal=1] - Total fragments
|
|
64
|
+
* @param {number} [options.ttlMs] - Time-to-live in ms
|
|
65
|
+
* @returns {MessageHeader} New header instance
|
|
66
|
+
*/
|
|
67
|
+
static create(options) {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const ttl = options.ttlMs ?? MESH_CONFIG.MESSAGE_TTL_MS;
|
|
70
|
+
|
|
71
|
+
return new MessageHeader({
|
|
72
|
+
version: PROTOCOL_VERSION,
|
|
73
|
+
type: options.type,
|
|
74
|
+
flags: options.flags ?? MESSAGE_FLAGS.NONE,
|
|
75
|
+
hopCount: 0,
|
|
76
|
+
maxHops: options.maxHops ?? MESH_CONFIG.MAX_HOPS,
|
|
77
|
+
messageId: generateUuid(),
|
|
78
|
+
timestamp: now,
|
|
79
|
+
expiresAt: now + ttl,
|
|
80
|
+
payloadLength: options.payloadLength,
|
|
81
|
+
fragmentIndex: options.fragmentIndex ?? 0,
|
|
82
|
+
fragmentTotal: options.fragmentTotal ?? 1,
|
|
83
|
+
checksum: 0
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Deserializes a header from bytes.
|
|
89
|
+
* @param {Uint8Array} data - 48-byte header data
|
|
90
|
+
* @returns {MessageHeader} Parsed header
|
|
91
|
+
* @throws {MessageError} If data is invalid
|
|
92
|
+
*/
|
|
93
|
+
static fromBytes(data) {
|
|
94
|
+
if (!(data instanceof Uint8Array) || data.length < HEADER_SIZE) {
|
|
95
|
+
throw MessageError.invalidFormat(null, { reason: 'Header too small' });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const view = new DataView(data.buffer, data.byteOffset, HEADER_SIZE);
|
|
99
|
+
|
|
100
|
+
return new MessageHeader({
|
|
101
|
+
version: data[0],
|
|
102
|
+
type: data[1],
|
|
103
|
+
flags: data[2],
|
|
104
|
+
hopCount: data[3],
|
|
105
|
+
maxHops: data[4],
|
|
106
|
+
messageId: data.slice(8, 24),
|
|
107
|
+
timestamp: readUint64BE(view, 24),
|
|
108
|
+
expiresAt: readUint64BE(view, 32),
|
|
109
|
+
payloadLength: view.getUint16(40, false),
|
|
110
|
+
fragmentIndex: data[42],
|
|
111
|
+
fragmentTotal: data[43],
|
|
112
|
+
checksum: view.getUint32(44, false)
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Serializes the header to bytes.
|
|
118
|
+
* @returns {Uint8Array} 48-byte header
|
|
119
|
+
*/
|
|
120
|
+
toBytes() {
|
|
121
|
+
return MessageHeader.toBytes(this);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Serializes a header to bytes.
|
|
126
|
+
* @param {MessageHeader} header - Header to serialize
|
|
127
|
+
* @returns {Uint8Array} 48-byte header
|
|
128
|
+
*/
|
|
129
|
+
static toBytes(header) {
|
|
130
|
+
const buffer = new Uint8Array(HEADER_SIZE);
|
|
131
|
+
const view = new DataView(buffer.buffer);
|
|
132
|
+
|
|
133
|
+
buffer[0] = header.version;
|
|
134
|
+
buffer[1] = header.type;
|
|
135
|
+
buffer[2] = header.flags;
|
|
136
|
+
buffer[3] = header.hopCount;
|
|
137
|
+
buffer[4] = header.maxHops;
|
|
138
|
+
// bytes 5-7 reserved (zeros)
|
|
139
|
+
buffer.set(header.messageId, 8);
|
|
140
|
+
writeUint64BE(view, 24, header.timestamp);
|
|
141
|
+
writeUint64BE(view, 32, header.expiresAt);
|
|
142
|
+
view.setUint16(40, header.payloadLength, false);
|
|
143
|
+
buffer[42] = header.fragmentIndex;
|
|
144
|
+
buffer[43] = header.fragmentTotal;
|
|
145
|
+
// Calculate checksum over header without checksum field
|
|
146
|
+
const checksumData = buffer.slice(0, 44);
|
|
147
|
+
const checksum = crc32(checksumData);
|
|
148
|
+
view.setUint32(44, checksum, false);
|
|
149
|
+
header.checksum = checksum;
|
|
150
|
+
|
|
151
|
+
return buffer;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Returns the message ID as a hex string.
|
|
156
|
+
* @returns {string} UUID hex string
|
|
157
|
+
*/
|
|
158
|
+
getMessageIdHex() {
|
|
159
|
+
return bytesToHex(this.messageId);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Generates a random 16-byte UUID.
|
|
165
|
+
* @returns {Uint8Array} 16-byte UUID
|
|
166
|
+
*/
|
|
167
|
+
function generateUuid() {
|
|
168
|
+
const uuid = new Uint8Array(16);
|
|
169
|
+
if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.getRandomValues) {
|
|
170
|
+
globalThis.crypto.getRandomValues(uuid);
|
|
171
|
+
} else {
|
|
172
|
+
const nodeCrypto = require('crypto');
|
|
173
|
+
const randomBuffer = nodeCrypto.randomBytes(16);
|
|
174
|
+
uuid.set(randomBuffer);
|
|
175
|
+
}
|
|
176
|
+
// Set version 4 (random) and variant bits
|
|
177
|
+
uuid[6] = (uuid[6] & 0x0f) | 0x40;
|
|
178
|
+
uuid[8] = (uuid[8] & 0x3f) | 0x80;
|
|
179
|
+
return uuid;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Reads a 64-bit unsigned integer (big-endian) from DataView.
|
|
184
|
+
* @param {DataView} view - DataView to read from
|
|
185
|
+
* @param {number} offset - Byte offset
|
|
186
|
+
* @returns {number} 64-bit value (may lose precision for large values)
|
|
187
|
+
*/
|
|
188
|
+
function readUint64BE(view, offset) {
|
|
189
|
+
const high = view.getUint32(offset, false);
|
|
190
|
+
const low = view.getUint32(offset + 4, false);
|
|
191
|
+
return high * 0x100000000 + low;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Writes a 64-bit unsigned integer (big-endian) to DataView.
|
|
196
|
+
* @param {DataView} view - DataView to write to
|
|
197
|
+
* @param {number} offset - Byte offset
|
|
198
|
+
* @param {number} value - Value to write
|
|
199
|
+
*/
|
|
200
|
+
function writeUint64BE(view, offset, value) {
|
|
201
|
+
const high = Math.floor(value / 0x100000000);
|
|
202
|
+
const low = value >>> 0;
|
|
203
|
+
view.setUint32(offset, high, false);
|
|
204
|
+
view.setUint32(offset + 4, low, false);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Converts bytes to hex string.
|
|
209
|
+
* @param {Uint8Array} bytes - Bytes to convert
|
|
210
|
+
* @returns {string} Hex string
|
|
211
|
+
*/
|
|
212
|
+
function bytesToHex(bytes) {
|
|
213
|
+
return Array.from(bytes)
|
|
214
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
215
|
+
.join('');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
module.exports = {
|
|
219
|
+
MessageHeader,
|
|
220
|
+
HEADER_SIZE,
|
|
221
|
+
generateUuid
|
|
222
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Protocol module exports for BLE Mesh Network library.
|
|
5
|
+
* Provides message serialization, deserialization, and validation.
|
|
6
|
+
* @module protocol
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { crc32, verifyCrc32, CRC32_POLYNOMIAL } = require('./crc32');
|
|
10
|
+
const { MessageHeader, HEADER_SIZE, generateUuid } = require('./header');
|
|
11
|
+
const { Message } = require('./message');
|
|
12
|
+
const { serialize, serializeHeader, serializeBatch } = require('./serializer');
|
|
13
|
+
const {
|
|
14
|
+
deserialize,
|
|
15
|
+
deserializeHeader,
|
|
16
|
+
tryDeserialize,
|
|
17
|
+
deserializeBatch,
|
|
18
|
+
peekMessageType,
|
|
19
|
+
peekMessageId
|
|
20
|
+
} = require('./deserializer');
|
|
21
|
+
const {
|
|
22
|
+
validateMessage,
|
|
23
|
+
validateHeader,
|
|
24
|
+
validateChecksum,
|
|
25
|
+
validateRawMessage,
|
|
26
|
+
isValidMessageType,
|
|
27
|
+
isExpired,
|
|
28
|
+
hasExceededMaxHops
|
|
29
|
+
} = require('./validator');
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
// CRC32
|
|
33
|
+
crc32,
|
|
34
|
+
verifyCrc32,
|
|
35
|
+
CRC32_POLYNOMIAL,
|
|
36
|
+
|
|
37
|
+
// Header
|
|
38
|
+
MessageHeader,
|
|
39
|
+
HEADER_SIZE,
|
|
40
|
+
generateUuid,
|
|
41
|
+
|
|
42
|
+
// Message
|
|
43
|
+
Message,
|
|
44
|
+
|
|
45
|
+
// Serialization
|
|
46
|
+
serialize,
|
|
47
|
+
serializeHeader,
|
|
48
|
+
serializeBatch,
|
|
49
|
+
|
|
50
|
+
// Deserialization
|
|
51
|
+
deserialize,
|
|
52
|
+
deserializeHeader,
|
|
53
|
+
tryDeserialize,
|
|
54
|
+
deserializeBatch,
|
|
55
|
+
peekMessageType,
|
|
56
|
+
peekMessageId,
|
|
57
|
+
|
|
58
|
+
// Validation
|
|
59
|
+
validateMessage,
|
|
60
|
+
validateHeader,
|
|
61
|
+
validateChecksum,
|
|
62
|
+
validateRawMessage,
|
|
63
|
+
isValidMessageType,
|
|
64
|
+
isExpired,
|
|
65
|
+
hasExceededMaxHops
|
|
66
|
+
};
|