19 #include <arpa/inet.h>
25 throw std::runtime_error(
"Packet too short");
28 std::memcpy(&_lct_header,
data, 4);
29 if (_lct_header.version != 1) {
30 throw std::runtime_error(
"Unsupported LCT version");
33 char* hdr_ptr =
data + 4;
34 if (_lct_header.congestion_control_flag != 0) {
35 throw std::runtime_error(
"Unsupported CCI field length");
40 if (_lct_header.half_word_flag == 0 && _lct_header.tsi_flag == 0) {
41 throw std::runtime_error(
"TSI field not present");
44 if(_lct_header.half_word_flag == 1) {
45 _tsi = ntohs(*(uint16_t*)hdr_ptr);
49 if(_lct_header.tsi_flag == 1) {
50 _tsi |= ntohl(*(uint32_t*)hdr_ptr) << tsi_shift;
54 if ( _lct_header.close_session_flag == 0 && _lct_header.half_word_flag == 0 && _lct_header.toi_flag == 0) {
55 throw std::runtime_error(
"TOI field not present");
58 if(_lct_header.half_word_flag == 1) {
59 _toi = ntohs(*(uint16_t*)hdr_ptr);
63 switch(_lct_header.toi_flag) {
66 _toi |= ntohl(*(uint32_t*)hdr_ptr) << toi_shift;
71 throw std::runtime_error(
"TOI fields over 64 bits in length are not supported");
73 _toi = ntohl(*(uint32_t*)hdr_ptr);
75 _toi |= (uint64_t)(ntohl(*(uint32_t*)hdr_ptr)) << 32;
80 throw std::runtime_error(
"TOI fields over 64 bits in length are not supported");
83 if (_lct_header.codepoint == 0) {
86 throw std::runtime_error(
"Only Compact No-Code FEC is supported");
89 auto expected_header_len = 2 +
90 _lct_header.congestion_control_flag +
91 _lct_header.half_word_flag +
92 _lct_header.tsi_flag +
95 size_t ext_header_len = (_lct_header.lct_header_len - expected_header_len) * 4;
96 while (ext_header_len > 0) {
97 auto ext_ptr = hdr_ptr;
98 uint8_t het = *ext_ptr;
108 if (ext_len > ext_header_len) {
109 throw std::runtime_error(
"Header extension length exceeds remaining header length");
112 switch ((AlcPacket::HeaderExtension)het) {
121 throw std::runtime_error(
"Invalid length for EXT_FTI header extension");
123 _fec_oti.
transfer_length = (uint64_t)(ntohs(*(uint16_t*)ext_ptr)) << 32;
135 uint8_t flute_version = (*ext_ptr & 0xF0) >> 4;
136 if (flute_version > 2) {
137 throw std::runtime_error(
"Unsupported FLUTE version");
139 _fdt_instance_id = (*ext_ptr & 0x0F) << 16;
141 _fdt_instance_id |= ntohs(*(uint16_t*)ext_ptr);
145 uint8_t encoding = *ext_ptr;
156 ext_header_len -= ext_len;
164 const size_t max_alc_header_size = 4;
165 auto lct_header_len = 3;
170 auto max_packet_length = max_encoding_symbol_size +
172 + max_alc_header_size ;
174 _buffer = (
char*)calloc(max_packet_length,
sizeof(
char));
176 auto lct_header = (lct_header_t*)_buffer;
178 lct_header->version = 1;
179 lct_header->half_word_flag = 1;
180 lct_header->lct_header_len = lct_header_len;
181 auto hdr_ptr = _buffer + 4;
182 auto payload_ptr = _buffer + 4 * lct_header_len;
185 _len = 4 * lct_header_len + payload_size;
189 *((uint16_t*)hdr_ptr) = htons(
tsi);
192 *((uint16_t*)hdr_ptr) = htons(
toi);
196 *((uint8_t*)hdr_ptr) = EXT_FDT;
203 *((uint8_t*)hdr_ptr) = EXT_FTI;
205 *((uint8_t*)hdr_ptr) = 4;
213 *((uint16_t*)hdr_ptr) = htons(
static_cast<uint16_t
>((_fec_oti.
transfer_length >> 32) & 0xFFFF));
215 *((uint32_t*)hdr_ptr) = htonl(
static_cast<uint32_t
>(_fec_oti.
transfer_length & 0xFFFFFFFF));
226 if (_buffer) free(_buffer);
uint64_t tsi() const
Get the TSI.
char * data() const
Get a pointer to the payload data of the constructed packet.
uint32_t fdt_instance_id() const
Get the FDT instance ID.
~AlcPacket()
Default destructor.
uint64_t toi() const
Get the TOI.
AlcPacket(char *data, size_t len)
Create an ALC packet from payload data.
static size_t to_payload(const std::vector< EncodingSymbol > &, char *encoded_data, size_t data_len, const FecOti &fec_oti, ContentEncoding encoding)
Write encoding symbols to a packet payload buffer.
uint32_t max_source_block_length
uint32_t encoding_symbol_length