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, ev_tstamp last_valid, 96 bool stale = false) pathFileEntry97 : path(std::move(path)), 98 length(length), 99 mtime(mtime), 100 last_valid(last_valid), 101 content_type(content_type), 102 dlnext(nullptr), 103 dlprev(nullptr), 104 fd(fd), 105 usecount(1), 106 stale(stale) {} 107 std::string path; 108 std::multimap<std::string, std::unique_ptr<FileEntry>>::iterator it; 109 int64_t length; 110 int64_t mtime; 111 ev_tstamp last_valid; 112 const std::string *content_type; 113 FileEntry *dlnext, *dlprev; 114 int fd; 115 int usecount; 116 bool stale; 117 }; 118 119 struct RequestHeader { 120 StringRef method; 121 StringRef scheme; 122 StringRef authority; 123 StringRef host; 124 StringRef path; 125 StringRef ims; 126 StringRef expect; 127 128 struct { 129 nghttp2_rcbuf *method; 130 nghttp2_rcbuf *scheme; 131 nghttp2_rcbuf *authority; 132 nghttp2_rcbuf *host; 133 nghttp2_rcbuf *path; 134 nghttp2_rcbuf *ims; 135 nghttp2_rcbuf *expect; 136 } rcbuf; 137 }; 138 139 struct Stream { 140 BlockAllocator balloc; 141 RequestHeader header; 142 Http2Handler *handler; 143 FileEntry *file_ent; 144 ev_timer rtimer; 145 ev_timer wtimer; 146 int64_t body_length; 147 int64_t body_offset; 148 // Total amount of bytes (sum of name and value length) used in 149 // headers. 150 size_t header_buffer_size; 151 int32_t stream_id; 152 bool echo_upload; 153 Stream(Http2Handler *handler, int32_t stream_id); 154 ~Stream(); 155 }; 156 157 class Sessions; 158 159 class Http2Handler { 160 public: 161 Http2Handler(Sessions *sessions, int fd, SSL *ssl, int64_t session_id); 162 ~Http2Handler(); 163 164 void remove_self(); 165 void start_settings_timer(); 166 int on_read(); 167 int on_write(); 168 int connection_made(); 169 int verify_npn_result(); 170 171 int submit_file_response(const StringRef &status, Stream *stream, 172 time_t last_modified, off_t file_length, 173 const std::string *content_type, 174 nghttp2_data_provider *data_prd); 175 176 int submit_response(const StringRef &status, int32_t stream_id, 177 nghttp2_data_provider *data_prd); 178 179 int submit_response(const StringRef &status, int32_t stream_id, 180 const HeaderRefs &headers, 181 nghttp2_data_provider *data_prd); 182 183 int submit_non_final_response(const std::string &status, int32_t stream_id); 184 185 int submit_push_promise(Stream *stream, const StringRef &push_path); 186 187 int submit_rst_stream(Stream *stream, uint32_t error_code); 188 189 void add_stream(int32_t stream_id, std::unique_ptr<Stream> stream); 190 void remove_stream(int32_t stream_id); 191 Stream *get_stream(int32_t stream_id); 192 int64_t session_id() const; 193 Sessions *get_sessions() const; 194 const Config *get_config() const; 195 void remove_settings_timer(); 196 void terminate_session(uint32_t error_code); 197 198 int fill_wb(); 199 200 int read_clear(); 201 int write_clear(); 202 int tls_handshake(); 203 int read_tls(); 204 int write_tls(); 205 206 struct ev_loop *get_loop() const; 207 208 using WriteBuf = Buffer<64_k>; 209 210 WriteBuf *get_wb(); 211 212 private: 213 ev_io wev_; 214 ev_io rev_; 215 ev_timer settings_timerev_; 216 std::map<int32_t, std::unique_ptr<Stream>> id2stream_; 217 WriteBuf wb_; 218 std::function<int(Http2Handler &)> read_, write_; 219 int64_t session_id_; 220 nghttp2_session *session_; 221 Sessions *sessions_; 222 SSL *ssl_; 223 const uint8_t *data_pending_; 224 size_t data_pendinglen_; 225 int fd_; 226 }; 227 228 struct StatusPage { 229 std::string status; 230 FileEntry file_ent; 231 }; 232 233 class HttpServer { 234 public: 235 HttpServer(const Config *config); 236 int listen(); 237 int run(); 238 const Config *get_config() const; 239 const StatusPage *get_status_page(int status) const; 240 241 private: 242 std::vector<StatusPage> status_pages_; 243 const Config *config_; 244 }; 245 246 ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, 247 uint8_t *buf, size_t length, uint32_t *data_flags, 248 nghttp2_data_source *source, void *user_data); 249 250 } // namespace nghttp2 251 252 #endif // HTTP_SERVER_H 253