1 /*
2  * ngtcp2
3  *
4  * Copyright (c) 2017 ngtcp2 contributors
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 H09CLIENT_H
26 #define H09CLIENT_H
27 
28 #ifdef HAVE_CONFIG_H
29 #  include <config.h>
30 #endif // HAVE_CONFIG_H
31 
32 #include <vector>
33 #include <deque>
34 #include <map>
35 #include <string_view>
36 #include <memory>
37 #include <set>
38 
39 #include <ngtcp2/ngtcp2.h>
40 #include <ngtcp2/ngtcp2_crypto.h>
41 
42 #include <nghttp3/nghttp3.h>
43 
44 #include <ev.h>
45 
46 #include "client_base.h"
47 #include "tls_client_context.h"
48 #include "tls_client_session.h"
49 #include "network.h"
50 #include "shared.h"
51 
52 using namespace ngtcp2;
53 
54 struct Stream {
55   Stream(const Request &req, int64_t stream_id);
56   ~Stream();
57 
58   int open_file(const std::string_view &path);
59 
60   Request req;
61   int64_t stream_id;
62   int fd;
63   std::string rawreqbuf;
64   nghttp3_buf reqbuf;
65 };
66 
67 struct StreamIDLess {
operatorStreamIDLess68   constexpr bool operator()(const Stream *lhs, const Stream *rhs) const {
69     return lhs->stream_id < rhs->stream_id;
70   }
71 };
72 
73 class Client;
74 
75 struct Endpoint {
76   Address addr;
77   ev_io rev;
78   Client *client;
79   int fd;
80 };
81 
82 class Client : public ClientBase {
83 public:
84   Client(struct ev_loop *loop);
85   ~Client();
86 
87   int init(int fd, const Address &local_addr, const Address &remote_addr,
88            const char *addr, const char *port, uint32_t version,
89            const TLSClientContext &tls_ctx);
90   void disconnect();
91 
92   void start_wev();
93 
94   int on_read(const Endpoint &ep);
95   int on_write();
96   int write_streams();
97   int feed_data(const Endpoint &ep, const sockaddr *sa, socklen_t salen,
98                 const ngtcp2_pkt_info *pi, uint8_t *data, size_t datalen);
99   int handle_expiry();
100   void schedule_retransmit();
101   int handshake_completed();
102   int handshake_confirmed();
103 
104   int send_packet(const Endpoint &ep, const ngtcp2_addr &remote_addr,
105                   unsigned int ecn, const uint8_t *data, size_t datalen);
106   int on_stream_close(int64_t stream_id, uint64_t app_error_code);
107   int on_extend_max_streams();
108   int handle_error();
109   int make_stream_early();
110   int change_local_addr();
111   void start_change_local_addr_timer();
112   int update_key(uint8_t *rx_secret, uint8_t *tx_secret,
113                  ngtcp2_crypto_aead_ctx *rx_aead_ctx, uint8_t *rx_iv,
114                  ngtcp2_crypto_aead_ctx *tx_aead_ctx, uint8_t *tx_iv,
115                  const uint8_t *current_rx_secret,
116                  const uint8_t *current_tx_secret, size_t secretlen);
117   int initiate_key_update();
118   void start_key_update_timer();
119   void start_delay_stream_timer();
120 
121   int select_preferred_address(Address &selected_addr,
122                                const ngtcp2_preferred_addr *paddr);
123 
124   std::optional<Endpoint *> endpoint_for(const Address &remote_addr);
125 
126   void set_remote_addr(const ngtcp2_addr &remote_addr);
127 
128   int submit_http_request(Stream *stream);
129   int recv_stream_data(uint32_t flags, int64_t stream_id, const uint8_t *data,
130                        size_t datalen);
131   int acked_stream_data_offset(int64_t stream_id, uint64_t offset,
132                                uint64_t datalen);
133   int extend_max_stream_data(int64_t stream_id, uint64_t max_data);
134 
135   void reset_idle_timer();
136 
137   void write_qlog(const void *data, size_t datalen);
138 
139   void idle_timeout();
140 
141 private:
142   std::vector<Endpoint> endpoints_;
143   Address remote_addr_;
144   ev_io wev_;
145   ev_timer timer_;
146   ev_timer rttimer_;
147   ev_timer change_local_addr_timer_;
148   ev_timer key_update_timer_;
149   ev_timer delay_stream_timer_;
150   ev_signal sigintev_;
151   struct ev_loop *loop_;
152   std::map<int64_t, std::unique_ptr<Stream>> streams_;
153   std::set<Stream *, StreamIDLess> sendq_;
154   // addr_ is the server host address.
155   const char *addr_;
156   // port_ is the server port.
157   const char *port_;
158   // nstreams_done_ is the number of streams opened.
159   size_t nstreams_done_;
160   // nstreams_closed_ is the number of streams get closed.
161   size_t nstreams_closed_;
162   // nkey_update_ is the number of key update occurred.
163   size_t nkey_update_;
164   uint32_t version_;
165   // early_data_ is true if client attempts to do 0RTT data transfer.
166   bool early_data_;
167   // should_exit_ is true if client should exit rather than waiting
168   // for timeout.
169   bool should_exit_;
170   // handshake_confirmed_ gets true after handshake has been
171   // confirmed.
172   bool handshake_confirmed_;
173 };
174 
175 #endif // CLIENT_H
176