xref: /openbmc/bmcweb/http/nghttp2_adapters.hpp (revision 1017ef80)
1 #pragma once
2 
3 extern "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 
16 struct nghttp2_session;
17 
18 struct 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 
87   private:
88     nghttp2_session_callbacks* get()
89     {
90         return ptr;
91     }
92 
93     nghttp2_session_callbacks* ptr = nullptr;
94 };
95 
96 struct nghttp2_session
97 {
98     explicit nghttp2_session(nghttp2_session_callbacks& callbacks)
99     {
100         if (nghttp2_session_server_new(&ptr, callbacks.get(), nullptr) != 0)
101         {
102             BMCWEB_LOG_ERROR << "nghttp2_session_server_new failed";
103             return;
104         }
105     }
106 
107     ~nghttp2_session()
108     {
109         nghttp2_session_del(ptr);
110     }
111 
112     // explicitly uncopyable
113     nghttp2_session(const nghttp2_session&) = delete;
114     nghttp2_session& operator=(const nghttp2_session&) = delete;
115 
116     nghttp2_session(nghttp2_session&& other) noexcept : ptr(other.ptr)
117     {
118         other.ptr = nullptr;
119     }
120 
121     nghttp2_session& operator=(nghttp2_session&& other) noexcept = delete;
122 
123     int submitSettings(std::span<nghttp2_settings_entry> iv)
124     {
125         return nghttp2_submit_settings(ptr, NGHTTP2_FLAG_NONE, iv.data(),
126                                        iv.size());
127     }
128     void setUserData(void* object)
129     {
130         nghttp2_session_set_user_data(ptr, object);
131     }
132 
133     ssize_t memRecv(std::span<const uint8_t> buffer)
134     {
135         return nghttp2_session_mem_recv(ptr, buffer.data(), buffer.size());
136     }
137 
138     ssize_t send()
139     {
140         return nghttp2_session_send(ptr);
141     }
142 
143     int submitResponse(int32_t streamId, std::span<const nghttp2_nv> headers,
144                        const nghttp2_data_provider* dataPrd)
145     {
146         return nghttp2_submit_response(ptr, streamId, headers.data(),
147                                        headers.size(), dataPrd);
148     }
149 
150   private:
151     nghttp2_session* ptr = nullptr;
152 };
153