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