blob: ff5e7083ad5a3df7b18eb8bf6d9dd94bb86a3490 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Ed Tanousfca2cbe2021-01-28 14:49:59 -08003#pragma once
4
5extern "C"
6{
7#include <nghttp2/nghttp2.h>
8}
9
10#include "logging.hpp"
11
Ed Tanouscd7dbb32025-02-01 12:37:56 -080012#include <bit>
Ed Tanousfca2cbe2021-01-28 14:49:59 -080013#include <span>
Ed Tanouscd7dbb32025-02-01 12:37:56 -080014#include <string_view>
Ed Tanousfca2cbe2021-01-28 14:49:59 -080015
16/* This file contains RAII compatible adapters for nghttp2 structures. They
17 * attempt to be as close to a direct call as possible, while keeping the RAII
Ed Tanousa93163a2024-03-25 11:20:18 -070018 * lifetime safety for the various classes. Because of this, they use the same
19 * naming as nghttp2, so ignore naming violations.
20 */
21
22// NOLINTBEGIN(readability-identifier-naming,
23// readability-make-member-function-const)
Ed Tanousfca2cbe2021-01-28 14:49:59 -080024
25struct nghttp2_session;
26
27struct nghttp2_session_callbacks
28{
29 friend nghttp2_session;
30 nghttp2_session_callbacks()
31 {
32 nghttp2_session_callbacks_new(&ptr);
33 }
34
35 ~nghttp2_session_callbacks()
36 {
37 nghttp2_session_callbacks_del(ptr);
38 }
39
40 nghttp2_session_callbacks(const nghttp2_session_callbacks&) = delete;
Patrick Williams504af5a2025-02-03 14:29:03 -050041 nghttp2_session_callbacks& operator=(const nghttp2_session_callbacks&) =
42 delete;
Ed Tanousfca2cbe2021-01-28 14:49:59 -080043 nghttp2_session_callbacks(nghttp2_session_callbacks&&) = delete;
44 nghttp2_session_callbacks& operator=(nghttp2_session_callbacks&&) = delete;
45
46 void setSendCallback(nghttp2_send_callback sendCallback)
47 {
48 nghttp2_session_callbacks_set_send_callback(ptr, sendCallback);
49 }
50
51 void setOnFrameRecvCallback(nghttp2_on_frame_recv_callback recvCallback)
52 {
53 nghttp2_session_callbacks_set_on_frame_recv_callback(ptr, recvCallback);
54 }
55
56 void setOnStreamCloseCallback(nghttp2_on_stream_close_callback onClose)
57 {
58 nghttp2_session_callbacks_set_on_stream_close_callback(ptr, onClose);
59 }
60
61 void setOnHeaderCallback(nghttp2_on_header_callback onHeader)
62 {
63 nghttp2_session_callbacks_set_on_header_callback(ptr, onHeader);
64 }
65
66 void setOnBeginHeadersCallback(
67 nghttp2_on_begin_headers_callback onBeginHeaders)
68 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040069 nghttp2_session_callbacks_set_on_begin_headers_callback(
70 ptr, onBeginHeaders);
Ed Tanousfca2cbe2021-01-28 14:49:59 -080071 }
72
73 void setSendDataCallback(nghttp2_send_data_callback onSendData)
74 {
75 nghttp2_session_callbacks_set_send_data_callback(ptr, onSendData);
76 }
77 void setBeforeFrameSendCallback(
78 nghttp2_before_frame_send_callback beforeSendFrame)
79 {
80 nghttp2_session_callbacks_set_before_frame_send_callback(
81 ptr, beforeSendFrame);
82 }
Patrick Williams504af5a2025-02-03 14:29:03 -050083 void setAfterFrameSendCallback(
84 nghttp2_on_frame_send_callback afterSendFrame)
Ed Tanousfca2cbe2021-01-28 14:49:59 -080085 {
86 nghttp2_session_callbacks_set_on_frame_send_callback(ptr,
87 afterSendFrame);
88 }
89 void setAfterFrameNoSendCallback(
90 nghttp2_on_frame_not_send_callback afterSendFrame)
91 {
92 nghttp2_session_callbacks_set_on_frame_not_send_callback(
93 ptr, afterSendFrame);
94 }
95
Ed Tanous325310d2024-03-15 09:05:04 -070096 void setOnDataChunkRecvCallback(
97 nghttp2_on_data_chunk_recv_callback afterDataChunkRecv)
98 {
99 nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
100 ptr, afterDataChunkRecv);
101 }
102
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800103 private:
104 nghttp2_session_callbacks* get()
105 {
106 return ptr;
107 }
108
109 nghttp2_session_callbacks* ptr = nullptr;
110};
111
112struct nghttp2_session
113{
114 explicit nghttp2_session(nghttp2_session_callbacks& callbacks)
115 {
116 if (nghttp2_session_server_new(&ptr, callbacks.get(), nullptr) != 0)
117 {
Ed Tanous62598e32023-07-17 17:06:25 -0700118 BMCWEB_LOG_ERROR("nghttp2_session_server_new failed");
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800119 return;
120 }
121 }
122
123 ~nghttp2_session()
124 {
125 nghttp2_session_del(ptr);
126 }
127
128 // explicitly uncopyable
129 nghttp2_session(const nghttp2_session&) = delete;
130 nghttp2_session& operator=(const nghttp2_session&) = delete;
131
132 nghttp2_session(nghttp2_session&& other) noexcept : ptr(other.ptr)
133 {
134 other.ptr = nullptr;
135 }
136
137 nghttp2_session& operator=(nghttp2_session&& other) noexcept = delete;
138
139 int submitSettings(std::span<nghttp2_settings_entry> iv)
140 {
141 return nghttp2_submit_settings(ptr, NGHTTP2_FLAG_NONE, iv.data(),
142 iv.size());
143 }
Ed Tanouscd7dbb32025-02-01 12:37:56 -0800144
145 int sessionUpgrade2(std::string_view settingsPayload, bool headRequest)
146 {
147 return nghttp2_session_upgrade2(
148 ptr, std::bit_cast<uint8_t*>(settingsPayload.data()),
149 settingsPayload.size(), headRequest ? 1 : 0, nullptr);
150 }
151
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800152 void setUserData(void* object)
153 {
154 nghttp2_session_set_user_data(ptr, object);
155 }
156
157 ssize_t memRecv(std::span<const uint8_t> buffer)
158 {
159 return nghttp2_session_mem_recv(ptr, buffer.data(), buffer.size());
160 }
161
Ed Tanousd0882182024-01-26 23:45:25 -0800162 std::span<const uint8_t> memSend()
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800163 {
Ed Tanousd0882182024-01-26 23:45:25 -0800164 const uint8_t* bytes = nullptr;
165 ssize_t size = nghttp2_session_mem_send(ptr, &bytes);
166 return {bytes, static_cast<size_t>(size)};
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800167 }
168
169 int submitResponse(int32_t streamId, std::span<const nghttp2_nv> headers,
170 const nghttp2_data_provider* dataPrd)
171 {
172 return nghttp2_submit_response(ptr, streamId, headers.data(),
173 headers.size(), dataPrd);
174 }
175
176 private:
177 nghttp2_session* ptr = nullptr;
178};
Ed Tanous52dd6932024-01-29 08:34:59 -0800179
Ed Tanousa93163a2024-03-25 11:20:18 -0700180struct nghttp2_hd_inflater_ex
Ed Tanous52dd6932024-01-29 08:34:59 -0800181{
182 nghttp2_hd_inflater* ptr = nullptr;
183
184 public:
Ed Tanousa93163a2024-03-25 11:20:18 -0700185 nghttp2_hd_inflater_ex()
Ed Tanous52dd6932024-01-29 08:34:59 -0800186 {
187 if (nghttp2_hd_inflate_new(&ptr) != 0)
188 {
189 BMCWEB_LOG_ERROR("nghttp2_hd_inflater_new failed");
190 }
191 }
192
193 ssize_t hd2(nghttp2_nv* nvOut, int* inflateFlags, const uint8_t* in,
194 size_t inlen, int inFinal)
195 {
196 return nghttp2_hd_inflate_hd2(ptr, nvOut, inflateFlags, in, inlen,
197 inFinal);
198 }
199
200 int endHeaders()
201 {
202 return nghttp2_hd_inflate_end_headers(ptr);
203 }
204
Ed Tanousa93163a2024-03-25 11:20:18 -0700205 nghttp2_hd_inflater_ex(const nghttp2_hd_inflater_ex&) = delete;
206 nghttp2_hd_inflater_ex& operator=(const nghttp2_hd_inflater_ex&) = delete;
207 nghttp2_hd_inflater_ex& operator=(nghttp2_hd_inflater_ex&&) = delete;
208 nghttp2_hd_inflater_ex(nghttp2_hd_inflater_ex&& other) = delete;
Ed Tanous52dd6932024-01-29 08:34:59 -0800209
Ed Tanousa93163a2024-03-25 11:20:18 -0700210 ~nghttp2_hd_inflater_ex()
Ed Tanous52dd6932024-01-29 08:34:59 -0800211 {
212 if (ptr != nullptr)
213 {
214 nghttp2_hd_inflate_del(ptr);
215 }
216 }
217};
Ed Tanousa93163a2024-03-25 11:20:18 -0700218// NOLINTEND(readability-identifier-naming,
219// readability-make-member-function-const)