blob: 61e45df37eaadf90c0615cee2c3fa168fb08f45d [file] [log] [blame]
Ed Tanousfca2cbe2021-01-28 14:49:59 -08001#pragma once
2
3extern "C"
4{
5#include <nghttp2/nghttp2.h>
6}
7
8#include "logging.hpp"
9
10#include <span>
11
12/* This file contains RAII compatible adapters for nghttp2 structures. They
13 * attempt to be as close to a direct call as possible, while keeping the RAII
Ed Tanousa93163a2024-03-25 11:20:18 -070014 * lifetime safety for the various classes. Because of this, they use the same
15 * naming as nghttp2, so ignore naming violations.
16 */
17
18// NOLINTBEGIN(readability-identifier-naming,
19// readability-make-member-function-const)
Ed Tanousfca2cbe2021-01-28 14:49:59 -080020
21struct nghttp2_session;
22
23struct nghttp2_session_callbacks
24{
25 friend nghttp2_session;
26 nghttp2_session_callbacks()
27 {
28 nghttp2_session_callbacks_new(&ptr);
29 }
30
31 ~nghttp2_session_callbacks()
32 {
33 nghttp2_session_callbacks_del(ptr);
34 }
35
36 nghttp2_session_callbacks(const nghttp2_session_callbacks&) = delete;
37 nghttp2_session_callbacks&
38 operator=(const nghttp2_session_callbacks&) = delete;
39 nghttp2_session_callbacks(nghttp2_session_callbacks&&) = delete;
40 nghttp2_session_callbacks& operator=(nghttp2_session_callbacks&&) = delete;
41
42 void setSendCallback(nghttp2_send_callback sendCallback)
43 {
44 nghttp2_session_callbacks_set_send_callback(ptr, sendCallback);
45 }
46
47 void setOnFrameRecvCallback(nghttp2_on_frame_recv_callback recvCallback)
48 {
49 nghttp2_session_callbacks_set_on_frame_recv_callback(ptr, recvCallback);
50 }
51
52 void setOnStreamCloseCallback(nghttp2_on_stream_close_callback onClose)
53 {
54 nghttp2_session_callbacks_set_on_stream_close_callback(ptr, onClose);
55 }
56
57 void setOnHeaderCallback(nghttp2_on_header_callback onHeader)
58 {
59 nghttp2_session_callbacks_set_on_header_callback(ptr, onHeader);
60 }
61
62 void setOnBeginHeadersCallback(
63 nghttp2_on_begin_headers_callback onBeginHeaders)
64 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040065 nghttp2_session_callbacks_set_on_begin_headers_callback(
66 ptr, onBeginHeaders);
Ed Tanousfca2cbe2021-01-28 14:49:59 -080067 }
68
69 void setSendDataCallback(nghttp2_send_data_callback onSendData)
70 {
71 nghttp2_session_callbacks_set_send_data_callback(ptr, onSendData);
72 }
73 void setBeforeFrameSendCallback(
74 nghttp2_before_frame_send_callback beforeSendFrame)
75 {
76 nghttp2_session_callbacks_set_before_frame_send_callback(
77 ptr, beforeSendFrame);
78 }
79 void
80 setAfterFrameSendCallback(nghttp2_on_frame_send_callback afterSendFrame)
81 {
82 nghttp2_session_callbacks_set_on_frame_send_callback(ptr,
83 afterSendFrame);
84 }
85 void setAfterFrameNoSendCallback(
86 nghttp2_on_frame_not_send_callback afterSendFrame)
87 {
88 nghttp2_session_callbacks_set_on_frame_not_send_callback(
89 ptr, afterSendFrame);
90 }
91
Ed Tanous325310d2024-03-15 09:05:04 -070092 void setOnDataChunkRecvCallback(
93 nghttp2_on_data_chunk_recv_callback afterDataChunkRecv)
94 {
95 nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
96 ptr, afterDataChunkRecv);
97 }
98
Ed Tanousfca2cbe2021-01-28 14:49:59 -080099 private:
100 nghttp2_session_callbacks* get()
101 {
102 return ptr;
103 }
104
105 nghttp2_session_callbacks* ptr = nullptr;
106};
107
108struct nghttp2_session
109{
110 explicit nghttp2_session(nghttp2_session_callbacks& callbacks)
111 {
112 if (nghttp2_session_server_new(&ptr, callbacks.get(), nullptr) != 0)
113 {
Ed Tanous62598e32023-07-17 17:06:25 -0700114 BMCWEB_LOG_ERROR("nghttp2_session_server_new failed");
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800115 return;
116 }
117 }
118
119 ~nghttp2_session()
120 {
121 nghttp2_session_del(ptr);
122 }
123
124 // explicitly uncopyable
125 nghttp2_session(const nghttp2_session&) = delete;
126 nghttp2_session& operator=(const nghttp2_session&) = delete;
127
128 nghttp2_session(nghttp2_session&& other) noexcept : ptr(other.ptr)
129 {
130 other.ptr = nullptr;
131 }
132
133 nghttp2_session& operator=(nghttp2_session&& other) noexcept = delete;
134
135 int submitSettings(std::span<nghttp2_settings_entry> iv)
136 {
137 return nghttp2_submit_settings(ptr, NGHTTP2_FLAG_NONE, iv.data(),
138 iv.size());
139 }
140 void setUserData(void* object)
141 {
142 nghttp2_session_set_user_data(ptr, object);
143 }
144
145 ssize_t memRecv(std::span<const uint8_t> buffer)
146 {
147 return nghttp2_session_mem_recv(ptr, buffer.data(), buffer.size());
148 }
149
Ed Tanousd0882182024-01-26 23:45:25 -0800150 std::span<const uint8_t> memSend()
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800151 {
Ed Tanousd0882182024-01-26 23:45:25 -0800152 const uint8_t* bytes = nullptr;
153 ssize_t size = nghttp2_session_mem_send(ptr, &bytes);
154 return {bytes, static_cast<size_t>(size)};
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800155 }
156
157 int submitResponse(int32_t streamId, std::span<const nghttp2_nv> headers,
158 const nghttp2_data_provider* dataPrd)
159 {
160 return nghttp2_submit_response(ptr, streamId, headers.data(),
161 headers.size(), dataPrd);
162 }
163
164 private:
165 nghttp2_session* ptr = nullptr;
166};
Ed Tanous52dd6932024-01-29 08:34:59 -0800167
Ed Tanousa93163a2024-03-25 11:20:18 -0700168struct nghttp2_hd_inflater_ex
Ed Tanous52dd6932024-01-29 08:34:59 -0800169{
170 nghttp2_hd_inflater* ptr = nullptr;
171
172 public:
Ed Tanousa93163a2024-03-25 11:20:18 -0700173 nghttp2_hd_inflater_ex()
Ed Tanous52dd6932024-01-29 08:34:59 -0800174 {
175 if (nghttp2_hd_inflate_new(&ptr) != 0)
176 {
177 BMCWEB_LOG_ERROR("nghttp2_hd_inflater_new failed");
178 }
179 }
180
181 ssize_t hd2(nghttp2_nv* nvOut, int* inflateFlags, const uint8_t* in,
182 size_t inlen, int inFinal)
183 {
184 return nghttp2_hd_inflate_hd2(ptr, nvOut, inflateFlags, in, inlen,
185 inFinal);
186 }
187
188 int endHeaders()
189 {
190 return nghttp2_hd_inflate_end_headers(ptr);
191 }
192
Ed Tanousa93163a2024-03-25 11:20:18 -0700193 nghttp2_hd_inflater_ex(const nghttp2_hd_inflater_ex&) = delete;
194 nghttp2_hd_inflater_ex& operator=(const nghttp2_hd_inflater_ex&) = delete;
195 nghttp2_hd_inflater_ex& operator=(nghttp2_hd_inflater_ex&&) = delete;
196 nghttp2_hd_inflater_ex(nghttp2_hd_inflater_ex&& other) = delete;
Ed Tanous52dd6932024-01-29 08:34:59 -0800197
Ed Tanousa93163a2024-03-25 11:20:18 -0700198 ~nghttp2_hd_inflater_ex()
Ed Tanous52dd6932024-01-29 08:34:59 -0800199 {
200 if (ptr != nullptr)
201 {
202 nghttp2_hd_inflate_del(ptr);
203 }
204 }
205};
Ed Tanousa93163a2024-03-25 11:20:18 -0700206// NOLINTEND(readability-identifier-naming,
207// readability-make-member-function-const)