#pragma once extern "C" { #include } #include "logging.hpp" #include /* This file contains RAII compatible adapters for nghttp2 structures. They * attempt to be as close to a direct call as possible, while keeping the RAII * lifetime safety for the various classes. Because of this, they use the same * naming as nghttp2, so ignore naming violations. */ // NOLINTBEGIN(readability-identifier-naming, // readability-make-member-function-const) struct nghttp2_session; struct nghttp2_session_callbacks { friend nghttp2_session; nghttp2_session_callbacks() { nghttp2_session_callbacks_new(&ptr); } ~nghttp2_session_callbacks() { nghttp2_session_callbacks_del(ptr); } nghttp2_session_callbacks(const nghttp2_session_callbacks&) = delete; nghttp2_session_callbacks& operator=(const nghttp2_session_callbacks&) = delete; nghttp2_session_callbacks(nghttp2_session_callbacks&&) = delete; nghttp2_session_callbacks& operator=(nghttp2_session_callbacks&&) = delete; void setSendCallback(nghttp2_send_callback sendCallback) { nghttp2_session_callbacks_set_send_callback(ptr, sendCallback); } void setOnFrameRecvCallback(nghttp2_on_frame_recv_callback recvCallback) { nghttp2_session_callbacks_set_on_frame_recv_callback(ptr, recvCallback); } void setOnStreamCloseCallback(nghttp2_on_stream_close_callback onClose) { nghttp2_session_callbacks_set_on_stream_close_callback(ptr, onClose); } void setOnHeaderCallback(nghttp2_on_header_callback onHeader) { nghttp2_session_callbacks_set_on_header_callback(ptr, onHeader); } void setOnBeginHeadersCallback( nghttp2_on_begin_headers_callback onBeginHeaders) { nghttp2_session_callbacks_set_on_begin_headers_callback(ptr, onBeginHeaders); } void setSendDataCallback(nghttp2_send_data_callback onSendData) { nghttp2_session_callbacks_set_send_data_callback(ptr, onSendData); } void setBeforeFrameSendCallback( nghttp2_before_frame_send_callback beforeSendFrame) { nghttp2_session_callbacks_set_before_frame_send_callback( ptr, beforeSendFrame); } void setAfterFrameSendCallback(nghttp2_on_frame_send_callback afterSendFrame) { nghttp2_session_callbacks_set_on_frame_send_callback(ptr, afterSendFrame); } void setAfterFrameNoSendCallback( nghttp2_on_frame_not_send_callback afterSendFrame) { nghttp2_session_callbacks_set_on_frame_not_send_callback( ptr, afterSendFrame); } void setOnDataChunkRecvCallback( nghttp2_on_data_chunk_recv_callback afterDataChunkRecv) { nghttp2_session_callbacks_set_on_data_chunk_recv_callback( ptr, afterDataChunkRecv); } private: nghttp2_session_callbacks* get() { return ptr; } nghttp2_session_callbacks* ptr = nullptr; }; struct nghttp2_session { explicit nghttp2_session(nghttp2_session_callbacks& callbacks) { if (nghttp2_session_server_new(&ptr, callbacks.get(), nullptr) != 0) { BMCWEB_LOG_ERROR("nghttp2_session_server_new failed"); return; } } ~nghttp2_session() { nghttp2_session_del(ptr); } // explicitly uncopyable nghttp2_session(const nghttp2_session&) = delete; nghttp2_session& operator=(const nghttp2_session&) = delete; nghttp2_session(nghttp2_session&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; } nghttp2_session& operator=(nghttp2_session&& other) noexcept = delete; int submitSettings(std::span iv) { return nghttp2_submit_settings(ptr, NGHTTP2_FLAG_NONE, iv.data(), iv.size()); } void setUserData(void* object) { nghttp2_session_set_user_data(ptr, object); } ssize_t memRecv(std::span buffer) { return nghttp2_session_mem_recv(ptr, buffer.data(), buffer.size()); } std::span memSend() { const uint8_t* bytes = nullptr; ssize_t size = nghttp2_session_mem_send(ptr, &bytes); return {bytes, static_cast(size)}; } int submitResponse(int32_t streamId, std::span headers, const nghttp2_data_provider* dataPrd) { return nghttp2_submit_response(ptr, streamId, headers.data(), headers.size(), dataPrd); } private: nghttp2_session* ptr = nullptr; }; struct nghttp2_hd_inflater_ex { nghttp2_hd_inflater* ptr = nullptr; public: nghttp2_hd_inflater_ex() { if (nghttp2_hd_inflate_new(&ptr) != 0) { BMCWEB_LOG_ERROR("nghttp2_hd_inflater_new failed"); } } ssize_t hd2(nghttp2_nv* nvOut, int* inflateFlags, const uint8_t* in, size_t inlen, int inFinal) { return nghttp2_hd_inflate_hd2(ptr, nvOut, inflateFlags, in, inlen, inFinal); } int endHeaders() { return nghttp2_hd_inflate_end_headers(ptr); } nghttp2_hd_inflater_ex(const nghttp2_hd_inflater_ex&) = delete; nghttp2_hd_inflater_ex& operator=(const nghttp2_hd_inflater_ex&) = delete; nghttp2_hd_inflater_ex& operator=(nghttp2_hd_inflater_ex&&) = delete; nghttp2_hd_inflater_ex(nghttp2_hd_inflater_ex&& other) = delete; ~nghttp2_hd_inflater_ex() { if (ptr != nullptr) { nghttp2_hd_inflate_del(ptr); } } }; // NOLINTEND(readability-identifier-naming, // readability-make-member-function-const)