• 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