140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3fca2cbeaSEd Tanous #pragma once 4fca2cbeaSEd Tanous 5fca2cbeaSEd Tanous extern "C" 6fca2cbeaSEd Tanous { 7fca2cbeaSEd Tanous #include <nghttp2/nghttp2.h> 8fca2cbeaSEd Tanous } 9fca2cbeaSEd Tanous 10fca2cbeaSEd Tanous #include "logging.hpp" 11fca2cbeaSEd Tanous 12*cd7dbb30SEd Tanous #include <bit> 13fca2cbeaSEd Tanous #include <span> 14*cd7dbb30SEd Tanous #include <string_view> 15fca2cbeaSEd Tanous 16fca2cbeaSEd Tanous /* This file contains RAII compatible adapters for nghttp2 structures. They 17fca2cbeaSEd Tanous * attempt to be as close to a direct call as possible, while keeping the RAII 18a93163aaSEd Tanous * lifetime safety for the various classes. Because of this, they use the same 19a93163aaSEd Tanous * naming as nghttp2, so ignore naming violations. 20a93163aaSEd Tanous */ 21a93163aaSEd Tanous 22a93163aaSEd Tanous // NOLINTBEGIN(readability-identifier-naming, 23a93163aaSEd Tanous // readability-make-member-function-const) 24fca2cbeaSEd Tanous 25fca2cbeaSEd Tanous struct nghttp2_session; 26fca2cbeaSEd Tanous 27fca2cbeaSEd Tanous struct nghttp2_session_callbacks 28fca2cbeaSEd Tanous { 29fca2cbeaSEd Tanous friend nghttp2_session; nghttp2_session_callbacksnghttp2_session_callbacks30fca2cbeaSEd Tanous nghttp2_session_callbacks() 31fca2cbeaSEd Tanous { 32fca2cbeaSEd Tanous nghttp2_session_callbacks_new(&ptr); 33fca2cbeaSEd Tanous } 34fca2cbeaSEd Tanous ~nghttp2_session_callbacksnghttp2_session_callbacks35fca2cbeaSEd Tanous ~nghttp2_session_callbacks() 36fca2cbeaSEd Tanous { 37fca2cbeaSEd Tanous nghttp2_session_callbacks_del(ptr); 38fca2cbeaSEd Tanous } 39fca2cbeaSEd Tanous 40fca2cbeaSEd Tanous nghttp2_session_callbacks(const nghttp2_session_callbacks&) = delete; 41504af5a0SPatrick Williams nghttp2_session_callbacks& operator=(const nghttp2_session_callbacks&) = 42504af5a0SPatrick Williams delete; 43fca2cbeaSEd Tanous nghttp2_session_callbacks(nghttp2_session_callbacks&&) = delete; 44fca2cbeaSEd Tanous nghttp2_session_callbacks& operator=(nghttp2_session_callbacks&&) = delete; 45fca2cbeaSEd Tanous setSendCallbacknghttp2_session_callbacks46fca2cbeaSEd Tanous void setSendCallback(nghttp2_send_callback sendCallback) 47fca2cbeaSEd Tanous { 48fca2cbeaSEd Tanous nghttp2_session_callbacks_set_send_callback(ptr, sendCallback); 49fca2cbeaSEd Tanous } 50fca2cbeaSEd Tanous setOnFrameRecvCallbacknghttp2_session_callbacks51fca2cbeaSEd Tanous void setOnFrameRecvCallback(nghttp2_on_frame_recv_callback recvCallback) 52fca2cbeaSEd Tanous { 53fca2cbeaSEd Tanous nghttp2_session_callbacks_set_on_frame_recv_callback(ptr, recvCallback); 54fca2cbeaSEd Tanous } 55fca2cbeaSEd Tanous setOnStreamCloseCallbacknghttp2_session_callbacks56fca2cbeaSEd Tanous void setOnStreamCloseCallback(nghttp2_on_stream_close_callback onClose) 57fca2cbeaSEd Tanous { 58fca2cbeaSEd Tanous nghttp2_session_callbacks_set_on_stream_close_callback(ptr, onClose); 59fca2cbeaSEd Tanous } 60fca2cbeaSEd Tanous setOnHeaderCallbacknghttp2_session_callbacks61fca2cbeaSEd Tanous void setOnHeaderCallback(nghttp2_on_header_callback onHeader) 62fca2cbeaSEd Tanous { 63fca2cbeaSEd Tanous nghttp2_session_callbacks_set_on_header_callback(ptr, onHeader); 64fca2cbeaSEd Tanous } 65fca2cbeaSEd Tanous setOnBeginHeadersCallbacknghttp2_session_callbacks66fca2cbeaSEd Tanous void setOnBeginHeadersCallback( 67fca2cbeaSEd Tanous nghttp2_on_begin_headers_callback onBeginHeaders) 68fca2cbeaSEd Tanous { 69bd79bce8SPatrick Williams nghttp2_session_callbacks_set_on_begin_headers_callback( 70bd79bce8SPatrick Williams ptr, onBeginHeaders); 71fca2cbeaSEd Tanous } 72fca2cbeaSEd Tanous setSendDataCallbacknghttp2_session_callbacks73fca2cbeaSEd Tanous void setSendDataCallback(nghttp2_send_data_callback onSendData) 74fca2cbeaSEd Tanous { 75fca2cbeaSEd Tanous nghttp2_session_callbacks_set_send_data_callback(ptr, onSendData); 76fca2cbeaSEd Tanous } setBeforeFrameSendCallbacknghttp2_session_callbacks77fca2cbeaSEd Tanous void setBeforeFrameSendCallback( 78fca2cbeaSEd Tanous nghttp2_before_frame_send_callback beforeSendFrame) 79fca2cbeaSEd Tanous { 80fca2cbeaSEd Tanous nghttp2_session_callbacks_set_before_frame_send_callback( 81fca2cbeaSEd Tanous ptr, beforeSendFrame); 82fca2cbeaSEd Tanous } setAfterFrameSendCallbacknghttp2_session_callbacks83504af5a0SPatrick Williams void setAfterFrameSendCallback( 84504af5a0SPatrick Williams nghttp2_on_frame_send_callback afterSendFrame) 85fca2cbeaSEd Tanous { 86fca2cbeaSEd Tanous nghttp2_session_callbacks_set_on_frame_send_callback(ptr, 87fca2cbeaSEd Tanous afterSendFrame); 88fca2cbeaSEd Tanous } setAfterFrameNoSendCallbacknghttp2_session_callbacks89fca2cbeaSEd Tanous void setAfterFrameNoSendCallback( 90fca2cbeaSEd Tanous nghttp2_on_frame_not_send_callback afterSendFrame) 91fca2cbeaSEd Tanous { 92fca2cbeaSEd Tanous nghttp2_session_callbacks_set_on_frame_not_send_callback( 93fca2cbeaSEd Tanous ptr, afterSendFrame); 94fca2cbeaSEd Tanous } 95fca2cbeaSEd Tanous setOnDataChunkRecvCallbacknghttp2_session_callbacks96325310d3SEd Tanous void setOnDataChunkRecvCallback( 97325310d3SEd Tanous nghttp2_on_data_chunk_recv_callback afterDataChunkRecv) 98325310d3SEd Tanous { 99325310d3SEd Tanous nghttp2_session_callbacks_set_on_data_chunk_recv_callback( 100325310d3SEd Tanous ptr, afterDataChunkRecv); 101325310d3SEd Tanous } 102325310d3SEd Tanous 103fca2cbeaSEd Tanous private: getnghttp2_session_callbacks104fca2cbeaSEd Tanous nghttp2_session_callbacks* get() 105fca2cbeaSEd Tanous { 106fca2cbeaSEd Tanous return ptr; 107fca2cbeaSEd Tanous } 108fca2cbeaSEd Tanous 109fca2cbeaSEd Tanous nghttp2_session_callbacks* ptr = nullptr; 110fca2cbeaSEd Tanous }; 111fca2cbeaSEd Tanous 112fca2cbeaSEd Tanous struct nghttp2_session 113fca2cbeaSEd Tanous { nghttp2_sessionnghttp2_session114fca2cbeaSEd Tanous explicit nghttp2_session(nghttp2_session_callbacks& callbacks) 115fca2cbeaSEd Tanous { 116fca2cbeaSEd Tanous if (nghttp2_session_server_new(&ptr, callbacks.get(), nullptr) != 0) 117fca2cbeaSEd Tanous { 11862598e31SEd Tanous BMCWEB_LOG_ERROR("nghttp2_session_server_new failed"); 119fca2cbeaSEd Tanous return; 120fca2cbeaSEd Tanous } 121fca2cbeaSEd Tanous } 122fca2cbeaSEd Tanous ~nghttp2_sessionnghttp2_session123fca2cbeaSEd Tanous ~nghttp2_session() 124fca2cbeaSEd Tanous { 125fca2cbeaSEd Tanous nghttp2_session_del(ptr); 126fca2cbeaSEd Tanous } 127fca2cbeaSEd Tanous 128fca2cbeaSEd Tanous // explicitly uncopyable 129fca2cbeaSEd Tanous nghttp2_session(const nghttp2_session&) = delete; 130fca2cbeaSEd Tanous nghttp2_session& operator=(const nghttp2_session&) = delete; 131fca2cbeaSEd Tanous nghttp2_sessionnghttp2_session132fca2cbeaSEd Tanous nghttp2_session(nghttp2_session&& other) noexcept : ptr(other.ptr) 133fca2cbeaSEd Tanous { 134fca2cbeaSEd Tanous other.ptr = nullptr; 135fca2cbeaSEd Tanous } 136fca2cbeaSEd Tanous 137fca2cbeaSEd Tanous nghttp2_session& operator=(nghttp2_session&& other) noexcept = delete; 138fca2cbeaSEd Tanous submitSettingsnghttp2_session139fca2cbeaSEd Tanous int submitSettings(std::span<nghttp2_settings_entry> iv) 140fca2cbeaSEd Tanous { 141fca2cbeaSEd Tanous return nghttp2_submit_settings(ptr, NGHTTP2_FLAG_NONE, iv.data(), 142fca2cbeaSEd Tanous iv.size()); 143fca2cbeaSEd Tanous } 144*cd7dbb30SEd Tanous sessionUpgrade2nghttp2_session145*cd7dbb30SEd Tanous int sessionUpgrade2(std::string_view settingsPayload, bool headRequest) 146*cd7dbb30SEd Tanous { 147*cd7dbb30SEd Tanous return nghttp2_session_upgrade2( 148*cd7dbb30SEd Tanous ptr, std::bit_cast<uint8_t*>(settingsPayload.data()), 149*cd7dbb30SEd Tanous settingsPayload.size(), headRequest ? 1 : 0, nullptr); 150*cd7dbb30SEd Tanous } 151*cd7dbb30SEd Tanous setUserDatanghttp2_session152fca2cbeaSEd Tanous void setUserData(void* object) 153fca2cbeaSEd Tanous { 154fca2cbeaSEd Tanous nghttp2_session_set_user_data(ptr, object); 155fca2cbeaSEd Tanous } 156fca2cbeaSEd Tanous memRecvnghttp2_session157fca2cbeaSEd Tanous ssize_t memRecv(std::span<const uint8_t> buffer) 158fca2cbeaSEd Tanous { 159fca2cbeaSEd Tanous return nghttp2_session_mem_recv(ptr, buffer.data(), buffer.size()); 160fca2cbeaSEd Tanous } 161fca2cbeaSEd Tanous memSendnghttp2_session162d0882189SEd Tanous std::span<const uint8_t> memSend() 163fca2cbeaSEd Tanous { 164d0882189SEd Tanous const uint8_t* bytes = nullptr; 165d0882189SEd Tanous ssize_t size = nghttp2_session_mem_send(ptr, &bytes); 166d0882189SEd Tanous return {bytes, static_cast<size_t>(size)}; 167fca2cbeaSEd Tanous } 168fca2cbeaSEd Tanous submitResponsenghttp2_session169fca2cbeaSEd Tanous int submitResponse(int32_t streamId, std::span<const nghttp2_nv> headers, 170fca2cbeaSEd Tanous const nghttp2_data_provider* dataPrd) 171fca2cbeaSEd Tanous { 172fca2cbeaSEd Tanous return nghttp2_submit_response(ptr, streamId, headers.data(), 173fca2cbeaSEd Tanous headers.size(), dataPrd); 174fca2cbeaSEd Tanous } 175fca2cbeaSEd Tanous 176fca2cbeaSEd Tanous private: 177fca2cbeaSEd Tanous nghttp2_session* ptr = nullptr; 178fca2cbeaSEd Tanous }; 17952dd6932SEd Tanous 180a93163aaSEd Tanous struct nghttp2_hd_inflater_ex 18152dd6932SEd Tanous { 18252dd6932SEd Tanous nghttp2_hd_inflater* ptr = nullptr; 18352dd6932SEd Tanous 18452dd6932SEd Tanous public: nghttp2_hd_inflater_exnghttp2_hd_inflater_ex185a93163aaSEd Tanous nghttp2_hd_inflater_ex() 18652dd6932SEd Tanous { 18752dd6932SEd Tanous if (nghttp2_hd_inflate_new(&ptr) != 0) 18852dd6932SEd Tanous { 18952dd6932SEd Tanous BMCWEB_LOG_ERROR("nghttp2_hd_inflater_new failed"); 19052dd6932SEd Tanous } 19152dd6932SEd Tanous } 19252dd6932SEd Tanous hd2nghttp2_hd_inflater_ex19352dd6932SEd Tanous ssize_t hd2(nghttp2_nv* nvOut, int* inflateFlags, const uint8_t* in, 19452dd6932SEd Tanous size_t inlen, int inFinal) 19552dd6932SEd Tanous { 19652dd6932SEd Tanous return nghttp2_hd_inflate_hd2(ptr, nvOut, inflateFlags, in, inlen, 19752dd6932SEd Tanous inFinal); 19852dd6932SEd Tanous } 19952dd6932SEd Tanous endHeadersnghttp2_hd_inflater_ex20052dd6932SEd Tanous int endHeaders() 20152dd6932SEd Tanous { 20252dd6932SEd Tanous return nghttp2_hd_inflate_end_headers(ptr); 20352dd6932SEd Tanous } 20452dd6932SEd Tanous 205a93163aaSEd Tanous nghttp2_hd_inflater_ex(const nghttp2_hd_inflater_ex&) = delete; 206a93163aaSEd Tanous nghttp2_hd_inflater_ex& operator=(const nghttp2_hd_inflater_ex&) = delete; 207a93163aaSEd Tanous nghttp2_hd_inflater_ex& operator=(nghttp2_hd_inflater_ex&&) = delete; 208a93163aaSEd Tanous nghttp2_hd_inflater_ex(nghttp2_hd_inflater_ex&& other) = delete; 20952dd6932SEd Tanous ~nghttp2_hd_inflater_exnghttp2_hd_inflater_ex210a93163aaSEd Tanous ~nghttp2_hd_inflater_ex() 21152dd6932SEd Tanous { 21252dd6932SEd Tanous if (ptr != nullptr) 21352dd6932SEd Tanous { 21452dd6932SEd Tanous nghttp2_hd_inflate_del(ptr); 21552dd6932SEd Tanous } 21652dd6932SEd Tanous } 21752dd6932SEd Tanous }; 218a93163aaSEd Tanous // NOLINTEND(readability-identifier-naming, 219a93163aaSEd Tanous // readability-make-member-function-const) 220