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 <openssl/ssl.h> 41 42 #include <ev.h> 43 44 #include <nghttp2/nghttp2.h> 45 46 #include "http2.h" 47 #include "buffer.h" 48 #include "template.h" 49 #include "allocator.h" 50 51 namespace nghttp2 { 52 53 struct Config { 54 std::map<std::string, std::vector<std::string>> push; 55 std::map<std::string, std::string> mime_types; 56 Headers trailer; 57 std::string trailer_names; 58 std::string htdocs; 59 std::string host; 60 std::string private_key_file; 61 std::string cert_file; 62 std::string dh_param_file; 63 std::string address; 64 std::string mime_types_file; 65 ev_tstamp stream_read_timeout; 66 ev_tstamp stream_write_timeout; 67 void *data_ptr; 68 size_t padding; 69 size_t num_worker; 70 size_t max_concurrent_streams; 71 ssize_t header_table_size; 72 ssize_t encoder_header_table_size; 73 int window_bits; 74 int connection_window_bits; 75 uint16_t port; 76 bool verbose; 77 bool daemon; 78 bool verify_client; 79 bool no_tls; 80 bool error_gzip; 81 bool early_response; 82 bool hexdump; 83 bool echo_upload; 84 bool no_content_length; 85 bool ktls; 86 bool no_rfc7540_pri; 87 Config(); 88 ~Config(); 89 }; 90 91 class Http2Handler; 92 93 struct FileEntry { 94 FileEntry(std::string path, int64_t length, int64_t mtime, int fd, 95 const std::string *content_type, 96 const std::chrono::steady_clock::time_point &last_valid, 97 bool stale = false) pathFileEntry98 : path(std::move(path)), 99 length(length), 100 mtime(mtime), 101 last_valid(last_valid), 102 content_type(content_type), 103 dlnext(nullptr), 104 dlprev(nullptr), 105 fd(fd), 106 usecount(1), 107 stale(stale) {} 108 std::string path; 109 std::multimap<std::string, std::unique_ptr<FileEntry>>::iterator it; 110 int64_t length; 111 int64_t mtime; 112 std::chrono::steady_clock::time_point last_valid; 113 const std::string *content_type; 114 FileEntry *dlnext, *dlprev; 115 int fd; 116 int usecount; 117 bool stale; 118 }; 119 120 struct RequestHeader { 121 StringRef method; 122 StringRef scheme; 123 StringRef authority; 124 StringRef host; 125 StringRef path; 126 StringRef ims; 127 StringRef expect; 128 129 struct { 130 nghttp2_rcbuf *method; 131 nghttp2_rcbuf *scheme; 132 nghttp2_rcbuf *authority; 133 nghttp2_rcbuf *host; 134 nghttp2_rcbuf *path; 135 nghttp2_rcbuf *ims; 136 nghttp2_rcbuf *expect; 137 } rcbuf; 138 }; 139 140 struct Stream { 141 BlockAllocator balloc; 142 RequestHeader header; 143 Http2Handler *handler; 144 FileEntry *file_ent; 145 ev_timer rtimer; 146 ev_timer wtimer; 147 int64_t body_length; 148 int64_t body_offset; 149 // Total amount of bytes (sum of name and value length) used in 150 // headers. 151 size_t header_buffer_size; 152 int32_t stream_id; 153 bool echo_upload; 154 Stream(Http2Handler *handler, int32_t stream_id); 155 ~Stream(); 156 }; 157 158 class Sessions; 159 160 class Http2Handler { 161 public: 162 Http2Handler(Sessions *sessions, int fd, SSL *ssl, int64_t session_id); 163 ~Http2Handler(); 164 165 void remove_self(); 166 void start_settings_timer(); 167 int on_read(); 168 int on_write(); 169 int connection_made(); 170 int verify_npn_result(); 171 172 int submit_file_response(const StringRef &status, Stream *stream, 173 time_t last_modified, off_t file_length, 174 const std::string *content_type, 175 nghttp2_data_provider *data_prd); 176 177 int submit_response(const StringRef &status, int32_t stream_id, 178 nghttp2_data_provider *data_prd); 179 180 int submit_response(const StringRef &status, int32_t stream_id, 181 const HeaderRefs &headers, 182 nghttp2_data_provider *data_prd); 183 184 int submit_non_final_response(const std::string &status, int32_t stream_id); 185 186 int submit_push_promise(Stream *stream, const StringRef &push_path); 187 188 int submit_rst_stream(Stream *stream, uint32_t error_code); 189 190 void add_stream(int32_t stream_id, std::unique_ptr<Stream> stream); 191 void remove_stream(int32_t stream_id); 192 Stream *get_stream(int32_t stream_id); 193 int64_t session_id() const; 194 Sessions *get_sessions() const; 195 const Config *get_config() const; 196 void remove_settings_timer(); 197 void terminate_session(uint32_t error_code); 198 199 int fill_wb(); 200 201 int read_clear(); 202 int write_clear(); 203 int tls_handshake(); 204 int read_tls(); 205 int write_tls(); 206 207 struct ev_loop *get_loop() const; 208 209 using WriteBuf = Buffer<64_k>; 210 211 WriteBuf *get_wb(); 212 213 private: 214 ev_io wev_; 215 ev_io rev_; 216 ev_timer settings_timerev_; 217 std::map<int32_t, std::unique_ptr<Stream>> id2stream_; 218 WriteBuf wb_; 219 std::function<int(Http2Handler &)> read_, write_; 220 int64_t session_id_; 221 nghttp2_session *session_; 222 Sessions *sessions_; 223 SSL *ssl_; 224 const uint8_t *data_pending_; 225 size_t data_pendinglen_; 226 int fd_; 227 }; 228 229 struct StatusPage { 230 std::string status; 231 FileEntry file_ent; 232 }; 233 234 class HttpServer { 235 public: 236 HttpServer(const Config *config); 237 int listen(); 238 int run(); 239 const Config *get_config() const; 240 const StatusPage *get_status_page(int status) const; 241 242 private: 243 std::vector<StatusPage> status_pages_; 244 const Config *config_; 245 }; 246 247 ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, 248 uint8_t *buf, size_t length, uint32_t *data_flags, 249 nghttp2_data_source *source, void *user_data); 250 251 } // namespace nghttp2 252 253 #endif // HTTP_SERVER_H 254