From 0db92dd70cd1727082ea00e158534a890eb897fb Mon Sep 17 00:00:00 2001 From: Green Sky Date: Sat, 9 Dec 2023 12:25:10 +0100 Subject: [PATCH] add zox ngc audio packet parsing and events --- solanaceae/zox/ngc.cpp | 85 ++++++++++++++++++++++++++++++++++++++++++ solanaceae/zox/ngc.hpp | 32 +++++++++++++++- 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/solanaceae/zox/ngc.cpp b/solanaceae/zox/ngc.cpp index 89d321d..7d7fdde 100644 --- a/solanaceae/zox/ngc.cpp +++ b/solanaceae/zox/ngc.cpp @@ -1,5 +1,7 @@ #include "./ngc.hpp" +#include +#include #include #include #include @@ -61,6 +63,9 @@ bool ZoxNGCEventProvider::onZoxGroupEvent( std::cout << "ZOX waring: ngch_syncmsg_file not implemented\n"; } else if (version == 0x01 && pkt_id == 0x11) { std::cout << "ZOX waring: ngc_ft not implemented\n"; + } else if (version == 0x01 && pkt_id == 0x31) { + // ngca + return parse_ngca(group_number, peer_number, data, data_size, _private); } else { std::cout << "ZOX waring: unknown packet v" << (int)version @@ -77,6 +82,14 @@ bool ZoxNGCEventProvider::parse_ngch_request( const uint8_t* data, size_t data_size, bool _private ) { + +//| what | Length in bytes| Contents | +//|-----------|----------------|------------------| +//| magic | 6 | 0x667788113435 | +//| version | 1 | 0x01 | +//| pkt id | 1 | 0x01 | +//| sync delta| 1 | how many minutes back from now() to get messages. allowed values from 5 to 130 minutes (both inclusive) | + if (data_size > 1) { std::cerr << "ZOX ngch_request has wrong size, should: <=1 , is: " << data_size << "\n"; return false; @@ -111,6 +124,17 @@ bool ZoxNGCEventProvider::parse_ngch_syncmsg( bool _private ) { +//| what | Length in bytes| Contents | +//|-------------|----------------|-------------------------------------------------------------------------------| +//| magic | 6 | 0x667788113435 | +//| version | 1 | 0x01 | +//| pkt id | 1 | 0x02 <-- text | +//| msg id | 4 | 4 bytes message id for this group message | +//| sender | 32 | 32 bytes pubkey of the original sender in the ngc group | +//| timestamp | 4 | uint32_t unixtimestamp in UTC of local wall clock (in bigendian) when the message was originally sent | +//| name | 25 | sender name 25 bytes (cut off if longer, or right padded with 0x0 bytes) | +//| message | [1, 39927] | message text, zero length message not allowed! | + constexpr size_t min_pkg_size = 4 + 32 + 4 + 25; if (data_size <= 4 + 32 + 4 + 25) { std::cerr << "ZOX ngch_syncmsg has wrong size, should: >=" << min_pkg_size << " , is: " << data_size << "\n"; @@ -174,6 +198,67 @@ bool ZoxNGCEventProvider::parse_ngch_syncmsg( ); } +bool ZoxNGCEventProvider::parse_ngca( + uint32_t group_number, uint32_t peer_number, + const uint8_t* data, size_t data_size, + bool _private +) { + +//| what | Length in bytes| Contents | +//|------ |-------- |------------------ | +//| magic | 6 | 0x667788113435 | +//| version | 1 | 0x01 | +//| pkt id | 1 | 0x31 | +//| audio channels| 1 | uint8_t always 1 (for MONO) | +//| sampling freq | 1 | uint8_t always 48 (for 48kHz) | +//| data |[1, 1362] | *uint8_t bytes, zero not allowed! | + + constexpr size_t min_pkg_size = 1 + 1 + 1; + if (data_size < min_pkg_size) { + std::cerr << "ZOX ngca has wrong size, should: >=" << min_pkg_size << " , is: " << data_size << "\n"; + return false; + } + + constexpr size_t max_pkg_size = 1 + 1 + 1362; + if (data_size > max_pkg_size) { + std::cerr << "ZOX ngca has wrong size, should: <=" << max_pkg_size << " , is: " << data_size << "\n"; + return false; + } + + // 1 byte, audio channels + uint8_t audio_channels = 0; + { + audio_channels = data[0]; + + data += 1; + data_size -= 1; + } + + // 1 byte, sampling freq + uint8_t sampling_freq = 0; + { + sampling_freq = data[0]; + + data += 1; + data_size -= 1; + } + + // 1-1362 bytes, data + std::vector v_data{data, data+data_size}; + + return dispatch( + ZoxNGC_Event::ngca, + Events::ZoxNGC_ngca{ + group_number, + peer_number, + _private, + audio_channels, + sampling_freq, + std::move(v_data) + } + ); +} + bool ZoxNGCEventProvider::onToxEvent(const Tox_Event_Group_Custom_Packet* e) { const uint32_t group_number = tox_event_group_custom_packet_get_group_number(e); const uint32_t peer_number = tox_event_group_custom_packet_get_peer_id(e); diff --git a/solanaceae/zox/ngc.hpp b/solanaceae/zox/ngc.hpp index db0b215..6d7aa43 100644 --- a/solanaceae/zox/ngc.hpp +++ b/solanaceae/zox/ngc.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -10,8 +11,12 @@ // fwd //struct ToxI; -// zoff ngc history sync (draft1?) -// https://gist.github.com/zoff99/81917ddb2e55b2ce602cac4772a7b68c +// zoff ngc history sync +// https://github.com/zoff99/c-toxcore/blob/zoff99/zoxcore_local_fork/docs/ngc_group_history_sync.md +// (old) https://gist.github.com/zoff99/81917ddb2e55b2ce602cac4772a7b68c + +// zoff ngc audio +// https://github.com/zoff99/c-toxcore/blob/zoff99/zoxcore_local_fork/docs/ngc_audio.md namespace Events { @@ -38,6 +43,17 @@ namespace Events { std::string_view message_text; }; + struct ZoxNGC_ngca { + uint32_t group_number {0u}; + uint32_t peer_number {0u}; + + bool _private {true}; + + uint8_t audio_channels {1u}; + uint8_t sampling_freq {48u}; // for 48kHz + std::vector data; // 1-1362 bytes of opus encoded audio + }; + } // Events enum class ZoxNGC_Event : uint32_t { @@ -70,6 +86,11 @@ enum class ZoxNGC_Event : uint32_t { // ... + v0x01_id0x31, + ngca = v0x01_id0x31, + + // ... + // v0x02_id0x01 MAX @@ -81,6 +102,7 @@ struct ZoxNGCEventI { using enumType = ZoxNGC_Event; virtual bool onEvent(const Events::ZoxNGC_ngch_request&) { return false; } virtual bool onEvent(const Events::ZoxNGC_ngch_syncmsg&) { return false; } + virtual bool onEvent(const Events::ZoxNGC_ngca&) { return false; } }; using ZoxNGCEventProviderI = EventProviderI; @@ -114,6 +136,12 @@ class ZoxNGCEventProvider : public ToxEventI, public ZoxNGCEventProviderI { bool _private ); + bool parse_ngca( + uint32_t group_number, uint32_t peer_number, + const uint8_t* data, size_t data_size, + bool _private + ); + protected: bool onToxEvent(const Tox_Event_Group_Custom_Packet* e) override; bool onToxEvent(const Tox_Event_Group_Custom_Private_Packet* e) override;