mirror of
https://gitlab.com/d3tn/ud3tn.git
synced 2026-08-13 12:33:27 +02:00
Removes unused includes detected by the clangd LSP. Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
275 lines
6.9 KiB
C
275 lines
6.9 KiB
C
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
|
|
#include "bundle7/eid.h"
|
|
#include "bundle7/serializer.h"
|
|
|
|
#include "cbor.h"
|
|
#include "compilersupport_p.h" // Private TinyCBOR header, used for endianness
|
|
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/* CBOR output buffer size. This buffer will be allocated during the
|
|
* serialization process and released afterwards
|
|
*/
|
|
#define BUFFER_SIZE 128
|
|
|
|
|
|
static inline size_t primary_block_get_item_count(const struct bundle *bundle)
|
|
{
|
|
size_t length = 8;
|
|
|
|
if (bundle->crc_type != BUNDLE_CRC_TYPE_NONE)
|
|
length++;
|
|
|
|
if (bundle_is_fragmented(bundle))
|
|
length += 2;
|
|
|
|
return length;
|
|
}
|
|
|
|
|
|
static inline size_t block_get_item_count(const struct bundle_block *block)
|
|
{
|
|
size_t length = 5;
|
|
|
|
if (block->crc_type != BUNDLE_CRC_TYPE_NONE)
|
|
length++;
|
|
|
|
return length;
|
|
}
|
|
|
|
|
|
static CborError write_crc(
|
|
struct CborEncoder *encoder,
|
|
enum bundle_crc_type crc_type, struct crc_stream *crc)
|
|
{
|
|
// CRC-32
|
|
if (crc_type == BUNDLE_CRC_TYPE_32) {
|
|
// Feed the "zero" CRC checksum
|
|
crc->feed(crc, 0x44);
|
|
crc->feed(crc, 0x00);
|
|
crc->feed(crc, 0x00);
|
|
crc->feed(crc, 0x00);
|
|
crc->feed(crc, 0x00);
|
|
crc->feed_eof(crc);
|
|
|
|
// Swap to network byte order
|
|
// cppcheck-suppress selfAssignment
|
|
crc->checksum = cbor_htonl(crc->checksum);
|
|
|
|
return cbor_encode_byte_string(encoder, crc->bytes, 4);
|
|
// CRC-16
|
|
} else {
|
|
// Feed the "zero" CRC checksum
|
|
crc->feed(crc, 0x42);
|
|
crc->feed(crc, 0x00);
|
|
crc->feed(crc, 0x00);
|
|
crc->feed_eof(crc);
|
|
|
|
// Swap to network byte order
|
|
// cppcheck-suppress selfAssignment
|
|
crc->checksum = cbor_htons(crc->checksum);
|
|
|
|
// We skip the first two (empty) bytes of the checksum here
|
|
return cbor_encode_byte_string(encoder, crc->bytes, 2);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Number of bytes required for CBOR-encoded max. value:
|
|
*
|
|
* Primary Block
|
|
* -------------
|
|
*
|
|
*
|
|
* Extension Block (without payload):
|
|
* ----------------------------------
|
|
*
|
|
* Array header: 1 Byte
|
|
* Block type code (255): 2 Byte
|
|
* Block number (255): 2 Byte
|
|
* Block processing control flags: 1 Byte
|
|
* CRC (32 bit): 5 Byte
|
|
* Block data length: 5 Byte
|
|
*/
|
|
|
|
|
|
static inline void init_crc(struct crc_stream *crc,
|
|
enum bundle_crc_type type)
|
|
{
|
|
if (type == BUNDLE_CRC_TYPE_32)
|
|
crc_init(crc, CRC32);
|
|
else if (type == BUNDLE_CRC_TYPE_16)
|
|
crc_init(crc, CRC16_X25);
|
|
}
|
|
|
|
|
|
static inline void feed_crc(struct crc_stream *crc,
|
|
enum bundle_crc_type type, const uint8_t *buffer, size_t length)
|
|
{
|
|
if (type != BUNDLE_CRC_TYPE_NONE)
|
|
crc_feed_bytes(crc, buffer, length);
|
|
}
|
|
|
|
enum ud3tn_result bundle7_serialize(
|
|
struct bundle *bundle,
|
|
enum ud3tn_result (*write)(void *cla_obj, const void *, const size_t),
|
|
void *cla_obj)
|
|
{
|
|
// Assert that the bundle has correct version
|
|
if (bundle->protocol_version != 7)
|
|
return UD3TN_FAIL;
|
|
|
|
uint8_t *buffer;
|
|
CborEncoder encoder;
|
|
struct crc_stream crc;
|
|
int written;
|
|
|
|
buffer = malloc(BUFFER_SIZE);
|
|
if (buffer == NULL)
|
|
return UD3TN_FAIL;
|
|
|
|
// Bundle start (CBOR indefinite array)
|
|
buffer[0] = 0x9f;
|
|
|
|
// -------------
|
|
// Primary Block
|
|
// -------------
|
|
|
|
buffer[1] = 0x80 + primary_block_get_item_count(bundle);
|
|
|
|
init_crc(&crc, bundle->crc_type);
|
|
|
|
cbor_encoder_init(&encoder, buffer + 2, BUFFER_SIZE - 2, 0);
|
|
cbor_encode_uint(&encoder, bundle->protocol_version);
|
|
cbor_encode_uint(&encoder, bundle->proc_flags);
|
|
cbor_encode_uint(&encoder, bundle->crc_type);
|
|
|
|
if (write(cla_obj, buffer, cbor_encoder_get_buffer_size(&encoder, buffer)) != UD3TN_OK)
|
|
goto fail;
|
|
feed_crc(&crc, bundle->crc_type, buffer + 1,
|
|
cbor_encoder_get_buffer_size(&encoder, buffer + 1));
|
|
|
|
// Destination EID
|
|
written = bundle7_eid_serialize(bundle->destination,
|
|
buffer, BUFFER_SIZE);
|
|
if (written <= 0)
|
|
goto fail;
|
|
if (write(cla_obj, buffer, written) != UD3TN_OK)
|
|
goto fail;
|
|
feed_crc(&crc, bundle->crc_type, buffer, written);
|
|
|
|
// Source EID
|
|
written = bundle7_eid_serialize(bundle->source,
|
|
buffer, BUFFER_SIZE);
|
|
if (written <= 0)
|
|
goto fail;
|
|
if (write(cla_obj, buffer, written) != UD3TN_OK)
|
|
goto fail;
|
|
feed_crc(&crc, bundle->crc_type, buffer, written);
|
|
|
|
// Report-To EID
|
|
written = bundle7_eid_serialize(bundle->report_to,
|
|
buffer, BUFFER_SIZE);
|
|
if (written <= 0)
|
|
goto fail;
|
|
if (write(cla_obj, buffer, written) != UD3TN_OK)
|
|
goto fail;
|
|
feed_crc(&crc, bundle->crc_type, buffer, written);
|
|
|
|
// Creation Timestamp
|
|
buffer[0] = 0x82;
|
|
cbor_encoder_init(&encoder, buffer + 1, BUFFER_SIZE - 1, 0);
|
|
cbor_encode_uint(&encoder, bundle->creation_timestamp_ms);
|
|
cbor_encode_uint(&encoder, bundle->sequence_number);
|
|
cbor_encode_uint(&encoder, bundle->lifetime_ms);
|
|
|
|
if (bundle_is_fragmented(bundle)) {
|
|
cbor_encode_uint(&encoder, bundle->fragment_offset);
|
|
cbor_encode_uint(&encoder, bundle->total_adu_length);
|
|
}
|
|
|
|
// CRC checksum for primary block
|
|
if (bundle->crc_type != BUNDLE_CRC_TYPE_NONE) {
|
|
feed_crc(&crc, bundle->crc_type, buffer,
|
|
cbor_encoder_get_buffer_size(&encoder, buffer));
|
|
|
|
// Calculate and encode CRC checksum for primary block.
|
|
write_crc(&encoder, bundle->crc_type, &crc);
|
|
}
|
|
|
|
if (write(cla_obj, buffer, cbor_encoder_get_buffer_size(&encoder, buffer)) != UD3TN_OK)
|
|
goto fail;
|
|
|
|
// ----------------
|
|
// Extension Blocks
|
|
// ----------------
|
|
|
|
struct bundle_block_list *cur_block = bundle->blocks;
|
|
|
|
while (cur_block != NULL) {
|
|
const struct bundle_block *block = cur_block->data;
|
|
|
|
init_crc(&crc, block->crc_type);
|
|
|
|
// CBOR array header with embedded number of items
|
|
buffer[0] = 0x80 + block_get_item_count(block);
|
|
|
|
cbor_encoder_init(&encoder, buffer + 1, BUFFER_SIZE - 1, 0);
|
|
cbor_encode_uint(&encoder, block->type);
|
|
cbor_encode_uint(&encoder, block->number);
|
|
cbor_encode_uint(&encoder, block->flags);
|
|
cbor_encode_uint(&encoder, block->crc_type);
|
|
|
|
const size_t bytes_before_length = cbor_encoder_get_buffer_size(
|
|
&encoder, buffer
|
|
);
|
|
|
|
// As the byte string length is represented in the same manner
|
|
// as a uint in CBOR, we can write it like that and afterwards
|
|
// change the type code to byte string.
|
|
cbor_encode_uint(&encoder, block->length);
|
|
buffer[bytes_before_length] |= 0x40; // uint -> bytestring
|
|
|
|
if (write(cla_obj, buffer,
|
|
cbor_encoder_get_buffer_size(&encoder,
|
|
buffer)) != UD3TN_OK)
|
|
goto fail;
|
|
feed_crc(&crc, block->crc_type, buffer,
|
|
cbor_encoder_get_buffer_size(&encoder, buffer));
|
|
|
|
if (write(cla_obj, block->data, block->length) != UD3TN_OK)
|
|
goto fail;
|
|
feed_crc(&crc, block->crc_type,
|
|
block->data, block->length);
|
|
|
|
if (block->crc_type != BUNDLE_CRC_TYPE_NONE) {
|
|
// Reset CBOR encoder
|
|
cbor_encoder_init(&encoder, buffer, BUFFER_SIZE, 0);
|
|
|
|
// Calculate and CRC checksum for extension block
|
|
write_crc(&encoder, block->crc_type, &crc);
|
|
|
|
if (write(cla_obj, buffer,
|
|
cbor_encoder_get_buffer_size(&encoder, buffer)) != UD3TN_OK)
|
|
goto fail;
|
|
}
|
|
|
|
cur_block = cur_block->next;
|
|
}
|
|
|
|
// CBOR "break"
|
|
buffer[0] = 0xff;
|
|
if (write(cla_obj, buffer, 1) != UD3TN_OK)
|
|
goto fail;
|
|
|
|
free(buffer);
|
|
return UD3TN_OK;
|
|
|
|
fail:
|
|
free(buffer);
|
|
return UD3TN_FAIL;
|
|
}
|