Loading src/httpd.cpp +33 −0 Changes for src/httpd.cpp: 33 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -81,6 +81,39 @@ static constexpr std::chrono::seconds H2_WINDOW_STALL_TIMEOUT{30}; static const char H2_CLIENT_PREFACE[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; static constexpr size_t H2_CLIENT_PREFACE_LEN = 24; // ============================================================================ // HTTP/3: mandatory control streams (RFC 9114 §6.2.1) // ============================================================================ void libhttppp::Http3QuicSocket::sendControlStreams() { if (_ctrlStreamsSent) return; _ctrlStreamsSent = true; // 1. Control stream (stream type 0x00) with SETTINGS frame // RFC 9114 §6.2.1: Each side MUST initiate a single control stream // and send its SETTINGS frame as the first frame on this stream. uint64_t ctrl_id = openStream(false); // server-initiated unidirectional std::vector<uint8_t> ctrl_data; ctrl_data.push_back(0x00); // Stream type: Control // SETTINGS frame (type 0x04) with empty payload (use defaults) ctrl_data.push_back(0x04); // Frame type: SETTINGS ctrl_data.push_back(0x00); // Frame length: 0 sendStreamData(ctrl_id, ctrl_data, false); // 2. QPACK encoder stream (stream type 0x02) // RFC 9204 §4.2: required for QPACK header compression uint64_t enc_id = openStream(false); std::vector<uint8_t> enc_data; enc_data.push_back(0x02); // Stream type: QPACK Encoder sendStreamData(enc_id, enc_data, false); // 3. QPACK decoder stream (stream type 0x03) uint64_t dec_id = openStream(false); std::vector<uint8_t> dec_data; dec_data.push_back(0x03); // Stream type: QPACK Decoder sendStreamData(dec_id, dec_data, false); } static std::string h2BuildFrame(uint8_t type, uint8_t flags, uint32_t stream_id, const std::string &payload) { std::string f(9 + payload.size(), '\0'); Loading src/httpd.h +13 −0 Changes for src/httpd.h: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -168,6 +168,19 @@ namespace libhttppp { void _reapStalledH2Streams(HttpRequest &cureq, std::string &out); }; // netplus::quic leaves sendControlStreams() (RFC 9114 §6.2.1: control + // QPACK encoder/decoder streams) as a no-op — that framing is HTTP/3 // application-layer knowledge, which belongs here alongside qpack.h/ // hpack.h rather than in the QUIC transport library. This override // holds the real implementation. class Http3QuicSocket : public netplus::quic { public: using netplus::quic::quic; void sendControlStreams() override; private: bool _ctrlStreamsSent = false; }; class HttpD { public: HttpD(int argc, char** argv); Loading Loading
src/httpd.cpp +33 −0 Changes for src/httpd.cpp: 33 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -81,6 +81,39 @@ static constexpr std::chrono::seconds H2_WINDOW_STALL_TIMEOUT{30}; static const char H2_CLIENT_PREFACE[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; static constexpr size_t H2_CLIENT_PREFACE_LEN = 24; // ============================================================================ // HTTP/3: mandatory control streams (RFC 9114 §6.2.1) // ============================================================================ void libhttppp::Http3QuicSocket::sendControlStreams() { if (_ctrlStreamsSent) return; _ctrlStreamsSent = true; // 1. Control stream (stream type 0x00) with SETTINGS frame // RFC 9114 §6.2.1: Each side MUST initiate a single control stream // and send its SETTINGS frame as the first frame on this stream. uint64_t ctrl_id = openStream(false); // server-initiated unidirectional std::vector<uint8_t> ctrl_data; ctrl_data.push_back(0x00); // Stream type: Control // SETTINGS frame (type 0x04) with empty payload (use defaults) ctrl_data.push_back(0x04); // Frame type: SETTINGS ctrl_data.push_back(0x00); // Frame length: 0 sendStreamData(ctrl_id, ctrl_data, false); // 2. QPACK encoder stream (stream type 0x02) // RFC 9204 §4.2: required for QPACK header compression uint64_t enc_id = openStream(false); std::vector<uint8_t> enc_data; enc_data.push_back(0x02); // Stream type: QPACK Encoder sendStreamData(enc_id, enc_data, false); // 3. QPACK decoder stream (stream type 0x03) uint64_t dec_id = openStream(false); std::vector<uint8_t> dec_data; dec_data.push_back(0x03); // Stream type: QPACK Decoder sendStreamData(dec_id, dec_data, false); } static std::string h2BuildFrame(uint8_t type, uint8_t flags, uint32_t stream_id, const std::string &payload) { std::string f(9 + payload.size(), '\0'); Loading
src/httpd.h +13 −0 Changes for src/httpd.h: 13 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -168,6 +168,19 @@ namespace libhttppp { void _reapStalledH2Streams(HttpRequest &cureq, std::string &out); }; // netplus::quic leaves sendControlStreams() (RFC 9114 §6.2.1: control + // QPACK encoder/decoder streams) as a no-op — that framing is HTTP/3 // application-layer knowledge, which belongs here alongside qpack.h/ // hpack.h rather than in the QUIC transport library. This override // holds the real implementation. class Http3QuicSocket : public netplus::quic { public: using netplus::quic::quic; void sendControlStreams() override; private: bool _ctrlStreamsSent = false; }; class HttpD { public: HttpD(int argc, char** argv); Loading