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