• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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