mirror of
https://github.com/vicliu624/trail-mate.git
synced 2026-08-06 18:59:43 +00:00
Refine Reticulum payload memory and chat status UI
This commit is contained in:
@@ -25,6 +25,12 @@ struct DecodedField
|
||||
std::vector<uint8_t> 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<std::vector<uint8_t>>& messages,
|
||||
uint8_t* out_payload,
|
||||
size_t* inout_len);
|
||||
bool encodePropagationBatch(double remote_timebase,
|
||||
const std::vector<ByteSpan>& 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<std::vector<uint8_t>>& ids
|
||||
bool encodePropagationMessageListPayload(const std::vector<std::vector<uint8_t>>& messages,
|
||||
uint8_t* out_payload,
|
||||
size_t* inout_len);
|
||||
bool encodePropagationMessageListPayload(const std::vector<ByteSpan>& 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],
|
||||
|
||||
@@ -569,6 +569,32 @@ bool appendArrayOfBins(const std::vector<std::vector<uint8_t>>& items,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool appendArrayOfBinSpans(const std::vector<ByteSpan>& items,
|
||||
uint8_t* out,
|
||||
size_t out_len,
|
||||
size_t& used)
|
||||
{
|
||||
if (items.size() > kMaxPropagationWireItems)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!appendArrayHeader(static_cast<uint8_t>(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<std::vector<uint8_t>>* out_items)
|
||||
{
|
||||
if (!out_items)
|
||||
@@ -1465,6 +1491,28 @@ bool encodePropagationBatch(double remote_timebase,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool encodePropagationBatch(double remote_timebase,
|
||||
const std::vector<ByteSpan>& 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<std::vector<uint8_t>>
|
||||
return encodePropagationIdListPayload(messages, out_payload, inout_len);
|
||||
}
|
||||
|
||||
bool encodePropagationMessageListPayload(const std::vector<ByteSpan>& 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,
|
||||
|
||||
@@ -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<MessageActionContext> retry_ctx;
|
||||
bool retry_enabled = false;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -248,6 +248,8 @@ Send ID Broadcast إرسال بث الهوية
|
||||
Send ID Local إرسال هوية محلي
|
||||
Sending... جار الإرسال...
|
||||
Sent تم الإرسال
|
||||
Queued في قائمة الانتظار
|
||||
Delivered تم التسليم
|
||||
Settings الإعدادات
|
||||
Setting إعداد
|
||||
Share Position Marker مشاركة علامة الموقع
|
||||
|
||||
|
@@ -248,6 +248,8 @@ Send ID Broadcast Отправить ID трансляцию
|
||||
Send ID Local Отправить ID локальный
|
||||
Sending... Отправка...
|
||||
Sent Отправлено
|
||||
Queued В очереди
|
||||
Delivered Доставлено
|
||||
Settings Настройки
|
||||
Setting Настройка
|
||||
Share Position Marker Маркер позиции акции
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -248,6 +248,8 @@ Send ID Broadcast ID ブロードキャストを送信
|
||||
Send ID Local ID をローカルに送信
|
||||
Sending... 送信中...
|
||||
Sent 送信済み
|
||||
Queued キュー済み
|
||||
Delivered 配信済み
|
||||
Settings 設定
|
||||
Setting 設定
|
||||
Share Position Marker シェアポジションマーカー
|
||||
|
||||
|
@@ -248,6 +248,8 @@ Send ID Broadcast ID 브로드캐스트 보내기
|
||||
Send ID Local ID 로컬 보내기
|
||||
Sending... 보내는 중...
|
||||
Sent 보냄
|
||||
Queued 대기 중
|
||||
Delivered 전달됨
|
||||
Settings 설정
|
||||
Setting 설정
|
||||
Share Position Marker 위치 마커 공유
|
||||
|
||||
|
@@ -248,6 +248,8 @@ Send ID Broadcast 广播发送 ID
|
||||
Send ID Local 本地发送 ID
|
||||
Sending... 发送中...
|
||||
Sent 已发送
|
||||
Queued 已排队
|
||||
Delivered 已送达
|
||||
Settings 设置
|
||||
Setting 设置
|
||||
Share Position Marker 分享位置标记
|
||||
|
||||
|
@@ -248,6 +248,8 @@ Send ID Broadcast 廣播傳送 ID
|
||||
Send ID Local 本地傳送 ID
|
||||
Sending... 傳送中...
|
||||
Sent 已傳送
|
||||
Queued 已排隊
|
||||
Delivered 已送達
|
||||
Settings 設定
|
||||
Setting 設定
|
||||
Share Position Marker 分享位置標記
|
||||
|
||||
|
+1
-1
@@ -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<uint8_t>* out_plaintext) const;
|
||||
runtime::ResourcePayloadBuffer* out_plaintext) const;
|
||||
bool sendLinkPacket(LinkSession& session,
|
||||
reticulum::PacketType packet_type,
|
||||
reticulum::PacketContext context,
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file lxmf_memory.h
|
||||
* @brief Memory ownership helpers for embedded LXMF runtime buffers.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
#if defined(ESP_PLATFORM)
|
||||
#include <esp_heap_caps.h>
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
namespace chat::lxmf::runtime
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class PsramAllocator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
PsramAllocator() noexcept = default;
|
||||
|
||||
template <typename U>
|
||||
PsramAllocator(const PsramAllocator<U>&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
T* allocate(std::size_t count)
|
||||
{
|
||||
if (count > std::numeric_limits<std::size_t>::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<T*>(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 <typename U>
|
||||
struct rebind
|
||||
{
|
||||
using other = PsramAllocator<U>;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator==(const PsramAllocator<T>&, const PsramAllocator<U>&) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool operator!=(const PsramAllocator<T>&, const PsramAllocator<U>&) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using ResourcePayloadBuffer = std::vector<uint8_t, PsramAllocator<uint8_t>>;
|
||||
using ResourcePayloadList = std::vector<ResourcePayloadBuffer>;
|
||||
|
||||
} // namespace chat::lxmf::runtime
|
||||
+1
-1
@@ -26,7 +26,7 @@ struct PropagationRuntimeLimits
|
||||
|
||||
struct PropagationMessageSelection
|
||||
{
|
||||
std::vector<std::vector<uint8_t>> messages;
|
||||
std::vector<ByteSpan> messages;
|
||||
uint32_t served_count = 0;
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ struct PropagationServiceResponse
|
||||
bool send_response = false;
|
||||
bool response_data_is_nil = false;
|
||||
bool offer_validated = false;
|
||||
std::vector<uint8_t> 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<uint8_t> local_delivery_payload;
|
||||
ResourcePayloadBuffer local_delivery_payload;
|
||||
};
|
||||
|
||||
struct PropagationBatchContext
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ bool recordResourcePart(LinkResourceTransfer& resource,
|
||||
ResourceAssemblyResult appendResourceAssemblySegment(
|
||||
LinkSession& session,
|
||||
LinkResourceTransfer& resource,
|
||||
std::vector<uint8_t>& payload_data,
|
||||
ResourcePayloadBuffer& payload_data,
|
||||
uint32_t now_ms);
|
||||
|
||||
void markResourceComplete(LinkResourceTransfer& resource, uint32_t now_ms);
|
||||
|
||||
+6
-5
@@ -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 <array>
|
||||
#include <cstddef>
|
||||
@@ -142,7 +143,7 @@ struct LinkPendingRequest
|
||||
|
||||
struct DeferredLinkPayload
|
||||
{
|
||||
std::vector<uint8_t> payload;
|
||||
ResourcePayloadBuffer payload;
|
||||
std::vector<uint8_t> request_id;
|
||||
uint32_t message_id = 0;
|
||||
uint8_t resource_flags = 0;
|
||||
@@ -165,7 +166,7 @@ struct LinkResourceTransfer
|
||||
std::vector<uint8_t> hashmap;
|
||||
std::vector<std::array<uint8_t, 4>> map_hashes;
|
||||
std::vector<uint8_t> map_hash_known;
|
||||
std::vector<std::vector<uint8_t>> parts;
|
||||
ResourcePayloadList parts;
|
||||
std::vector<uint8_t> 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<uint8_t> request_id;
|
||||
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> transient_data;
|
||||
ResourcePayloadBuffer transient_data;
|
||||
uint32_t created_ms = 0;
|
||||
uint32_t message_id = 0;
|
||||
uint8_t stamp_cost = 0;
|
||||
|
||||
@@ -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<uint8_t>* 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<uint8_t> 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<std::vector<uint8_t>> messages;
|
||||
messages.push_back(upload.transient_data);
|
||||
std::vector<uint8_t> batch(upload.transient_data.size() + 32U, 0);
|
||||
std::vector<ByteSpan> 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<double>(currentTimestampSeconds()),
|
||||
messages,
|
||||
@@ -5394,7 +5431,7 @@ bool LxmfAdapter::handleLinkDataPacket(LinkSession& session,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t, reticulum::kFullHashSize * 2> 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<uint8_t>* out_plaintext) const
|
||||
runtime::ResourcePayloadBuffer* out_plaintext) const
|
||||
{
|
||||
if (!payload || payload_len == 0 || !out_plaintext)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<std::array<uint8_t, kResourceMapHashLen>> 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<uint8_t> 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<uint8_t, kResourceMapHashLen> map_hash{};
|
||||
memcpy(map_hash.data(), full_hash, map_hash.size());
|
||||
|
||||
@@ -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;
|
||||
|
||||
+6
-6
@@ -48,7 +48,7 @@ bool packUintResponse(uint32_t value, PropagationServiceResponse* out_response)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> 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<uint8_t> 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<std::vector<uint8_t>>& items,
|
||||
|
||||
const std::size_t response_capacity =
|
||||
4 + (items.size() * (reticulum::kFullHashSize + 3));
|
||||
std::vector<uint8_t> 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<std::vector<uint8_t>>& items,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool packMessageListResponse(const std::vector<std::vector<uint8_t>>& items,
|
||||
bool packMessageListResponse(const std::vector<ByteSpan>& items,
|
||||
PropagationServiceResponse* out_response)
|
||||
{
|
||||
if (!out_response)
|
||||
@@ -115,9 +115,9 @@ bool packMessageListResponse(const std::vector<std::vector<uint8_t>>& items,
|
||||
std::size_t response_capacity = 4;
|
||||
for (const auto& item : items)
|
||||
{
|
||||
response_capacity += item.size() + 3;
|
||||
response_capacity += item.size + 3;
|
||||
}
|
||||
std::vector<uint8_t> packed(response_capacity, 0);
|
||||
ResourcePayloadBuffer packed(response_capacity, 0);
|
||||
std::size_t packed_len = packed.size();
|
||||
if (!encodePropagationMessageListPayload(items, packed.data(), &packed_len))
|
||||
{
|
||||
|
||||
@@ -438,7 +438,7 @@ bool recordResourcePart(LinkResourceTransfer& resource,
|
||||
ResourceAssemblyResult appendResourceAssemblySegment(
|
||||
LinkSession& session,
|
||||
LinkResourceTransfer& resource,
|
||||
std::vector<uint8_t>& payload_data,
|
||||
ResourcePayloadBuffer& payload_data,
|
||||
uint32_t now_ms)
|
||||
{
|
||||
if (!resource.split && resource.total_segments <= 1)
|
||||
|
||||
@@ -562,7 +562,7 @@ int main()
|
||||
true,
|
||||
600,
|
||||
1));
|
||||
std::vector<uint8_t> 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<uint8_t> split_payload_2{0x13};
|
||||
ResourcePayloadBuffer split_payload_2{0x13};
|
||||
assert(appendResourceAssemblySegment(resource_session,
|
||||
split_segment_2,
|
||||
split_payload_2,
|
||||
|
||||
Reference in New Issue
Block a user