blob: 3235372157864170c79680a561f3bf76d5f4d22f [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
14 * lifetime safety for the various classes.*/
15
16struct nghttp2_session;
17
18struct nghttp2_session_callbacks
19{
20 friend nghttp2_session;
21 nghttp2_session_callbacks()
22 {
23 nghttp2_session_callbacks_new(&ptr);
24 }
25
26 ~nghttp2_session_callbacks()
27 {
28 nghttp2_session_callbacks_del(ptr);
29 }
30
31 nghttp2_session_callbacks(const nghttp2_session_callbacks&) = delete;
32 nghttp2_session_callbacks&
33 operator=(const nghttp2_session_callbacks&) = delete;
34 nghttp2_session_callbacks(nghttp2_session_callbacks&&) = delete;
35 nghttp2_session_callbacks& operator=(nghttp2_session_callbacks&&) = delete;
36
37 void setSendCallback(nghttp2_send_callback sendCallback)
38 {
39 nghttp2_session_callbacks_set_send_callback(ptr, sendCallback);
40 }
41
42 void setOnFrameRecvCallback(nghttp2_on_frame_recv_callback recvCallback)
43 {
44 nghttp2_session_callbacks_set_on_frame_recv_callback(ptr, recvCallback);
45 }
46
47 void setOnStreamCloseCallback(nghttp2_on_stream_close_callback onClose)
48 {
49 nghttp2_session_callbacks_set_on_stream_close_callback(ptr, onClose);
50 }
51
52 void setOnHeaderCallback(nghttp2_on_header_callback onHeader)
53 {
54 nghttp2_session_callbacks_set_on_header_callback(ptr, onHeader);
55 }
56
57 void setOnBeginHeadersCallback(
58 nghttp2_on_begin_headers_callback onBeginHeaders)
59 {
60 nghttp2_session_callbacks_set_on_begin_headers_callback(ptr,
61 onBeginHeaders);
62 }
63
64 void setSendDataCallback(nghttp2_send_data_callback onSendData)
65 {
66 nghttp2_session_callbacks_set_send_data_callback(ptr, onSendData);
67 }
68 void setBeforeFrameSendCallback(
69 nghttp2_before_frame_send_callback beforeSendFrame)
70 {
71 nghttp2_session_callbacks_set_before_frame_send_callback(
72 ptr, beforeSendFrame);
73 }
74 void
75 setAfterFrameSendCallback(nghttp2_on_frame_send_callback afterSendFrame)
76 {
77 nghttp2_session_callbacks_set_on_frame_send_callback(ptr,
78 afterSendFrame);
79 }
80 void setAfterFrameNoSendCallback(
81 nghttp2_on_frame_not_send_callback afterSendFrame)
82 {
83 nghttp2_session_callbacks_set_on_frame_not_send_callback(
84 ptr, afterSendFrame);
85 }
86
Ed Tanous325310d2024-03-15 09:05:04 -070087 void setOnDataChunkRecvCallback(
88 nghttp2_on_data_chunk_recv_callback afterDataChunkRecv)
89 {
90 nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
91 ptr, afterDataChunkRecv);
92 }
93
Ed Tanousfca2cbe2021-01-28 14:49:59 -080094 private:
95 nghttp2_session_callbacks* get()
96 {
97 return ptr;
98 }
99
100 nghttp2_session_callbacks* ptr = nullptr;
101};
102
103struct nghttp2_session
104{
105 explicit nghttp2_session(nghttp2_session_callbacks& callbacks)
106 {
107 if (nghttp2_session_server_new(&ptr, callbacks.get(), nullptr) != 0)
108 {
Ed Tanous62598e32023-07-17 17:06:25 -0700109 BMCWEB_LOG_ERROR("nghttp2_session_server_new failed");
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800110 return;
111 }
112 }
113
114 ~nghttp2_session()
115 {
116 nghttp2_session_del(ptr);
117 }
118
119 // explicitly uncopyable
120 nghttp2_session(const nghttp2_session&) = delete;
121 nghttp2_session& operator=(const nghttp2_session&) = delete;
122
123 nghttp2_session(nghttp2_session&& other) noexcept : ptr(other.ptr)
124 {
125 other.ptr = nullptr;
126 }
127
128 nghttp2_session& operator=(nghttp2_session&& other) noexcept = delete;
129
130 int submitSettings(std::span<nghttp2_settings_entry> iv)
131 {
132 return nghttp2_submit_settings(ptr, NGHTTP2_FLAG_NONE, iv.data(),
133 iv.size());
134 }
135 void setUserData(void* object)
136 {
137 nghttp2_session_set_user_data(ptr, object);
138 }
139
140 ssize_t memRecv(std::span<const uint8_t> buffer)
141 {
142 return nghttp2_session_mem_recv(ptr, buffer.data(), buffer.size());
143 }
144
Ed Tanousd0882182024-01-26 23:45:25 -0800145 std::span<const uint8_t> memSend()
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800146 {
Ed Tanousd0882182024-01-26 23:45:25 -0800147 const uint8_t* bytes = nullptr;
148 ssize_t size = nghttp2_session_mem_send(ptr, &bytes);
149 return {bytes, static_cast<size_t>(size)};
Ed Tanousfca2cbe2021-01-28 14:49:59 -0800150 }
151
152 int submitResponse(int32_t streamId, std::span<const nghttp2_nv> headers,
153 const nghttp2_data_provider* dataPrd)
154 {
155 return nghttp2_submit_response(ptr, streamId, headers.data(),
156 headers.size(), dataPrd);
157 }
158
159 private:
160 nghttp2_session* ptr = nullptr;
161};
Ed Tanous52dd6932024-01-29 08:34:59 -0800162
163class nghttp2_hd_inflater
164{
165 nghttp2_hd_inflater* ptr = nullptr;
166
167 public:
168 nghttp2_hd_inflater()
169 {
170 if (nghttp2_hd_inflate_new(&ptr) != 0)
171 {
172 BMCWEB_LOG_ERROR("nghttp2_hd_inflater_new failed");
173 }
174 }
175
176 ssize_t hd2(nghttp2_nv* nvOut, int* inflateFlags, const uint8_t* in,
177 size_t inlen, int inFinal)
178 {
179 return nghttp2_hd_inflate_hd2(ptr, nvOut, inflateFlags, in, inlen,
180 inFinal);
181 }
182
183 int endHeaders()
184 {
185 return nghttp2_hd_inflate_end_headers(ptr);
186 }
187
188 nghttp2_hd_inflater(const nghttp2_hd_inflater&) = delete;
189 nghttp2_hd_inflater& operator=(const nghttp2_hd_inflater&) = delete;
190 nghttp2_hd_inflater& operator=(nghttp2_hd_inflater&&) = delete;
191 nghttp2_hd_inflater(nghttp2_hd_inflater&& other) = delete;
192
193 ~nghttp2_hd_inflater()
194 {
195 if (ptr != nullptr)
196 {
197 nghttp2_hd_inflate_del(ptr);
198 }
199 }
200};