Imported Upstream version 1.41.0
[platform/upstream/nghttp2.git] / src / h2load.h
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2014 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 H2LOAD_H
26 #define H2LOAD_H
27
28 #include "nghttp2_config.h"
29
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 #  include <sys/socket.h>
33 #endif // HAVE_SYS_SOCKET_H
34 #ifdef HAVE_NETDB_H
35 #  include <netdb.h>
36 #endif // HAVE_NETDB_H
37 #include <sys/un.h>
38
39 #include <vector>
40 #include <string>
41 #include <unordered_map>
42 #include <memory>
43 #include <chrono>
44 #include <array>
45
46 #include <nghttp2/nghttp2.h>
47
48 #include <ev.h>
49
50 #include <openssl/ssl.h>
51
52 #include "http2.h"
53 #include "memchunk.h"
54 #include "template.h"
55
56 using namespace nghttp2;
57
58 namespace h2load {
59
60 constexpr auto BACKOFF_WRITE_BUFFER_THRES = 16_k;
61
62 class Session;
63 struct Worker;
64
65 struct Config {
66   std::vector<std::vector<nghttp2_nv>> nva;
67   std::vector<std::string> h1reqs;
68   std::vector<ev_tstamp> timings;
69   nghttp2::Headers custom_headers;
70   std::string scheme;
71   std::string host;
72   std::string connect_to_host;
73   std::string ifile;
74   std::string ciphers;
75   // length of upload data
76   int64_t data_length;
77   addrinfo *addrs;
78   size_t nreqs;
79   size_t nclients;
80   size_t nthreads;
81   // The maximum number of concurrent streams per session.
82   ssize_t max_concurrent_streams;
83   size_t window_bits;
84   size_t connection_window_bits;
85   // rate at which connections should be made
86   size_t rate;
87   ev_tstamp rate_period;
88   // amount of time for main measurements in timing-based test
89   ev_tstamp duration;
90   // amount of time to wait before starting measurements in timing-based test
91   ev_tstamp warm_up_time;
92   // amount of time to wait for activity on a given connection
93   ev_tstamp conn_active_timeout;
94   // amount of time to wait after the last request is made on a connection
95   ev_tstamp conn_inactivity_timeout;
96   enum { PROTO_HTTP2, PROTO_HTTP1_1 } no_tls_proto;
97   uint32_t header_table_size;
98   uint32_t encoder_header_table_size;
99   // file descriptor for upload data
100   int data_fd;
101   // file descriptor to write per-request stats to.
102   int log_fd;
103   uint16_t port;
104   uint16_t default_port;
105   uint16_t connect_to_port;
106   bool verbose;
107   bool timing_script;
108   std::string base_uri;
109   // true if UNIX domain socket is used.  In this case, base_uri is
110   // not used in usual way.
111   bool base_uri_unix;
112   // used when UNIX domain socket is used (base_uri_unix is true).
113   sockaddr_un unix_addr;
114   // list of supported NPN/ALPN protocol strings in the order of
115   // preference.
116   std::vector<std::string> npn_list;
117
118   Config();
119   ~Config();
120
121   bool is_rate_mode() const;
122   bool is_timing_based_mode() const;
123   bool has_base_uri() const;
124 };
125
126 struct RequestStat {
127   // time point when request was sent
128   std::chrono::steady_clock::time_point request_time;
129   // same, but in wall clock reference frame
130   std::chrono::system_clock::time_point request_wall_time;
131   // time point when stream was closed
132   std::chrono::steady_clock::time_point stream_close_time;
133   // upload data length sent so far
134   int64_t data_offset;
135   // HTTP status code
136   int status;
137   // true if stream was successfully closed.  This means stream was
138   // not reset, but it does not mean HTTP level error (e.g., 404).
139   bool completed;
140 };
141
142 struct ClientStat {
143   // time client started (i.e., first connect starts)
144   std::chrono::steady_clock::time_point client_start_time;
145   // time client end (i.e., client somehow processed all requests it
146   // is responsible for, and disconnected)
147   std::chrono::steady_clock::time_point client_end_time;
148   // The number of requests completed successful, but not necessarily
149   // means successful HTTP status code.
150   size_t req_success;
151
152   // The following 3 numbers are overwritten each time when connection
153   // is made.
154
155   // time connect starts
156   std::chrono::steady_clock::time_point connect_start_time;
157   // time to connect
158   std::chrono::steady_clock::time_point connect_time;
159   // time to first byte (TTFB)
160   std::chrono::steady_clock::time_point ttfb;
161 };
162
163 struct SDStat {
164   // min, max, mean and sd (standard deviation)
165   double min, max, mean, sd;
166   // percentage of samples inside mean -/+ sd
167   double within_sd;
168 };
169
170 struct SDStats {
171   // time for request
172   SDStat request;
173   // time for connect
174   SDStat connect;
175   // time to first byte (TTFB)
176   SDStat ttfb;
177   // request per second for each client
178   SDStat rps;
179 };
180
181 struct Stats {
182   Stats(size_t req_todo, size_t nclients);
183   // The total number of requests
184   size_t req_todo;
185   // The number of requests issued so far
186   size_t req_started;
187   // The number of requests finished
188   size_t req_done;
189   // The number of requests completed successful, but not necessarily
190   // means successful HTTP status code.
191   size_t req_success;
192   // The number of requests marked as success.  HTTP status code is
193   // also considered as success. This is subset of req_done.
194   size_t req_status_success;
195   // The number of requests failed. This is subset of req_done.
196   size_t req_failed;
197   // The number of requests failed due to network errors. This is
198   // subset of req_failed.
199   size_t req_error;
200   // The number of requests that failed due to timeout.
201   size_t req_timedout;
202   // The number of bytes received on the "wire". If SSL/TLS is used,
203   // this is the number of decrypted bytes the application received.
204   int64_t bytes_total;
205   // The number of bytes received for header fields.  This is
206   // compressed version.
207   int64_t bytes_head;
208   // The number of bytes received for header fields after they are
209   // decompressed.
210   int64_t bytes_head_decomp;
211   // The number of bytes received in DATA frame.
212   int64_t bytes_body;
213   // The number of each HTTP status category, status[i] is status code
214   // in the range [i*100, (i+1)*100).
215   std::array<size_t, 6> status;
216   // The statistics per request
217   std::vector<RequestStat> req_stats;
218   // THe statistics per client
219   std::vector<ClientStat> client_stats;
220 };
221
222 enum ClientState { CLIENT_IDLE, CLIENT_CONNECTED };
223
224 // This type tells whether the client is in warmup phase or not or is over
225 enum class Phase {
226   INITIAL_IDLE,  // Initial idle state before warm-up phase
227   WARM_UP,       // Warm up phase when no measurements are done
228   MAIN_DURATION, // Main measurement phase; if timing-based
229                  // test is not run, this is the default phase
230   DURATION_OVER  // This phase occurs after the measurements are over
231 };
232
233 struct Client;
234
235 // We use reservoir sampling method
236 struct Sampling {
237   // maximum number of samples
238   size_t max_samples;
239   // number of samples seen, including discarded samples.
240   size_t n;
241 };
242
243 struct Worker {
244   MemchunkPool mcpool;
245   Stats stats;
246   Sampling request_times_smp;
247   Sampling client_smp;
248   struct ev_loop *loop;
249   SSL_CTX *ssl_ctx;
250   Config *config;
251   size_t progress_interval;
252   uint32_t id;
253   bool tls_info_report_done;
254   bool app_info_report_done;
255   size_t nconns_made;
256   // number of clients this worker handles
257   size_t nclients;
258   // number of requests each client issues
259   size_t nreqs_per_client;
260   // at most nreqs_rem clients get an extra request
261   size_t nreqs_rem;
262   size_t rate;
263   // maximum number of samples in this worker thread
264   size_t max_samples;
265   ev_timer timeout_watcher;
266   // The next client ID this worker assigns
267   uint32_t next_client_id;
268   // Keeps track of the current phase (for timing-based experiment) for the
269   // worker
270   Phase current_phase;
271   // We need to keep track of the clients in order to stop them when needed
272   std::vector<Client *> clients;
273   // This is only active when there is not a bounded number of requests
274   // specified
275   ev_timer duration_watcher;
276   ev_timer warmup_watcher;
277
278   Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients,
279          size_t rate, size_t max_samples, Config *config);
280   ~Worker();
281   Worker(Worker &&o) = default;
282   void run();
283   void sample_req_stat(RequestStat *req_stat);
284   void sample_client_stat(ClientStat *cstat);
285   void report_progress();
286   void report_rate_progress();
287   // This function calls the destructors of all the clients.
288   void stop_all_clients();
289   // This function frees a client from the list of clients for this Worker.
290   void free_client(Client *);
291 };
292
293 struct Stream {
294   RequestStat req_stat;
295   int status_success;
296   Stream();
297 };
298
299 struct Client {
300   DefaultMemchunks wb;
301   std::unordered_map<int32_t, Stream> streams;
302   ClientStat cstat;
303   std::unique_ptr<Session> session;
304   ev_io wev;
305   ev_io rev;
306   std::function<int(Client &)> readfn, writefn;
307   Worker *worker;
308   SSL *ssl;
309   ev_timer request_timeout_watcher;
310   addrinfo *next_addr;
311   // Address for the current address.  When try_new_connection() is
312   // used and current_addr is not nullptr, it is used instead of
313   // trying next address though next_addr.  To try new address, set
314   // nullptr to current_addr before calling connect().
315   addrinfo *current_addr;
316   size_t reqidx;
317   ClientState state;
318   // The number of requests this client has to issue.
319   size_t req_todo;
320   // The number of requests left to issue
321   size_t req_left;
322   // The number of requests currently have started, but not abandoned
323   // or finished.
324   size_t req_inflight;
325   // The number of requests this client has issued so far.
326   size_t req_started;
327   // The number of requests this client has done so far.
328   size_t req_done;
329   // The client id per worker
330   uint32_t id;
331   int fd;
332   ev_timer conn_active_watcher;
333   ev_timer conn_inactivity_watcher;
334   std::string selected_proto;
335   bool new_connection_requested;
336   // true if the current connection will be closed, and no more new
337   // request cannot be processed.
338   bool final;
339
340   enum { ERR_CONNECT_FAIL = -100 };
341
342   Client(uint32_t id, Worker *worker, size_t req_todo);
343   ~Client();
344   int make_socket(addrinfo *addr);
345   int connect();
346   void disconnect();
347   void fail();
348   // Call this function when do_read() returns -1.  This function
349   // tries to connect to the remote host again if it is requested.  If
350   // so, this function returns 0, and this object should be retained.
351   // Otherwise, this function returns -1, and this object should be
352   // deleted.
353   int try_again_or_fail();
354   void timeout();
355   void restart_timeout();
356   int submit_request();
357   void process_request_failure();
358   void process_timedout_streams();
359   void process_abandoned_streams();
360   void report_tls_info();
361   void report_app_info();
362   void terminate_session();
363   // Asks client to create new connection, instead of just fail.
364   void try_new_connection();
365
366   int do_read();
367   int do_write();
368
369   // low-level I/O callback functions called by do_read/do_write
370   int connected();
371   int read_clear();
372   int write_clear();
373   int tls_handshake();
374   int read_tls();
375   int write_tls();
376
377   int on_read(const uint8_t *data, size_t len);
378   int on_write();
379
380   int connection_made();
381
382   void on_request(int32_t stream_id);
383   void on_header(int32_t stream_id, const uint8_t *name, size_t namelen,
384                  const uint8_t *value, size_t valuelen);
385   void on_status_code(int32_t stream_id, uint16_t status);
386   // |success| == true means that the request/response was exchanged
387   // |successfully, but it does not mean response carried successful
388   // |HTTP status code.
389   void on_stream_close(int32_t stream_id, bool success, bool final = false);
390   // Returns RequestStat for |stream_id|.  This function must be
391   // called after on_request(stream_id), and before
392   // on_stream_close(stream_id, ...).  Otherwise, this will return
393   // nullptr.
394   RequestStat *get_req_stat(int32_t stream_id);
395
396   void record_request_time(RequestStat *req_stat);
397   void record_connect_start_time();
398   void record_connect_time();
399   void record_ttfb();
400   void clear_connect_times();
401   void record_client_start_time();
402   void record_client_end_time();
403
404   void signal_write();
405 };
406
407 } // namespace h2load
408
409 #endif // H2LOAD_H