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