#include "quicr/QuicrEncoder.hpp" #include "quicr/QuicrConnection.hpp" #include "bytebuffer/ByteBufferReader.hpp" #include "quicr/QuicrFrameType.hpp" #include namespace tw::net::quicr { QuicrPacket QuicrDecoder::decode_packet_header(std::span data, size_t &offset) { ByteBufferReader reader(data); QuicrPacket packet; reader.pop_bytes(&packet.type); reader.pop_bytes(&packet.destination_id); reader.pop_bytes(&packet.local_id); reader.pop_bytes(&packet.require_ack); // if(packet.require_ack) { uint32_t packet_number = 0; reader.pop_bytes(&packet_number); packet.packet_number = packet_number; // } // packet.require_ack = false; uint32_t length = 0; reader.pop_bytes(&length); offset = data.size() - reader.remaining(); return packet; } QuicrPacket QuicrDecoder::decode_packet(std::span data) { size_t offset = 0; QuicrPacket packet = decode_packet_header(data, offset); ByteBufferReader reader(data.subspan(offset)); while(reader.remaining()) { FrameType frame_type; reader.pop_bytes(&frame_type); switch(frame_type) { case FrameType::KeepAlive: case FrameType::Padding: { break; } case FrameType::Ack: { uint8_t num_acks = 0; reader.pop_bytes(&num_acks); std::vector acked_packets(num_acks); reader.pop_bytes(acked_packets.data(), acked_packets.size() * sizeof(uint32_t)); packet.frames.push_back(QuicrFrame::make_ack(acked_packets)); break; } case FrameType::Hello: { packet.require_ack = true; packet.frames.push_back(QuicrFrame::make_hello()); break; } case FrameType::HelloFin: { packet.require_ack = true; packet.frames.push_back(QuicrFrame::make_hello_fin()); break; } case FrameType::StreamBase: packet.require_ack = true; case FrameType::StreamUnreliable: { uint32_t size = 0; reader.pop_bytes(&size); std::vector content(size); reader.pop_bytes(content.data(), size); packet.frames.push_back(QuicrFrame::make_stream(content)); break; } default: { throw std::runtime_error("Unrecognized frame type: " + std::to_string((uint8_t)frame_type)); spdlog::error("Unrecognized frame type: {}", (uint8_t)frame_type); break; } } } return packet; } QuicrPacketEncoder::QuicrPacketEncoder(std::span target, size_t& offset, QuicrPacketType type, std::optional packet_number, QuicrConnection& connection) : m_target(target), m_offset(offset), m_type(type), m_connection(connection), m_writer(m_target), size_val_offset(0), is_reliable_val_offset(0) { m_writer.write_bytes((uint8_t*)&type); m_writer.write_bytes(&m_connection.peer_id()); m_writer.write_bytes(&m_connection.self_id()); is_reliable_val_offset = m_writer.length(); bool require_ack = false; // TODO: When does it need the ACK? m_writer.write_bytes(&require_ack); //if(require_ack) { uint32_t _packet_num = packet_number.value(); m_writer.write_bytes(&_packet_num); //} uint32_t length_offset = m_writer.remaining(); uint32_t length = 0; m_writer.write_bytes(&length); } QuicrPacketEncoder& QuicrPacketEncoder::encode_stream_frame(std::span data, bool is_reliable) { uint8_t frame_type = is_reliable ? FrameType::StreamBase : FrameType::StreamUnreliable; if(is_reliable) { set_as_reliable(); } m_writer.write_bytes(&frame_type); uint32_t length = data.size(); m_writer.write_bytes(&length); m_writer.write_bytes(data); return *this; } QuicrPacketEncoder& QuicrPacketEncoder::encode_ack_frame(std::vector& acked_packets) { if(!acked_packets.empty()) { uint8_t ack_frame_type = FrameType::Ack; uint8_t acks_count = acked_packets.size(); m_writer.write_bytes(&ack_frame_type); m_writer.write_bytes(&acks_count); for(auto& ack : acked_packets) { m_writer.write_bytes(&ack); } } return *this; } QuicrPacketEncoder& QuicrPacketEncoder::encode_frame(QuicrFrame& frame) { m_offset += m_writer.write_bytes(&frame.type); switch(frame.type) { case FrameType::KeepAlive: case FrameType::Padding: case FrameType::Hello: set_as_reliable(); break; case FrameType::StreamBase: set_as_reliable(); case FrameType::StreamUnreliable: { m_offset += m_writer.write_bytes(frame.content); break; } case FrameType::Ack: case FrameType::AckEcn: case FrameType::ResetStream: case FrameType::StopSending: case FrameType::Crypto: case FrameType::NewToken: case FrameType::HandshakeDone: set_as_reliable(); m_offset += m_writer.write_bytes(frame.content); break; default: { break; } } return *this; } }