18 #include <arpa/inet.h>
24 throw "Packet too short";
27 std::memcpy(&_lct_header,
data, 4);
28 if (_lct_header.version != 1) {
29 throw "Unsupported LCT version";
32 char* hdr_ptr =
data + 4;
33 if (_lct_header.congestion_control_flag != 0) {
34 throw "Unsupported CCI field length";
39 if (_lct_header.half_word_flag == 0 && _lct_header.tsi_flag == 0) {
40 throw "TSI field not present";
43 if(_lct_header.half_word_flag == 1) {
44 _tsi = ntohs(*(uint16_t*)hdr_ptr);
48 if(_lct_header.tsi_flag == 1) {
49 _tsi |= ntohl(*(uint32_t*)hdr_ptr) << tsi_shift;
53 if ( _lct_header.close_session_flag == 0 && _lct_header.half_word_flag == 0 && _lct_header.toi_flag == 0) {
54 throw "TOI field not present";
57 if(_lct_header.half_word_flag == 1) {
58 _toi = ntohs(*(uint16_t*)hdr_ptr);
62 switch(_lct_header.toi_flag) {
65 _toi |= ntohl(*(uint32_t*)hdr_ptr) << toi_shift;
70 throw "TOI fields over 64 bits in length are not supported";
72 _toi = ntohl(*(uint32_t*)hdr_ptr);
74 _toi |= (uint64_t)(ntohl(*(uint32_t*)hdr_ptr)) << 32;
79 throw "TOI fields over 64 bits in length are not supported";
82 if (_lct_header.codepoint == 0) {
85 throw "Only Compact No-Code FEC is supported";
88 auto expected_header_len = 2 +
89 _lct_header.congestion_control_flag +
90 _lct_header.half_word_flag +
91 _lct_header.tsi_flag +
94 size_t ext_header_len = (_lct_header.lct_header_len - expected_header_len) * 4;
95 while (ext_header_len > 0) {
96 auto ext_ptr = hdr_ptr;
97 uint8_t het = *ext_ptr;
107 if (ext_len > ext_header_len) {
108 throw "Header extension length exceeds remaining header length";
111 switch ((AlcPacket::HeaderExtension)het) {
120 throw "Invalid length for EXT_FTI header extension";
122 _fec_oti.
transfer_length = (uint64_t)(ntohs(*(uint16_t*)ext_ptr)) << 32;
134 uint8_t flute_version = (*ext_ptr & 0xF0) >> 4;
135 if (flute_version > 2) {
136 throw "Unsupported FLUTE version";
138 _fdt_instance_id = (*ext_ptr & 0x0F) << 16;
140 _fdt_instance_id |= ntohs(*(uint16_t*)ext_ptr);
144 uint8_t encoding = *ext_ptr;
155 ext_header_len -= ext_len;
163 const size_t max_alc_header_size = 4;
164 auto lct_header_len = 3;
169 auto max_packet_length = max_encoding_symbol_size +
171 + max_alc_header_size ;
173 _buffer = (
char*)calloc(max_packet_length,
sizeof(
char));
175 auto lct_header = (lct_header_t*)_buffer;
177 lct_header->version = 1;
178 lct_header->half_word_flag = 1;
179 lct_header->lct_header_len = lct_header_len;
180 auto hdr_ptr = _buffer + 4;
181 auto payload_ptr = _buffer + 4 * lct_header_len;
184 _len = 4 * lct_header_len + payload_size;
188 *((uint16_t*)hdr_ptr) = htons(
tsi);
191 *((uint16_t*)hdr_ptr) = htons(
toi);
195 *((uint8_t*)hdr_ptr) = EXT_FDT;
202 *((uint8_t*)hdr_ptr) = EXT_FTI;
204 *((uint8_t*)hdr_ptr) = 4;
206 *((uint16_t*)hdr_ptr) = htons((_fec_oti.
transfer_length & 0x00FF0000) >> 32);
219 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