From 18aed9abdf2304b2c97dba7ccbe545d6741b06de Mon Sep 17 00:00:00 2001 From: liu weikai Date: Fri, 17 Jul 2026 01:48:28 +0800 Subject: [PATCH] Refine Reticulum payload memory and chat status UI --- .../include/chat/infra/lxmf/lxmf_wire.h | 13 ++ .../core_chat/src/infra/lxmf/lxmf_wire.cpp | 67 ++++++++ .../chat/chat_conversation_components.h | 2 +- .../screens/chat/chat_conversation_layout.h | 3 - .../screens/chat/chat_conversation_styles.h | 1 - modules/ui_shared/src/ui/app_runtime.cpp | 4 + .../chat/chat_conversation_components.cpp | 106 +++++++++--- .../screens/chat/chat_conversation_layout.cpp | 7 - .../screens/chat/chat_conversation_styles.cpp | 12 -- packs/ar/locales/ar/strings.tsv | 2 + .../locales/ru/strings.tsv | 2 + packs/europe-latin-ext/locales/de/strings.tsv | 2 + packs/europe-latin-ext/locales/es/strings.tsv | 2 + packs/europe-latin-ext/locales/fr/strings.tsv | 2 + packs/europe-latin-ext/locales/it/strings.tsv | 2 + packs/europe-latin-ext/locales/nl/strings.tsv | 2 + packs/europe-latin-ext/locales/pl/strings.tsv | 2 + .../locales/pt-PT/strings.tsv | 2 + packs/ja/locales/ja/strings.tsv | 2 + packs/ko/locales/ko/strings.tsv | 2 + packs/zh-Hans/locales/zh-Hans/strings.tsv | 2 + packs/zh-Hant/locales/zh-Hant/strings.tsv | 2 + .../chat/infra/lxmf/lxmf_adapter.h | 2 +- .../chat/infra/lxmf/lxmf_memory.h | 96 +++++++++++ .../infra/lxmf/lxmf_propagation_runtime.h | 2 +- .../lxmf/lxmf_propagation_service_runtime.h | 4 +- .../chat/infra/lxmf/lxmf_resource_runtime.h | 2 +- .../chat/infra/lxmf/lxmf_runtime_state.h | 11 +- .../src/chat/infra/lxmf/lxmf_adapter.cpp | 161 +++++++++++------- .../infra/lxmf/lxmf_propagation_runtime.cpp | 3 +- .../lxmf/lxmf_propagation_service_runtime.cpp | 12 +- .../chat/infra/lxmf/lxmf_resource_runtime.cpp | 2 +- .../test_reticulum_runtime_state_contract.cpp | 4 +- 33 files changed, 412 insertions(+), 128 deletions(-) create mode 100644 platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_memory.h diff --git a/modules/core_chat/include/chat/infra/lxmf/lxmf_wire.h b/modules/core_chat/include/chat/infra/lxmf/lxmf_wire.h index 3df77146..972e0f2f 100644 --- a/modules/core_chat/include/chat/infra/lxmf/lxmf_wire.h +++ b/modules/core_chat/include/chat/infra/lxmf/lxmf_wire.h @@ -25,6 +25,12 @@ struct DecodedField std::vector encoded_value; }; +struct ByteSpan +{ + const uint8_t* data = nullptr; + size_t size = 0; +}; + struct DecodedEnvelope { uint8_t destination_hash[reticulum::kTruncatedHashSize] = {}; @@ -241,6 +247,10 @@ bool encodePropagationBatch(double remote_timebase, const std::vector>& messages, uint8_t* out_payload, size_t* inout_len); +bool encodePropagationBatch(double remote_timebase, + const std::vector& messages, + uint8_t* out_payload, + size_t* inout_len); bool decodePropagationBatch(const uint8_t* data, size_t len, DecodedPropagationBatch* out_batch); @@ -280,6 +290,9 @@ bool encodePropagationIdListPayload(const std::vector>& ids bool encodePropagationMessageListPayload(const std::vector>& messages, uint8_t* out_payload, size_t* inout_len); +bool encodePropagationMessageListPayload(const std::vector& messages, + uint8_t* out_payload, + size_t* inout_len); void computeMessageHash(const uint8_t destination_hash[reticulum::kTruncatedHashSize], const uint8_t source_hash[reticulum::kTruncatedHashSize], diff --git a/modules/core_chat/src/infra/lxmf/lxmf_wire.cpp b/modules/core_chat/src/infra/lxmf/lxmf_wire.cpp index 79ddb867..c5641602 100644 --- a/modules/core_chat/src/infra/lxmf/lxmf_wire.cpp +++ b/modules/core_chat/src/infra/lxmf/lxmf_wire.cpp @@ -569,6 +569,32 @@ bool appendArrayOfBins(const std::vector>& items, return true; } +bool appendArrayOfBinSpans(const std::vector& items, + uint8_t* out, + size_t out_len, + size_t& used) +{ + if (items.size() > kMaxPropagationWireItems) + { + return false; + } + if (!appendArrayHeader(static_cast(items.size()), out, out_len, used)) + { + return false; + } + + for (const auto& item : items) + { + if ((!item.data && item.size != 0U) || + !appendBin(item.data, item.size, out, out_len, used)) + { + return false; + } + } + + return true; +} + bool readArrayOfBins(Cursor& cursor, std::vector>* out_items) { if (!out_items) @@ -1465,6 +1491,28 @@ bool encodePropagationBatch(double remote_timebase, return true; } +bool encodePropagationBatch(double remote_timebase, + const std::vector& messages, + uint8_t* out_payload, + size_t* inout_len) +{ + if (!out_payload || !inout_len) + { + return false; + } + + size_t used = 0; + if (!appendArrayHeader(2, out_payload, *inout_len, used) || + !appendFloat64(remote_timebase, out_payload, *inout_len, used) || + !appendArrayOfBinSpans(messages, out_payload, *inout_len, used)) + { + return false; + } + + *inout_len = used; + return true; +} + bool decodePropagationBatch(const uint8_t* data, size_t len, DecodedPropagationBatch* out_batch) { @@ -1838,6 +1886,25 @@ bool encodePropagationMessageListPayload(const std::vector> return encodePropagationIdListPayload(messages, out_payload, inout_len); } +bool encodePropagationMessageListPayload(const std::vector& messages, + uint8_t* out_payload, + size_t* inout_len) +{ + if (!out_payload || !inout_len) + { + return false; + } + + size_t used = 0; + if (!appendArrayOfBinSpans(messages, out_payload, *inout_len, used)) + { + return false; + } + + *inout_len = used; + return true; +} + void computeMessageHash(const uint8_t destination_hash[reticulum::kTruncatedHashSize], const uint8_t source_hash[reticulum::kTruncatedHashSize], const uint8_t* packed_payload, diff --git a/modules/ui_shared/include/ui/screens/chat/chat_conversation_components.h b/modules/ui_shared/include/ui/screens/chat/chat_conversation_components.h index 12e07a14..28c16355 100644 --- a/modules/ui_shared/include/ui/screens/chat/chat_conversation_components.h +++ b/modules/ui_shared/include/ui/screens/chat/chat_conversation_components.h @@ -182,7 +182,7 @@ class ChatConversationScreen lv_obj_t* source_label = nullptr; lv_obj_t* text_label = nullptr; // inside bubble lv_obj_t* time_label = nullptr; // inside meta row - lv_obj_t* status_label = nullptr; // reserved (not used) + lv_obj_t* status_label = nullptr; // inside meta row std::unique_ptr retry_ctx; bool retry_enabled = false; }; diff --git a/modules/ui_shared/include/ui/screens/chat/chat_conversation_layout.h b/modules/ui_shared/include/ui/screens/chat/chat_conversation_layout.h index 4d5ff472..5b205102 100644 --- a/modules/ui_shared/include/ui/screens/chat/chat_conversation_layout.h +++ b/modules/ui_shared/include/ui/screens/chat/chat_conversation_layout.h @@ -38,9 +38,6 @@ lv_obj_t* create_bubble_text(lv_obj_t* bubble_parent); // Create bubble time label lv_obj_t* create_bubble_time(lv_obj_t* bubble_parent); -// Create bubble status label -lv_obj_t* create_bubble_status(lv_obj_t* bubble_parent); - // Layout-only helpers to align message row left/right void align_message_row(lv_obj_t* row, bool is_self); diff --git a/modules/ui_shared/include/ui/screens/chat/chat_conversation_styles.h b/modules/ui_shared/include/ui/screens/chat/chat_conversation_styles.h index 6f6b355b..0b3d3378 100644 --- a/modules/ui_shared/include/ui/screens/chat/chat_conversation_styles.h +++ b/modules/ui_shared/include/ui/screens/chat/chat_conversation_styles.h @@ -21,6 +21,5 @@ void apply_message_row(lv_obj_t* row); void apply_bubble(lv_obj_t* bubble, bool is_self, bool source_unverified = false); void apply_bubble_text(lv_obj_t* label); void apply_bubble_time(lv_obj_t* label); -void apply_bubble_status(lv_obj_t* label); } // namespace chat::ui::conversation::styles diff --git a/modules/ui_shared/src/ui/app_runtime.cpp b/modules/ui_shared/src/ui/app_runtime.cpp index 29f5e090..b649f791 100644 --- a/modules/ui_shared/src/ui/app_runtime.cpp +++ b/modules/ui_shared/src/ui/app_runtime.cpp @@ -478,6 +478,10 @@ bool ui_present_interruption_app(AppScreen* app, lv_obj_t* parent) s_interruption_app = app; ui_set_overlay_active(true); ui::menu_layout::setMenuVisible(false); + if (main_screen != nullptr) + { + lv_tileview_set_tile_by_index(main_screen, 0, 1, LV_ANIM_OFF); + } ui_switch_to_app(app, parent); return s_active_app == app; } diff --git a/modules/ui_shared/src/ui/screens/chat/chat_conversation_components.cpp b/modules/ui_shared/src/ui/screens/chat/chat_conversation_components.cpp index 0f3e36be..fe626edc 100644 --- a/modules/ui_shared/src/ui/screens/chat/chat_conversation_components.cpp +++ b/modules/ui_shared/src/ui/screens/chat/chat_conversation_components.cpp @@ -274,6 +274,82 @@ bool model_fits_location_overlay(lv_obj_t* viewport_root, return ::ui::chat::MessageDeliveryState::Unknown; } +const char* delivery_status_text_key(::ui::chat::MessageDeliveryState delivery) +{ + switch (delivery) + { + case ::ui::chat::MessageDeliveryState::Queued: + return "Queued"; + case ::ui::chat::MessageDeliveryState::Sending: + case ::ui::chat::MessageDeliveryState::Sent: + return "Sending..."; + case ::ui::chat::MessageDeliveryState::Delivered: + return "Delivered"; + case ::ui::chat::MessageDeliveryState::Failed: + return "Failed"; + case ::ui::chat::MessageDeliveryState::Draft: + case ::ui::chat::MessageDeliveryState::Received: + case ::ui::chat::MessageDeliveryState::Unknown: + return nullptr; + } + return nullptr; +} + +lv_color_t delivery_status_chip_color(::ui::chat::MessageDeliveryState delivery) +{ + switch (delivery) + { + case ::ui::chat::MessageDeliveryState::Queued: + return lv_color_hex(0xF4E2B0); + case ::ui::chat::MessageDeliveryState::Sending: + case ::ui::chat::MessageDeliveryState::Sent: + return lv_color_hex(0xCFE4FF); + case ::ui::chat::MessageDeliveryState::Delivered: + return lv_color_hex(0xD4F0D2); + case ::ui::chat::MessageDeliveryState::Failed: + return lv_color_hex(0xF1B8AA); + case ::ui::chat::MessageDeliveryState::Draft: + case ::ui::chat::MessageDeliveryState::Received: + case ::ui::chat::MessageDeliveryState::Unknown: + break; + } + return lv_color_hex(0xE8E0D8); +} + +void update_delivery_status_chip(lv_obj_t* status_label, + ::ui::chat::MessageDeliveryState delivery) +{ + if (!status_label) + { + return; + } + + lv_obj_t* chip = lv_obj_get_parent(status_label); + const char* text_key = delivery_status_text_key(delivery); + if (!text_key || text_key[0] == '\0') + { + lv_label_set_text(status_label, ""); + if (chip) + { + lv_obj_add_flag(chip, LV_OBJ_FLAG_HIDDEN); + } + return; + } + + if (chip) + { + lv_obj_set_style_bg_color(chip, + delivery_status_chip_color(delivery), + LV_PART_MAIN); + lv_obj_clear_flag(chip, LV_OBJ_FLAG_HIDDEN); + } + ::ui::i18n::set_label_text(status_label, text_key); + ::ui::fonts::apply_localized_font( + status_label, + lv_label_get_text(status_label), + ::ui::page_profile::resolve_caption_font()); +} + bool message_ref_matches_id(const ::ui::chat::MessageRef& ref, chat::MessageId msg_id) { @@ -683,20 +759,13 @@ bool ChatConversationScreen::updateMessageStatus(const chat::MessageId msg_id, return true; } + update_delivery_status_chip(item.status_label, item.delivery); if (status == MessageStatus::Failed) { - ::ui::i18n::set_label_text(item.status_label, "Failed"); - ::ui::fonts::apply_localized_font( - item.status_label, lv_label_get_text(item.status_label), ::ui::fonts::ui_chrome_font()); - lv_obj_clear_flag(item.status_label, LV_OBJ_FLAG_HIDDEN); enableRetryAction(item); } else { - lv_label_set_text(item.status_label, ""); - ::ui::fonts::apply_localized_font( - item.status_label, lv_label_get_text(item.status_label), ::ui::fonts::ui_chrome_font()); - lv_obj_add_flag(item.status_label, LV_OBJ_FLAG_HIDDEN); disableRetryAction(item); } return true; @@ -1283,6 +1352,14 @@ void ChatConversationScreen::createMessageItem(const ::ui::chat::MessageRow& row } item.time_label = create_meta_chip(item.meta_row, time_buf, lv_color_hex(0xD4F0D2), max_meta_w); + if (is_self) + { + item.status_label = create_meta_chip(item.meta_row, + "Sending...", + delivery_status_chip_color(row.delivery), + max_meta_w); + update_delivery_status_chip(item.status_label, row.delivery); + } item.text_label = chat::ui::layout::create_bubble_text(bubble); chat::ui::conversation::styles::apply_bubble_text(item.text_label); @@ -1331,23 +1408,10 @@ void ChatConversationScreen::createMessageItem(const ::ui::chat::MessageRow& row lv_obj_set_width(item.text_label, LV_SIZE_CONTENT); } - item.status_label = chat::ui::layout::create_bubble_status(bubble); - chat::ui::conversation::styles::apply_bubble_status(item.status_label); if (row.delivery == ::ui::chat::MessageDeliveryState::Failed) { - ::ui::i18n::set_label_text(item.status_label, "Failed"); - ::ui::fonts::apply_localized_font( - item.status_label, lv_label_get_text(item.status_label), ::ui::fonts::ui_chrome_font()); - lv_obj_clear_flag(item.status_label, LV_OBJ_FLAG_HIDDEN); enableRetryAction(item); } - else - { - lv_label_set_text(item.status_label, ""); - ::ui::fonts::apply_localized_font( - item.status_label, lv_label_get_text(item.status_label), ::ui::fonts::ui_chrome_font()); - lv_obj_add_flag(item.status_label, LV_OBJ_FLAG_HIDDEN); - } // Align row based on sender (same behavior) chat::ui::layout::align_message_row(item.container, is_self); diff --git a/modules/ui_shared/src/ui/screens/chat/chat_conversation_layout.cpp b/modules/ui_shared/src/ui/screens/chat/chat_conversation_layout.cpp index 55ae70b4..fbe6ce3d 100644 --- a/modules/ui_shared/src/ui/screens/chat/chat_conversation_layout.cpp +++ b/modules/ui_shared/src/ui/screens/chat/chat_conversation_layout.cpp @@ -206,13 +206,6 @@ lv_obj_t* create_bubble_time(lv_obj_t* bubble_parent) return label; } -lv_obj_t* create_bubble_status(lv_obj_t* bubble_parent) -{ - lv_obj_t* label = lv_label_create(bubble_parent); - lv_obj_set_width(label, LV_SIZE_CONTENT); - return label; -} - void align_message_row(lv_obj_t* row, bool is_self) { // Match original behavior: diff --git a/modules/ui_shared/src/ui/screens/chat/chat_conversation_styles.cpp b/modules/ui_shared/src/ui/screens/chat/chat_conversation_styles.cpp index b825426e..e19826a4 100644 --- a/modules/ui_shared/src/ui/screens/chat/chat_conversation_styles.cpp +++ b/modules/ui_shared/src/ui/screens/chat/chat_conversation_styles.cpp @@ -24,7 +24,6 @@ static lv_style_t s_bubble_other; static lv_style_t s_bubble_unverified; static lv_style_t s_bubble_text; static lv_style_t s_bubble_time; -static lv_style_t s_bubble_status; static constexpr lv_coord_t kPadX = 8; static constexpr lv_coord_t kPadY = 6; @@ -138,11 +137,6 @@ void init_once() lv_style_set_text_color(&s_bubble_time, lv_color_hex(0x6A5646)); lv_style_set_text_align(&s_bubble_time, LV_TEXT_ALIGN_LEFT); lv_style_set_text_font(&s_bubble_time, meta_font); - - lv_style_init(&s_bubble_status); - lv_style_set_text_color(&s_bubble_status, lv_color_hex(0xCC0000)); - lv_style_set_text_align(&s_bubble_status, LV_TEXT_ALIGN_LEFT); - lv_style_set_text_font(&s_bubble_status, meta_font); } void apply_root(lv_obj_t* root) @@ -204,12 +198,6 @@ void apply_bubble_time(lv_obj_t* label) lv_obj_add_style(label, &s_bubble_time, 0); } -void apply_bubble_status(lv_obj_t* label) -{ - init_once(); - lv_obj_add_style(label, &s_bubble_status, 0); -} - } // namespace chat::ui::conversation::styles #endif diff --git a/packs/ar/locales/ar/strings.tsv b/packs/ar/locales/ar/strings.tsv index d2df7d7a..c89c8308 100644 --- a/packs/ar/locales/ar/strings.tsv +++ b/packs/ar/locales/ar/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast إرسال بث الهوية Send ID Local إرسال هوية محلي Sending... جار الإرسال... Sent تم الإرسال +Queued في قائمة الانتظار +Delivered تم التسليم Settings الإعدادات Setting إعداد Share Position Marker مشاركة علامة الموقع diff --git a/packs/europe-cyrillic-ext/locales/ru/strings.tsv b/packs/europe-cyrillic-ext/locales/ru/strings.tsv index 5c08720e..b0fa63a1 100644 --- a/packs/europe-cyrillic-ext/locales/ru/strings.tsv +++ b/packs/europe-cyrillic-ext/locales/ru/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast Отправить ID трансляцию Send ID Local Отправить ID локальный Sending... Отправка... Sent Отправлено +Queued В очереди +Delivered Доставлено Settings Настройки Setting Настройка Share Position Marker Маркер позиции акции diff --git a/packs/europe-latin-ext/locales/de/strings.tsv b/packs/europe-latin-ext/locales/de/strings.tsv index 56dca70a..64ed6740 100644 --- a/packs/europe-latin-ext/locales/de/strings.tsv +++ b/packs/europe-latin-ext/locales/de/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast ID Broadcast senden Send ID Local Senden Sie ID Local Sending... Wird gesendet... Sent Gesendet +Queued In Warteschlange +Delivered Zugestellt Settings Einstellungen Setting Einstellung Share Position Marker Positionsmarkierung teilen diff --git a/packs/europe-latin-ext/locales/es/strings.tsv b/packs/europe-latin-ext/locales/es/strings.tsv index 127b1ddd..c96491a1 100644 --- a/packs/europe-latin-ext/locales/es/strings.tsv +++ b/packs/europe-latin-ext/locales/es/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast Enviar ID Difusión Send ID Local Enviar ID Local Sending... Enviando... Sent Enviado +Queued En cola +Delivered Entregado Settings Configuración Setting Configuración Share Position Marker Compartir marcador de posición diff --git a/packs/europe-latin-ext/locales/fr/strings.tsv b/packs/europe-latin-ext/locales/fr/strings.tsv index 90f9ab35..f7251940 100644 --- a/packs/europe-latin-ext/locales/fr/strings.tsv +++ b/packs/europe-latin-ext/locales/fr/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast Envoyer la diffusion ID Send ID Local Envoyer ID Local Sending... Envoi en cours... Sent Envoyé +Queued En file +Delivered Livré Settings Paramètres Setting Paramètre Share Position Marker Partager le marqueur de position diff --git a/packs/europe-latin-ext/locales/it/strings.tsv b/packs/europe-latin-ext/locales/it/strings.tsv index 5bc54018..5f1aeb0a 100644 --- a/packs/europe-latin-ext/locales/it/strings.tsv +++ b/packs/europe-latin-ext/locales/it/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast Invia ID Trasmetti Send ID Local Invia ID Locale Sending... Invio... Sent Inviato +Queued In coda +Delivered Consegnato Settings Impostazioni Setting Impostazione Share Position Marker Condividi indicatore di posizione diff --git a/packs/europe-latin-ext/locales/nl/strings.tsv b/packs/europe-latin-ext/locales/nl/strings.tsv index 2240633c..d4c372e8 100644 --- a/packs/europe-latin-ext/locales/nl/strings.tsv +++ b/packs/europe-latin-ext/locales/nl/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast Verzend ID uitzending Send ID Local Verzend ID Lokaal Sending... Verzenden... Sent Verzonden +Queued In wachtrij +Delivered Afgeleverd Settings Instellingen Setting Instelling Share Position Marker Aandeelpositiemarkering diff --git a/packs/europe-latin-ext/locales/pl/strings.tsv b/packs/europe-latin-ext/locales/pl/strings.tsv index 55319973..b2c38b2d 100644 --- a/packs/europe-latin-ext/locales/pl/strings.tsv +++ b/packs/europe-latin-ext/locales/pl/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast Wyślij ID Transmisja Send ID Local Wyślij ID lokalnie Sending... Wysyłanie... Sent Wysłano +Queued W kolejce +Delivered Dostarczono Settings Ustawienia Setting Ustawienie Share Position Marker Udostępnij znacznik pozycji diff --git a/packs/europe-latin-ext/locales/pt-PT/strings.tsv b/packs/europe-latin-ext/locales/pt-PT/strings.tsv index cbab1791..aa847880 100644 --- a/packs/europe-latin-ext/locales/pt-PT/strings.tsv +++ b/packs/europe-latin-ext/locales/pt-PT/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast Enviar ID Transmissão Send ID Local Enviar ID Local Sending... Enviando... Sent Enviado +Queued Na fila +Delivered Entregue Settings Configurações Setting Configuração Share Position Marker Marcador de posição de compartilhamento diff --git a/packs/ja/locales/ja/strings.tsv b/packs/ja/locales/ja/strings.tsv index 6cb40fbe..edf5e660 100644 --- a/packs/ja/locales/ja/strings.tsv +++ b/packs/ja/locales/ja/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast ID ブロードキャストを送信 Send ID Local ID をローカルに送信 Sending... 送信中... Sent 送信済み +Queued キュー済み +Delivered 配信済み Settings 設定 Setting 設定 Share Position Marker シェアポジションマーカー diff --git a/packs/ko/locales/ko/strings.tsv b/packs/ko/locales/ko/strings.tsv index c80e1e05..49cdb55a 100644 --- a/packs/ko/locales/ko/strings.tsv +++ b/packs/ko/locales/ko/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast ID 브로드캐스트 보내기 Send ID Local ID 로컬 보내기 Sending... 보내는 중... Sent 보냄 +Queued 대기 중 +Delivered 전달됨 Settings 설정 Setting 설정 Share Position Marker 위치 마커 공유 diff --git a/packs/zh-Hans/locales/zh-Hans/strings.tsv b/packs/zh-Hans/locales/zh-Hans/strings.tsv index c7f82382..0b36b696 100644 --- a/packs/zh-Hans/locales/zh-Hans/strings.tsv +++ b/packs/zh-Hans/locales/zh-Hans/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast 广播发送 ID Send ID Local 本地发送 ID Sending... 发送中... Sent 已发送 +Queued 已排队 +Delivered 已送达 Settings 设置 Setting 设置 Share Position Marker 分享位置标记 diff --git a/packs/zh-Hant/locales/zh-Hant/strings.tsv b/packs/zh-Hant/locales/zh-Hant/strings.tsv index bb6d830c..e03382f9 100644 --- a/packs/zh-Hant/locales/zh-Hant/strings.tsv +++ b/packs/zh-Hant/locales/zh-Hant/strings.tsv @@ -248,6 +248,8 @@ Send ID Broadcast 廣播傳送 ID Send ID Local 本地傳送 ID Sending... 傳送中... Sent 已傳送 +Queued 已排隊 +Delivered 已送達 Settings 設定 Setting 設定 Share Position Marker 分享位置標記 diff --git a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_adapter.h b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_adapter.h index 92c0fc3a..93845613 100644 --- a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_adapter.h +++ b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_adapter.h @@ -423,7 +423,7 @@ class LxmfAdapter : public IMeshAdapter uint8_t* out_payload, size_t* inout_len) const; bool decryptLinkPayload(const LinkSession& session, const uint8_t* payload, size_t payload_len, - std::vector* out_plaintext) const; + runtime::ResourcePayloadBuffer* out_plaintext) const; bool sendLinkPacket(LinkSession& session, reticulum::PacketType packet_type, reticulum::PacketContext context, diff --git a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_memory.h b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_memory.h new file mode 100644 index 00000000..8807947c --- /dev/null +++ b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_memory.h @@ -0,0 +1,96 @@ +/** + * @file lxmf_memory.h + * @brief Memory ownership helpers for embedded LXMF runtime buffers. + */ + +#pragma once + +#include +#include +#include +#include +#include + +#if defined(ESP_PLATFORM) +#include +#else +#include +#endif + +namespace chat::lxmf::runtime +{ + +template +class PsramAllocator +{ + public: + using value_type = T; + + PsramAllocator() noexcept = default; + + template + PsramAllocator(const PsramAllocator&) noexcept + { + } + + T* allocate(std::size_t count) + { + if (count > std::numeric_limits::max() / sizeof(T)) + { + throw std::bad_alloc(); + } + + const std::size_t bytes = count * sizeof(T); + if (bytes == 0) + { + return nullptr; + } + +#if defined(ESP_PLATFORM) + void* ptr = heap_caps_malloc(bytes, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); +#else + void* ptr = std::malloc(bytes); +#endif + if (!ptr) + { + throw std::bad_alloc(); + } + return static_cast(ptr); + } + + void deallocate(T* ptr, std::size_t) noexcept + { + if (!ptr) + { + return; + } +#if defined(ESP_PLATFORM) + heap_caps_free(ptr); +#else + std::free(ptr); +#endif + } + + template + struct rebind + { + using other = PsramAllocator; + }; +}; + +template +bool operator==(const PsramAllocator&, const PsramAllocator&) noexcept +{ + return true; +} + +template +bool operator!=(const PsramAllocator&, const PsramAllocator&) noexcept +{ + return false; +} + +using ResourcePayloadBuffer = std::vector>; +using ResourcePayloadList = std::vector; + +} // namespace chat::lxmf::runtime diff --git a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_runtime.h b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_runtime.h index 406c4ff6..57a7a5cf 100644 --- a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_runtime.h +++ b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_runtime.h @@ -26,7 +26,7 @@ struct PropagationRuntimeLimits struct PropagationMessageSelection { - std::vector> messages; + std::vector messages; uint32_t served_count = 0; }; diff --git a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_service_runtime.h b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_service_runtime.h index 4fee946f..cfb1b93c 100644 --- a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_service_runtime.h +++ b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_service_runtime.h @@ -42,7 +42,7 @@ struct PropagationServiceResponse bool send_response = false; bool response_data_is_nil = false; bool offer_validated = false; - std::vector packed_response; + ResourcePayloadBuffer packed_response; }; enum class PropagationMessageAction : uint8_t @@ -69,7 +69,7 @@ struct PropagationMessageAcceptance PropagationMessageAction action = PropagationMessageAction::Rejected; uint8_t transient_id[reticulum::kFullHashSize] = {}; uint8_t destination_hash[reticulum::kTruncatedHashSize] = {}; - std::vector local_delivery_payload; + ResourcePayloadBuffer local_delivery_payload; }; struct PropagationBatchContext diff --git a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_resource_runtime.h b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_resource_runtime.h index 297c0910..755e0c95 100644 --- a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_resource_runtime.h +++ b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_resource_runtime.h @@ -107,7 +107,7 @@ bool recordResourcePart(LinkResourceTransfer& resource, ResourceAssemblyResult appendResourceAssemblySegment( LinkSession& session, LinkResourceTransfer& resource, - std::vector& payload_data, + ResourcePayloadBuffer& payload_data, uint32_t now_ms); void markResourceComplete(LinkResourceTransfer& resource, uint32_t now_ms); diff --git a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_runtime_state.h b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_runtime_state.h index b2baccc9..cb460f21 100644 --- a/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_runtime_state.h +++ b/platform/esp/arduino_common/include/platform/esp/arduino_common/chat/infra/lxmf/lxmf_runtime_state.h @@ -9,6 +9,7 @@ #include "chat/infra/lxmf/lxmf_wire.h" #include "chat/infra/reticulum/lxst_call_state_machine.h" #include "platform/esp/arduino_common/chat/infra/lxmf/lxmf_identity.h" +#include "platform/esp/arduino_common/chat/infra/lxmf/lxmf_memory.h" #include #include @@ -142,7 +143,7 @@ struct LinkPendingRequest struct DeferredLinkPayload { - std::vector payload; + ResourcePayloadBuffer payload; std::vector request_id; uint32_t message_id = 0; uint8_t resource_flags = 0; @@ -165,7 +166,7 @@ struct LinkResourceTransfer std::vector hashmap; std::vector> map_hashes; std::vector map_hash_known; - std::vector> parts; + ResourcePayloadList parts; std::vector received_bitmap; uint32_t data_size = 0; uint32_t transfer_size = 0; @@ -194,7 +195,7 @@ struct LinkResourceAssembly { uint8_t original_hash[reticulum::kFullHashSize] = {}; std::vector request_id; - std::vector payload; + ResourcePayloadBuffer payload; uint32_t next_segment_index = 1; uint32_t total_segments = 1; uint32_t last_activity_ms = 0; @@ -250,7 +251,7 @@ struct PropagationEntry { uint8_t transient_id[reticulum::kFullHashSize] = {}; uint8_t destination_hash[reticulum::kTruncatedHashSize] = {}; - std::vector lxmf_data; + ResourcePayloadBuffer lxmf_data; uint32_t created_s = 0; uint32_t served_count = 0; }; @@ -278,7 +279,7 @@ struct PendingPropagationUpload uint8_t destination_hash[reticulum::kTruncatedHashSize] = {}; uint8_t message_hash[reticulum::kFullHashSize] = {}; uint8_t transient_id[reticulum::kFullHashSize] = {}; - std::vector transient_data; + ResourcePayloadBuffer transient_data; uint32_t created_ms = 0; uint32_t message_id = 0; uint8_t stamp_cost = 0; diff --git a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_adapter.cpp b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_adapter.cpp index 1745a50b..408a8a18 100644 --- a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_adapter.cpp +++ b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_adapter.cpp @@ -18,6 +18,7 @@ #include "platform/esp/arduino_common/chat/infra/lxmf/lxmf_propagation_service_runtime.h" #include "platform/esp/arduino_common/chat/infra/lxmf/lxmf_resource_runtime.h" #include "platform/esp/arduino_common/chat/infra/lxmf/lxmf_transport_runtime.h" +#include "platform/esp/common/mbedtls_sha256_compat.h" #include "platform/esp/common/reticulum_crypto_compat.h" #include "platform/esp/common/reticulum_runtime_compat.h" #include "platform/ui/gps_runtime.h" @@ -47,6 +48,7 @@ namespace rtdir = ::platform::ui::reticulum_directory; namespace rtnet = ::platform::ui::reticulum_network_config; namespace rtpage = ::platform::ui::reticulum_page; namespace screen_runtime = ::platform::ui::screen; +namespace sha_compat = ::platform::esp::common::crypto; using PageFailureKind = rtpage::RequestProgress::FailureKind; constexpr size_t kMaxPacketLen = reticulum::kReticulumMtu; @@ -636,6 +638,40 @@ bool hashesEqual(const uint8_t* a, const uint8_t* b, size_t len) return true; } +bool fullHashJoined(const uint8_t* first, + size_t first_len, + const uint8_t* second, + size_t second_len, + uint8_t out_hash[reticulum::kFullHashSize]) +{ + if (!out_hash || (!first && first_len != 0) || (!second && second_len != 0)) + { + return false; + } + + mbedtls_sha256_context sha; + mbedtls_sha256_init(&sha); + bool ok = sha_compat::sha256_starts(&sha, 0) == 0; + if (ok && first_len != 0) + { + ok = sha_compat::sha256_update(&sha, first, first_len) == 0; + } + if (ok && second_len != 0) + { + ok = sha_compat::sha256_update(&sha, second, second_len) == 0; + } + if (ok) + { + ok = sha_compat::sha256_finish(&sha, out_hash) == 0; + } + mbedtls_sha256_free(&sha); + if (!ok) + { + std::memset(out_hash, 0, reticulum::kFullHashSize); + } + return ok; +} + bool unpackRnsLxmfEnvelope(const uint8_t expected_destination_hash[reticulum::kTruncatedHashSize], const uint8_t* payload, size_t payload_len, DecodedEnvelope* out_envelope, @@ -891,7 +927,7 @@ void bzip2PsramFree(void*, void* address) bool decompressBzip2Payload(const uint8_t* compressed, size_t compressed_len, size_t expected_size, - std::vector* out_payload, + runtime::ResourcePayloadBuffer* out_payload, int* out_status) { if (out_status) @@ -905,7 +941,7 @@ bool decompressBzip2Payload(const uint8_t* compressed, return false; } - std::vector output(expected_size, 0); + runtime::ResourcePayloadBuffer output(expected_size, 0); bz_stream stream{}; stream.bzalloc = bzip2PsramAlloc; stream.bzfree = bzip2PsramFree; @@ -1515,9 +1551,10 @@ bool LxmfAdapter::queueReadyPropagationUpload( return false; } - std::vector> messages; - messages.push_back(upload.transient_data); - std::vector batch(upload.transient_data.size() + 32U, 0); + std::vector messages; + messages.push_back(ByteSpan{upload.transient_data.data(), + upload.transient_data.size()}); + runtime::ResourcePayloadBuffer batch(upload.transient_data.size() + 32U, 0); size_t batch_len = batch.size(); if (!encodePropagationBatch(static_cast(currentTimestampSeconds()), messages, @@ -5394,7 +5431,7 @@ bool LxmfAdapter::handleLinkDataPacket(LinkSession& session, return false; } - std::vector plaintext; + runtime::ResourcePayloadBuffer plaintext; const uint8_t context = packet.context; const bool raw_payload = packetContextUsesRawLinkPayload(context); if (!raw_payload) @@ -6366,14 +6403,14 @@ bool LxmfAdapter::handleLinkResourcePart(LinkSession& session, saw_incoming_resource = true; uint8_t full_hash[reticulum::kFullHashSize] = {}; - std::vector hash_material(packet.payload_len + sizeof(resource.random_hash), 0); - memcpy(hash_material.data(), packet.payload, packet.payload_len); - memcpy(hash_material.data() + packet.payload_len, - resource.random_hash, - sizeof(resource.random_hash)); - reticulum::fullHash(hash_material.data(), - hash_material.size(), - full_hash); + if (!fullHashJoined(packet.payload, + packet.payload_len, + resource.random_hash, + sizeof(resource.random_hash), + full_hash)) + { + return false; + } bool complete = false; std::size_t matched_index = resource.part_count; @@ -6476,7 +6513,7 @@ bool LxmfAdapter::handleLinkResourcePart(LinkSession& session, return true; } - std::vector assembled; + runtime::ResourcePayloadBuffer assembled; assembled.reserve(resource.transfer_size); for (const auto& part : resource.parts) { @@ -6487,7 +6524,7 @@ bool LxmfAdapter::handleLinkResourcePart(LinkSession& session, assembled.resize(resource.transfer_size); } - std::vector resource_stream; + runtime::ResourcePayloadBuffer resource_stream; if (resource.encrypted) { if (!decryptLinkPayload(session, @@ -6518,7 +6555,7 @@ bool LxmfAdapter::handleLinkResourcePart(LinkSession& session, resource_stream.data() + kResourceDataPrefixLen; const size_t resource_payload_len = resource_stream.size() - kResourceDataPrefixLen; - std::vector payload_data; + runtime::ResourcePayloadBuffer payload_data; if (resource.compressed) { int bz_status = BZ_OK; @@ -6565,19 +6602,15 @@ bool LxmfAdapter::handleLinkResourcePart(LinkSession& session, return false; } - std::vector resource_hash_material(payload_data.size() + sizeof(resource.random_hash), 0); - if (!payload_data.empty()) - { - memcpy(resource_hash_material.data(), payload_data.data(), payload_data.size()); - } - memcpy(resource_hash_material.data() + payload_data.size(), - resource.random_hash, - sizeof(resource.random_hash)); - uint8_t expected_resource_hash[reticulum::kFullHashSize] = {}; - reticulum::fullHash(resource_hash_material.data(), - resource_hash_material.size(), - expected_resource_hash); + if (!fullHashJoined(payload_data.data(), + payload_data.size(), + resource.random_hash, + sizeof(resource.random_hash), + expected_resource_hash)) + { + return false; + } if (!hashesEqual(expected_resource_hash, resource.resource_hash, reticulum::kFullHashSize)) @@ -6585,17 +6618,14 @@ bool LxmfAdapter::handleLinkResourcePart(LinkSession& session, return false; } - std::vector proof_material(payload_data.size() + reticulum::kFullHashSize, 0); - if (!payload_data.empty()) + if (!fullHashJoined(payload_data.data(), + payload_data.size(), + resource.resource_hash, + reticulum::kFullHashSize, + resource.expected_proof)) { - memcpy(proof_material.data(), payload_data.data(), payload_data.size()); + return false; } - memcpy(proof_material.data() + payload_data.size(), - resource.resource_hash, - reticulum::kFullHashSize); - reticulum::fullHash(proof_material.data(), - proof_material.size(), - resource.expected_proof); std::array proof_payload{}; memcpy(proof_payload.data(), resource.resource_hash, reticulum::kFullHashSize); @@ -8574,14 +8604,16 @@ bool LxmfAdapter::encryptLinkPayload(const LinkSession& session, bool LxmfAdapter::decryptLinkPayload(const LinkSession& session, const uint8_t* payload, size_t payload_len, - std::vector* out_plaintext) const + runtime::ResourcePayloadBuffer* out_plaintext) const { if (!payload || payload_len == 0 || !out_plaintext) { return false; } - std::vector plaintext(reticulum::paddedTokenPlaintextSize(payload_len), 0); + runtime::ResourcePayloadBuffer plaintext( + reticulum::paddedTokenPlaintextSize(payload_len), + 0); size_t plaintext_len = plaintext.size(); if (!reticulum::tokenDecrypt(session.derived_key, payload, @@ -9450,12 +9482,12 @@ bool LxmfAdapter::queueOutgoingResource(LinkSession& session, return false; } - std::vector stream(kResourceDataPrefixLen + len, 0); + runtime::ResourcePayloadBuffer stream(kResourceDataPrefixLen + len, 0); fillRandomBytes(stream.data(), kResourceDataPrefixLen); memcpy(stream.data() + kResourceDataPrefixLen, data, len); const size_t encrypted_capacity = reticulum::tokenSizeForPlaintext(stream.size()); - std::vector encrypted_stream(encrypted_capacity, 0); + runtime::ResourcePayloadBuffer encrypted_stream(encrypted_capacity, 0); size_t encrypted_len = encrypted_stream.size(); uint8_t iv[reticulum::kTokenIvSize] = {}; fillRandomBytes(iv, sizeof(iv)); @@ -9500,22 +9532,24 @@ bool LxmfAdapter::queueOutgoingResource(LinkSession& session, { fillRandomBytes(resource.random_hash, sizeof(resource.random_hash)); - std::vector hash_material(len + sizeof(resource.random_hash), 0); - memcpy(hash_material.data(), data, len); - memcpy(hash_material.data() + len, resource.random_hash, sizeof(resource.random_hash)); - reticulum::fullHash(hash_material.data(), - hash_material.size(), - resource.resource_hash); + if (!fullHashJoined(data, + len, + resource.random_hash, + sizeof(resource.random_hash), + resource.resource_hash)) + { + return false; + } memcpy(resource.original_hash, resource.resource_hash, sizeof(resource.original_hash)); - std::vector proof_material(len + reticulum::kFullHashSize, 0); - memcpy(proof_material.data(), data, len); - memcpy(proof_material.data() + len, - resource.resource_hash, - reticulum::kFullHashSize); - reticulum::fullHash(proof_material.data(), - proof_material.size(), - resource.expected_proof); + if (!fullHashJoined(data, + len, + resource.resource_hash, + reticulum::kFullHashSize, + resource.expected_proof)) + { + return false; + } resource.hashmap.clear(); std::vector> recent_hashes; @@ -9531,14 +9565,15 @@ bool LxmfAdapter::queueOutgoingResource(LinkSession& session, resource.parts[index].assign(encrypted_stream.begin() + offset, encrypted_stream.begin() + offset + chunk_len); - std::vector map_material(chunk_len + sizeof(resource.random_hash), 0); - memcpy(map_material.data(), resource.parts[index].data(), chunk_len); - memcpy(map_material.data() + chunk_len, - resource.random_hash, - sizeof(resource.random_hash)); - uint8_t full_hash[reticulum::kFullHashSize] = {}; - reticulum::fullHash(map_material.data(), map_material.size(), full_hash); + if (!fullHashJoined(resource.parts[index].data(), + chunk_len, + resource.random_hash, + sizeof(resource.random_hash), + full_hash)) + { + return false; + } std::array map_hash{}; memcpy(map_hash.data(), full_hash, map_hash.size()); diff --git a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_runtime.cpp b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_runtime.cpp index 1206e6b3..333a1ba3 100644 --- a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_runtime.cpp +++ b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_runtime.cpp @@ -571,7 +571,8 @@ PropagationMessageSelection collectPropagationMessagesForWants( break; } - selection.messages.push_back(entry->lxmf_data); + selection.messages.push_back(ByteSpan{entry->lxmf_data.data(), + entry->lxmf_data.size()}); cumulative_size = next_size; entry->served_count += 1; selection.served_count += 1; diff --git a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_service_runtime.cpp b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_service_runtime.cpp index 6a686f5b..3c4a2053 100644 --- a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_service_runtime.cpp +++ b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_propagation_service_runtime.cpp @@ -48,7 +48,7 @@ bool packUintResponse(uint32_t value, PropagationServiceResponse* out_response) return false; } - std::vector packed(8, 0); + ResourcePayloadBuffer packed(8, 0); std::size_t packed_len = packed.size(); if (!encodeMsgpackUint(value, packed.data(), &packed_len)) { @@ -68,7 +68,7 @@ bool packBoolResponse(bool value, PropagationServiceResponse* out_response) return false; } - std::vector packed(4, 0); + ResourcePayloadBuffer packed(4, 0); std::size_t packed_len = packed.size(); if (!encodeMsgpackBool(value, packed.data(), &packed_len)) { @@ -91,7 +91,7 @@ bool packIdListResponse(const std::vector>& items, const std::size_t response_capacity = 4 + (items.size() * (reticulum::kFullHashSize + 3)); - std::vector packed(response_capacity, 0); + ResourcePayloadBuffer packed(response_capacity, 0); std::size_t packed_len = packed.size(); if (!encodePropagationIdListPayload(items, packed.data(), &packed_len)) { @@ -104,7 +104,7 @@ bool packIdListResponse(const std::vector>& items, return true; } -bool packMessageListResponse(const std::vector>& items, +bool packMessageListResponse(const std::vector& items, PropagationServiceResponse* out_response) { if (!out_response) @@ -115,9 +115,9 @@ bool packMessageListResponse(const std::vector>& items, std::size_t response_capacity = 4; for (const auto& item : items) { - response_capacity += item.size() + 3; + response_capacity += item.size + 3; } - std::vector packed(response_capacity, 0); + ResourcePayloadBuffer packed(response_capacity, 0); std::size_t packed_len = packed.size(); if (!encodePropagationMessageListPayload(items, packed.data(), &packed_len)) { diff --git a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_resource_runtime.cpp b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_resource_runtime.cpp index 8143169b..5af19653 100644 --- a/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_resource_runtime.cpp +++ b/platform/esp/arduino_common/src/chat/infra/lxmf/lxmf_resource_runtime.cpp @@ -438,7 +438,7 @@ bool recordResourcePart(LinkResourceTransfer& resource, ResourceAssemblyResult appendResourceAssemblySegment( LinkSession& session, LinkResourceTransfer& resource, - std::vector& payload_data, + ResourcePayloadBuffer& payload_data, uint32_t now_ms) { if (!resource.split && resource.total_segments <= 1) diff --git a/tests/reticulum_conformance/test_reticulum_runtime_state_contract.cpp b/tests/reticulum_conformance/test_reticulum_runtime_state_contract.cpp index 04831409..265d1f32 100644 --- a/tests/reticulum_conformance/test_reticulum_runtime_state_contract.cpp +++ b/tests/reticulum_conformance/test_reticulum_runtime_state_contract.cpp @@ -562,7 +562,7 @@ int main() true, 600, 1)); - std::vector split_payload_1{0x11, 0x12}; + ResourcePayloadBuffer split_payload_1{0x11, 0x12}; assert(appendResourceAssemblySegment(resource_session, split_segment_1, split_payload_1, @@ -574,7 +574,7 @@ int main() LinkResourceTransfer split_segment_2 = split_segment_1; split_segment_2.segment_index = 2; split_segment_2.last_activity_ms = 620; - std::vector split_payload_2{0x13}; + ResourcePayloadBuffer split_payload_2{0x13}; assert(appendResourceAssemblySegment(resource_session, split_segment_2, split_payload_2,