• 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 #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