// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0 #include "bundle6/sdnv.h" #include "bundle6/bundle6.h" #include "bundle6/serializer.h" #include "ud3tn/result.h" #include #include #include #include #define write_bytes(success_var, bytes, data) do { \ if ((success_var) && write(cla_obj, data, bytes) != UD3TN_OK) \ (success_var) = false; \ } while (0) #define serialize_u16(success_var, buffer, value) do { \ __typeof__(buffer) *_buffer = &(buffer); \ write_bytes(success_var, sdnv_write_u16(*_buffer, value), *_buffer); \ } while (0) #define serialize_u32(success_var, buffer, value) do { \ __typeof__(buffer) *_buffer = &(buffer); \ write_bytes(success_var, sdnv_write_u32(*_buffer, value), *_buffer); \ } while (0) #define serialize_u64(success_var, buffer, value) do { \ __typeof__(buffer) *_buffer = &(buffer); \ write_bytes(success_var, sdnv_write_u64(*_buffer, value), *_buffer); \ } while (0) enum ud3tn_result bundle6_serialize( struct bundle *bundle, enum ud3tn_result (*write)(void *cla_obj, const void *, const size_t), void *cla_obj) { uint8_t buffer[MAX_SDNV_SIZE]; // Serialize dict struct bundle6_dict_descriptor *dict_desc = bundle6_calculate_dict( bundle ); if (dict_desc == NULL) return UD3TN_FAIL; char *dict = malloc(dict_desc->dict_length_bytes); if (dict == NULL) { bundle6_free_dict_descriptor(dict_desc); return UD3TN_FAIL; } bundle6_serialize_dictionary(dict, dict_desc); // Indicates whether the serialization process can continue bool ok = true; /* Write version field */ write_bytes(ok, 1, &(bundle->protocol_version)); /* Write SDNV values up to dictionary length */ serialize_u64(ok, buffer, bundle->proc_flags); serialize_u64(ok, buffer, bundle->primary_block_length); serialize_u16(ok, buffer, dict_desc->destination_eid_info.dict_scheme_offset); serialize_u16(ok, buffer, dict_desc->destination_eid_info.dict_ssp_offset); serialize_u16(ok, buffer, dict_desc->source_eid_info.dict_scheme_offset); serialize_u16(ok, buffer, dict_desc->source_eid_info.dict_ssp_offset); serialize_u16(ok, buffer, dict_desc->report_to_eid_info.dict_scheme_offset); serialize_u16(ok, buffer, dict_desc->report_to_eid_info.dict_ssp_offset); serialize_u16(ok, buffer, dict_desc->custodian_eid_info.dict_scheme_offset); serialize_u16(ok, buffer, dict_desc->custodian_eid_info.dict_ssp_offset); serialize_u64(ok, buffer, bundle->creation_timestamp_ms / 1000); serialize_u64(ok, buffer, bundle->sequence_number); serialize_u64(ok, buffer, bundle->lifetime_ms / 1000); serialize_u16(ok, buffer, dict_desc->dict_length_bytes); /* Write dictionary byte array */ write_bytes(ok, dict_desc->dict_length_bytes, dict); /* Write remaining SDNV values */ if (HAS_FLAG(bundle->proc_flags, BUNDLE_FLAG_IS_FRAGMENT)) { serialize_u64(ok, buffer, bundle->fragment_offset); serialize_u64(ok, buffer, bundle->total_adu_length); } /* Serialize bundle blocks */ struct bundle_block_list *cur_entry = bundle->blocks; struct eid_list *cur_ref; while (ok && cur_entry != NULL) { write_bytes(ok, 1, &cur_entry->data->type); serialize_u64(ok, buffer, cur_entry->data->flags); if (HAS_FLAG(cur_entry->data->flags, BUNDLE_V6_BLOCK_FLAG_HAS_EID_REF_FIELD) ) { // Determine the count of refs int eid_ref_cnt = 0; for (cur_ref = cur_entry->data->eid_refs; cur_ref; cur_ref = cur_ref->next, eid_ref_cnt++) ; serialize_u16(ok, buffer, eid_ref_cnt); // Write out the refs for (int c = 0; c < eid_ref_cnt; c++) { struct bundle6_eid_info eid_info = dict_desc->eid_references[c]; serialize_u16(ok, buffer, eid_info.dict_scheme_offset); serialize_u16(ok, buffer, eid_info.dict_ssp_offset); } } serialize_u64(ok, buffer, cur_entry->data->length); write_bytes(ok, cur_entry->data->length, cur_entry->data->data); cur_entry = cur_entry->next; } free(dict); bundle6_free_dict_descriptor(dict_desc); return ok ? UD3TN_OK : UD3TN_FAIL; }