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