xref: /openbmc/bmcweb/http/nghttp2_adapters.hpp (revision cd7dbb308f3e867e70a4e6de7880f889e8556eb7)
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