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