1 /* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2013 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #ifndef HTTP_SERVER_H 26 #define HTTP_SERVER_H 27 28 #include "nghttp2_config.h" 29 30 #include <sys/types.h> 31 32 #include <cinttypes> 33 #include <cstdlib> 34 35 #include <string> 36 #include <vector> 37 #include <map> 38 #include <memory> 39 40 #include "ssl_compat.h" 41 42 #ifdef NGHTTP2_OPENSSL_IS_WOLFSSL 43 # include <wolfssl/options.h> 44 # include <wolfssl/openssl/ssl.h> 45 #else // !NGHTTP2_OPENSSL_IS_WOLFSSL 46 # include <openssl/ssl.h> 47 #endif // !NGHTTP2_OPENSSL_IS_WOLFSSL 48 49 #include <ev.h> 50 51 #define NGHTTP2_NO_SSIZE_T 52 #include <nghttp2/nghttp2.h> 53 54 #include "http2.h" 55 #include "buffer.h" 56 #include "template.h" 57 #include "allocator.h" 58 59 namespace nghttp2 { 60 61 struct Config { 62 std::map<std::string, std::vector<std::string>> push; 63 std::map<std::string, std::string> mime_types; 64 Headers trailer; 65 std::string trailer_names; 66 std::string htdocs; 67 std::string host; 68 std::string private_key_file; 69 std::string cert_file; 70 std::string dh_param_file; 71 std::string address; 72 std::string mime_types_file; 73 ev_tstamp stream_read_timeout; 74 ev_tstamp stream_write_timeout; 75 void *data_ptr; 76 size_t padding; 77 size_t num_worker; 78 size_t max_concurrent_streams; 79 ssize_t header_table_size; 80 ssize_t encoder_header_table_size; 81 int window_bits; 82 int connection_window_bits; 83 uint16_t port; 84 bool verbose; 85 bool daemon; 86 bool verify_client; 87 bool no_tls; 88 bool error_gzip; 89 bool early_response; 90 bool hexdump; 91 bool echo_upload; 92 bool no_content_length; 93 bool ktls; 94 bool no_rfc7540_pri; 95 Config(); 96 ~Config(); 97 }; 98 99 class Http2Handler; 100 101 struct FileEntry { 102 FileEntry(std::string path, int64_t length, int64_t mtime, int fd, 103 const std::string *content_type, 104 const std::chrono::steady_clock::time_point &last_valid, 105 bool stale = false) pathFileEntry106 : path(std::move(path)), 107 length(length), 108 mtime(mtime), 109 last_valid(last_valid), 110 content_type(content_type), 111 dlnext(nullptr), 112 dlprev(nullptr), 113 fd(fd), 114 usecount(1), 115 stale(stale) {} 116 std::string path; 117 std::multimap<std::string, std::unique_ptr<FileEntry>>::iterator it; 118 int64_t length; 119 int64_t mtime; 120 std::chrono::steady_clock::time_point last_valid; 121 const std::string *content_type; 122 FileEntry *dlnext, *dlprev; 123 int fd; 124 int usecount; 125 bool stale; 126 }; 127 128 struct RequestHeader { 129 StringRef method; 130 StringRef scheme; 131 StringRef authority; 132 StringRef host; 133 StringRef path; 134 StringRef ims; 135 StringRef expect; 136 137 struct { 138 nghttp2_rcbuf *method; 139 nghttp2_rcbuf *scheme; 140 nghttp2_rcbuf *authority; 141 nghttp2_rcbuf *host; 142 nghttp2_rcbuf *path; 143 nghttp2_rcbuf *ims; 144 nghttp2_rcbuf *expect; 145 } rcbuf; 146 }; 147 148 struct Stream { 149 BlockAllocator balloc; 150 RequestHeader header; 151 Http2Handler *handler; 152 FileEntry *file_ent; 153 ev_timer rtimer; 154 ev_timer wtimer; 155 int64_t body_length; 156 int64_t body_offset; 157 // Total amount of bytes (sum of name and value length) used in 158 // headers. 159 size_t header_buffer_size; 160 int32_t stream_id; 161 bool echo_upload; 162 Stream(Http2Handler *handler, int32_t stream_id); 163 ~Stream(); 164 }; 165 166 class Sessions; 167 168 class Http2Handler { 169 public: 170 Http2Handler(Sessions *sessions, int fd, SSL *ssl, int64_t session_id); 171 ~Http2Handler(); 172 173 void remove_self(); 174 void start_settings_timer(); 175 int on_read(); 176 int on_write(); 177 int connection_made(); 178 int verify_alpn_result(); 179 180 int submit_file_response(const StringRef &status, Stream *stream, 181 time_t last_modified, off_t file_length, 182 const std::string *content_type, 183 nghttp2_data_provider2 *data_prd); 184 185 int submit_response(const StringRef &status, int32_t stream_id, 186 nghttp2_data_provider2 *data_prd); 187 188 int submit_response(const StringRef &status, int32_t stream_id, 189 const HeaderRefs &headers, 190 nghttp2_data_provider2 *data_prd); 191 192 int submit_non_final_response(const std::string &status, int32_t stream_id); 193 194 int submit_push_promise(Stream *stream, const StringRef &push_path); 195 196 int submit_rst_stream(Stream *stream, uint32_t error_code); 197 198 void add_stream(int32_t stream_id, std::unique_ptr<Stream> stream); 199 void remove_stream(int32_t stream_id); 200 Stream *get_stream(int32_t stream_id); 201 int64_t session_id() const; 202 Sessions *get_sessions() const; 203 const Config *get_config() const; 204 void remove_settings_timer(); 205 void terminate_session(uint32_t error_code); 206 207 int fill_wb(); 208 209 int read_clear(); 210 int write_clear(); 211 int tls_handshake(); 212 int read_tls(); 213 int write_tls(); 214 215 struct ev_loop *get_loop() const; 216 217 using WriteBuf = Buffer<64_k>; 218 219 WriteBuf *get_wb(); 220 221 private: 222 ev_io wev_; 223 ev_io rev_; 224 ev_timer settings_timerev_; 225 std::map<int32_t, std::unique_ptr<Stream>> id2stream_; 226 WriteBuf wb_; 227 std::function<int(Http2Handler &)> read_, write_; 228 int64_t session_id_; 229 nghttp2_session *session_; 230 Sessions *sessions_; 231 SSL *ssl_; 232 const uint8_t *data_pending_; 233 size_t data_pendinglen_; 234 int fd_; 235 }; 236 237 struct StatusPage { 238 std::string status; 239 FileEntry file_ent; 240 }; 241 242 class HttpServer { 243 public: 244 HttpServer(const Config *config); 245 int listen(); 246 int run(); 247 const Config *get_config() const; 248 const StatusPage *get_status_page(int status) const; 249 250 private: 251 std::vector<StatusPage> status_pages_; 252 const Config *config_; 253 }; 254 255 nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id, 256 uint8_t *buf, size_t length, 257 uint32_t *data_flags, 258 nghttp2_data_source *source, void *user_data); 259 260 } // namespace nghttp2 261 262 #endif // HTTP_SERVER_H 263