Skip to content

Commit df1f6e3

Browse files
updates
1 parent ded7475 commit df1f6e3

File tree

1 file changed

+39
-8
lines changed

1 file changed

+39
-8
lines changed

libudpard/udpard.c

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,10 @@ static uint32_t crc_partial_finalize(const size_t n_bytes, const uint32_t crc_ac
249249

250250
// --------------------------------------------- HEADER ---------------------------------------------
251251

252-
#define HEADER_SIZE_BYTES 48U
253-
#define HEADER_VERSION 2U
254-
#define HEADER_FLAG_ACK 0x01U
252+
#define HEADER_SIZE_BYTES 48U
253+
#define HEADER_VERSION 2U
254+
#define HEADER_FLAG_ACK 0x01U
255+
#define HEADER_FRAME_INDEX_MAX 0xFFFFFFU /// 4 GiB with 256-byte MTU
255256

256257
typedef struct
257258
{
@@ -316,7 +317,7 @@ static byte_t* header_serialize(byte_t* const buffer,
316317
*ptr++ = flags;
317318
*ptr++ = 0;
318319
*ptr++ = 0;
319-
ptr = serialize_u32(ptr, frame_index);
320+
ptr = serialize_u32(ptr, frame_index & HEADER_FRAME_INDEX_MAX);
320321
ptr = serialize_u32(ptr, frame_payload_offset);
321322
ptr = serialize_u32(ptr, meta.transfer_payload_size);
322323
ptr = serialize_u64(ptr, meta.transfer_id);
@@ -355,10 +356,15 @@ static bool header_deserialize(const udpard_bytes_mut_t dgram_payload,
355356
ptr = deserialize_u64(ptr, &out_meta->topic_hash);
356357
ptr = deserialize_u32(ptr, prefix_crc);
357358
(void)ptr;
358-
// TODO: validate the fields (e.g., ensure offset+size does not exceed the transfer payload size)
359359
// Set up the output payload view.
360360
out_payload->size = dgram_payload.size - HEADER_SIZE_BYTES;
361361
out_payload->data = (byte_t*)dgram_payload.data + HEADER_SIZE_BYTES;
362+
// Finalize the fields.
363+
*frame_index = HEADER_FRAME_INDEX_MAX & *frame_index;
364+
// Validate the fields.
365+
ok = ((uint64_t)*frame_payload_offset + (uint64_t)out_payload->size) <=
366+
(uint64_t)out_meta->transfer_payload_size;
367+
ok = ok && ((0 == *frame_index) == (0 == *frame_payload_offset));
362368
} else {
363369
ok = false;
364370
}
@@ -715,9 +721,8 @@ void udpard_tx_free(const udpard_tx_mem_resources_t memory, udpard_tx_item_t* co
715721
/// All but the transfer metadata: fields that change from frame to frame within the same transfer.
716722
typedef struct
717723
{
718-
uint32_t index;
719724
uint32_t offset; ///< Offset of this fragment's payload within the full transfer payload.
720-
udpard_bytes_t payload; ///< Also contains the transfer CRC (but not the header CRC).
725+
udpard_bytes_t payload; ///< Does not include the header, just pure payload.
721726
udpard_bytes_mut_t origin; ///< The entirety of the free-able buffer passed from the application.
722727
} rx_frame_base_t;
723728

@@ -732,7 +737,11 @@ typedef struct
732737
/// One implication is that no two fragments can have the same offset.
733738
static int32_t rx_cavl_compare_fragment_offset(const void* const user, const udpard_tree_t* const node)
734739
{
735-
return ((*(const size_t*)user) - ((udpard_fragment_t*)node)->offset) ? +1 : -1;
740+
const size_t u = *(const size_t*)user;
741+
const size_t v = ((const udpard_fragment_t*)node)->offset; // clang-format off
742+
if (u < v) { return -1; }
743+
if (u > v) { return +1; }
744+
return 0; // clang-format on
736745
}
737746

738747
/// Find the first fragment where offset >= left in log time. Returns NULL if no such fragment exists.
@@ -756,6 +765,7 @@ static bool rx_fragment_tree_has_gap_in_range(udpard_tree_t* const root, const s
756765
if (frag == NULL) {
757766
return true;
758767
}
768+
// offset+size can overflow on platforms with 16-bit size and requires special treatment there.
759769
if ((frag->offset + frag->view.size) <= left) { // The predecessor ends before the left edge.
760770
return true;
761771
}
@@ -808,6 +818,27 @@ static size_t rx_fragment_tree_update_covered_prefix(udpard_tree_t* const root,
808818
return out;
809819
}
810820

821+
typedef enum
822+
{
823+
rx_fragment_tree_not_done,
824+
rx_fragment_tree_done,
825+
rx_fragment_tree_oom,
826+
} rx_fragment_tree_update_result_t;
827+
828+
/// Takes ownership of the frame payload. Returns true if the transfer is fully reassembled in the tree.
829+
static rx_fragment_tree_update_result_t rx_fragment_tree_update(udpard_tree_t** const root,
830+
const udpard_mem_resource_t fragment_memory,
831+
const rx_frame_base_t frame,
832+
const udpard_mem_deleter_t payload_deleter,
833+
const size_t transfer_payload_size,
834+
const size_t extent,
835+
size_t* const covered_prefix_io)
836+
{
837+
// First we need to check if the new fragment is needed at all. It is needed in two cases:
838+
// 1) It covers new ground in the [0, extent) range.
839+
// 2) It overlaps smaller fragments that are already in the tree, which can be replaced.
840+
}
841+
811842
typedef enum
812843
{
813844
rx_slot_idle = 0,

0 commit comments

Comments
 (0)