12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2014 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#ifndef H2LOAD_H 262c593315Sopenharmony_ci#define H2LOAD_H 272c593315Sopenharmony_ci 282c593315Sopenharmony_ci#include "nghttp2_config.h" 292c593315Sopenharmony_ci 302c593315Sopenharmony_ci#include <sys/types.h> 312c593315Sopenharmony_ci#ifdef HAVE_SYS_SOCKET_H 322c593315Sopenharmony_ci# include <sys/socket.h> 332c593315Sopenharmony_ci#endif // HAVE_SYS_SOCKET_H 342c593315Sopenharmony_ci#ifdef HAVE_NETDB_H 352c593315Sopenharmony_ci# include <netdb.h> 362c593315Sopenharmony_ci#endif // HAVE_NETDB_H 372c593315Sopenharmony_ci#include <sys/un.h> 382c593315Sopenharmony_ci 392c593315Sopenharmony_ci#include <vector> 402c593315Sopenharmony_ci#include <string> 412c593315Sopenharmony_ci#include <unordered_map> 422c593315Sopenharmony_ci#include <memory> 432c593315Sopenharmony_ci#include <chrono> 442c593315Sopenharmony_ci#include <array> 452c593315Sopenharmony_ci 462c593315Sopenharmony_ci#include <nghttp2/nghttp2.h> 472c593315Sopenharmony_ci 482c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 492c593315Sopenharmony_ci# include <ngtcp2/ngtcp2.h> 502c593315Sopenharmony_ci# include <ngtcp2/ngtcp2_crypto.h> 512c593315Sopenharmony_ci#endif // ENABLE_HTTP3 522c593315Sopenharmony_ci 532c593315Sopenharmony_ci#include <ev.h> 542c593315Sopenharmony_ci 552c593315Sopenharmony_ci#include <openssl/ssl.h> 562c593315Sopenharmony_ci 572c593315Sopenharmony_ci#include "http2.h" 582c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 592c593315Sopenharmony_ci# include "quic.h" 602c593315Sopenharmony_ci#endif // ENABLE_HTTP3 612c593315Sopenharmony_ci#include "memchunk.h" 622c593315Sopenharmony_ci#include "template.h" 632c593315Sopenharmony_ci 642c593315Sopenharmony_ciusing namespace nghttp2; 652c593315Sopenharmony_ci 662c593315Sopenharmony_cinamespace h2load { 672c593315Sopenharmony_ci 682c593315Sopenharmony_ciconstexpr auto BACKOFF_WRITE_BUFFER_THRES = 16_k; 692c593315Sopenharmony_ci 702c593315Sopenharmony_ciclass Session; 712c593315Sopenharmony_cistruct Worker; 722c593315Sopenharmony_ci 732c593315Sopenharmony_cistruct Config { 742c593315Sopenharmony_ci std::vector<std::vector<nghttp2_nv>> nva; 752c593315Sopenharmony_ci std::vector<std::string> h1reqs; 762c593315Sopenharmony_ci std::vector<std::chrono::steady_clock::duration> timings; 772c593315Sopenharmony_ci nghttp2::Headers custom_headers; 782c593315Sopenharmony_ci std::string scheme; 792c593315Sopenharmony_ci std::string host; 802c593315Sopenharmony_ci std::string connect_to_host; 812c593315Sopenharmony_ci std::string ifile; 822c593315Sopenharmony_ci std::string ciphers; 832c593315Sopenharmony_ci std::string tls13_ciphers; 842c593315Sopenharmony_ci // supported groups (or curves). 852c593315Sopenharmony_ci std::string groups; 862c593315Sopenharmony_ci // length of upload data 872c593315Sopenharmony_ci int64_t data_length; 882c593315Sopenharmony_ci // memory mapped upload data 892c593315Sopenharmony_ci uint8_t *data; 902c593315Sopenharmony_ci addrinfo *addrs; 912c593315Sopenharmony_ci size_t nreqs; 922c593315Sopenharmony_ci size_t nclients; 932c593315Sopenharmony_ci size_t nthreads; 942c593315Sopenharmony_ci // The maximum number of concurrent streams per session. 952c593315Sopenharmony_ci ssize_t max_concurrent_streams; 962c593315Sopenharmony_ci size_t window_bits; 972c593315Sopenharmony_ci size_t connection_window_bits; 982c593315Sopenharmony_ci size_t max_frame_size; 992c593315Sopenharmony_ci // rate at which connections should be made 1002c593315Sopenharmony_ci size_t rate; 1012c593315Sopenharmony_ci ev_tstamp rate_period; 1022c593315Sopenharmony_ci // amount of time for main measurements in timing-based test 1032c593315Sopenharmony_ci ev_tstamp duration; 1042c593315Sopenharmony_ci // amount of time to wait before starting measurements in timing-based test 1052c593315Sopenharmony_ci ev_tstamp warm_up_time; 1062c593315Sopenharmony_ci // amount of time to wait for activity on a given connection 1072c593315Sopenharmony_ci ev_tstamp conn_active_timeout; 1082c593315Sopenharmony_ci // amount of time to wait after the last request is made on a connection 1092c593315Sopenharmony_ci ev_tstamp conn_inactivity_timeout; 1102c593315Sopenharmony_ci enum { PROTO_HTTP2, PROTO_HTTP1_1 } no_tls_proto; 1112c593315Sopenharmony_ci uint32_t header_table_size; 1122c593315Sopenharmony_ci uint32_t encoder_header_table_size; 1132c593315Sopenharmony_ci // file descriptor for upload data 1142c593315Sopenharmony_ci int data_fd; 1152c593315Sopenharmony_ci // file descriptor to write per-request stats to. 1162c593315Sopenharmony_ci int log_fd; 1172c593315Sopenharmony_ci // base file name of qlog output files 1182c593315Sopenharmony_ci std::string qlog_file_base; 1192c593315Sopenharmony_ci uint16_t port; 1202c593315Sopenharmony_ci uint16_t default_port; 1212c593315Sopenharmony_ci uint16_t connect_to_port; 1222c593315Sopenharmony_ci bool verbose; 1232c593315Sopenharmony_ci bool timing_script; 1242c593315Sopenharmony_ci std::string base_uri; 1252c593315Sopenharmony_ci // true if UNIX domain socket is used. In this case, base_uri is 1262c593315Sopenharmony_ci // not used in usual way. 1272c593315Sopenharmony_ci bool base_uri_unix; 1282c593315Sopenharmony_ci // used when UNIX domain socket is used (base_uri_unix is true). 1292c593315Sopenharmony_ci sockaddr_un unix_addr; 1302c593315Sopenharmony_ci // list of supported NPN/ALPN protocol strings in the order of 1312c593315Sopenharmony_ci // preference. 1322c593315Sopenharmony_ci std::vector<std::string> npn_list; 1332c593315Sopenharmony_ci // The number of request per second for each client. 1342c593315Sopenharmony_ci double rps; 1352c593315Sopenharmony_ci // Disables GSO for UDP connections. 1362c593315Sopenharmony_ci bool no_udp_gso; 1372c593315Sopenharmony_ci // The maximum UDP datagram payload size to send. 1382c593315Sopenharmony_ci size_t max_udp_payload_size; 1392c593315Sopenharmony_ci // Enable ktls. 1402c593315Sopenharmony_ci bool ktls; 1412c593315Sopenharmony_ci 1422c593315Sopenharmony_ci Config(); 1432c593315Sopenharmony_ci ~Config(); 1442c593315Sopenharmony_ci 1452c593315Sopenharmony_ci bool is_rate_mode() const; 1462c593315Sopenharmony_ci bool is_timing_based_mode() const; 1472c593315Sopenharmony_ci bool has_base_uri() const; 1482c593315Sopenharmony_ci bool rps_enabled() const; 1492c593315Sopenharmony_ci bool is_quic() const; 1502c593315Sopenharmony_ci}; 1512c593315Sopenharmony_ci 1522c593315Sopenharmony_cistruct RequestStat { 1532c593315Sopenharmony_ci // time point when request was sent 1542c593315Sopenharmony_ci std::chrono::steady_clock::time_point request_time; 1552c593315Sopenharmony_ci // same, but in wall clock reference frame 1562c593315Sopenharmony_ci std::chrono::system_clock::time_point request_wall_time; 1572c593315Sopenharmony_ci // time point when stream was closed 1582c593315Sopenharmony_ci std::chrono::steady_clock::time_point stream_close_time; 1592c593315Sopenharmony_ci // upload data length sent so far 1602c593315Sopenharmony_ci int64_t data_offset; 1612c593315Sopenharmony_ci // HTTP status code 1622c593315Sopenharmony_ci int status; 1632c593315Sopenharmony_ci // true if stream was successfully closed. This means stream was 1642c593315Sopenharmony_ci // not reset, but it does not mean HTTP level error (e.g., 404). 1652c593315Sopenharmony_ci bool completed; 1662c593315Sopenharmony_ci}; 1672c593315Sopenharmony_ci 1682c593315Sopenharmony_cistruct ClientStat { 1692c593315Sopenharmony_ci // time client started (i.e., first connect starts) 1702c593315Sopenharmony_ci std::chrono::steady_clock::time_point client_start_time; 1712c593315Sopenharmony_ci // time client end (i.e., client somehow processed all requests it 1722c593315Sopenharmony_ci // is responsible for, and disconnected) 1732c593315Sopenharmony_ci std::chrono::steady_clock::time_point client_end_time; 1742c593315Sopenharmony_ci // The number of requests completed successful, but not necessarily 1752c593315Sopenharmony_ci // means successful HTTP status code. 1762c593315Sopenharmony_ci size_t req_success; 1772c593315Sopenharmony_ci 1782c593315Sopenharmony_ci // The following 3 numbers are overwritten each time when connection 1792c593315Sopenharmony_ci // is made. 1802c593315Sopenharmony_ci 1812c593315Sopenharmony_ci // time connect starts 1822c593315Sopenharmony_ci std::chrono::steady_clock::time_point connect_start_time; 1832c593315Sopenharmony_ci // time to connect 1842c593315Sopenharmony_ci std::chrono::steady_clock::time_point connect_time; 1852c593315Sopenharmony_ci // time to first byte (TTFB) 1862c593315Sopenharmony_ci std::chrono::steady_clock::time_point ttfb; 1872c593315Sopenharmony_ci}; 1882c593315Sopenharmony_ci 1892c593315Sopenharmony_cistruct SDStat { 1902c593315Sopenharmony_ci // min, max, mean and sd (standard deviation) 1912c593315Sopenharmony_ci double min, max, mean, sd; 1922c593315Sopenharmony_ci // percentage of samples inside mean -/+ sd 1932c593315Sopenharmony_ci double within_sd; 1942c593315Sopenharmony_ci}; 1952c593315Sopenharmony_ci 1962c593315Sopenharmony_cistruct SDStats { 1972c593315Sopenharmony_ci // time for request 1982c593315Sopenharmony_ci SDStat request; 1992c593315Sopenharmony_ci // time for connect 2002c593315Sopenharmony_ci SDStat connect; 2012c593315Sopenharmony_ci // time to first byte (TTFB) 2022c593315Sopenharmony_ci SDStat ttfb; 2032c593315Sopenharmony_ci // request per second for each client 2042c593315Sopenharmony_ci SDStat rps; 2052c593315Sopenharmony_ci}; 2062c593315Sopenharmony_ci 2072c593315Sopenharmony_cistruct Stats { 2082c593315Sopenharmony_ci Stats(size_t req_todo, size_t nclients); 2092c593315Sopenharmony_ci // The total number of requests 2102c593315Sopenharmony_ci size_t req_todo; 2112c593315Sopenharmony_ci // The number of requests issued so far 2122c593315Sopenharmony_ci size_t req_started; 2132c593315Sopenharmony_ci // The number of requests finished 2142c593315Sopenharmony_ci size_t req_done; 2152c593315Sopenharmony_ci // The number of requests completed successful, but not necessarily 2162c593315Sopenharmony_ci // means successful HTTP status code. 2172c593315Sopenharmony_ci size_t req_success; 2182c593315Sopenharmony_ci // The number of requests marked as success. HTTP status code is 2192c593315Sopenharmony_ci // also considered as success. This is subset of req_done. 2202c593315Sopenharmony_ci size_t req_status_success; 2212c593315Sopenharmony_ci // The number of requests failed. This is subset of req_done. 2222c593315Sopenharmony_ci size_t req_failed; 2232c593315Sopenharmony_ci // The number of requests failed due to network errors. This is 2242c593315Sopenharmony_ci // subset of req_failed. 2252c593315Sopenharmony_ci size_t req_error; 2262c593315Sopenharmony_ci // The number of requests that failed due to timeout. 2272c593315Sopenharmony_ci size_t req_timedout; 2282c593315Sopenharmony_ci // The number of bytes received on the "wire". If SSL/TLS is used, 2292c593315Sopenharmony_ci // this is the number of decrypted bytes the application received. 2302c593315Sopenharmony_ci int64_t bytes_total; 2312c593315Sopenharmony_ci // The number of bytes received for header fields. This is 2322c593315Sopenharmony_ci // compressed version. 2332c593315Sopenharmony_ci int64_t bytes_head; 2342c593315Sopenharmony_ci // The number of bytes received for header fields after they are 2352c593315Sopenharmony_ci // decompressed. 2362c593315Sopenharmony_ci int64_t bytes_head_decomp; 2372c593315Sopenharmony_ci // The number of bytes received in DATA frame. 2382c593315Sopenharmony_ci int64_t bytes_body; 2392c593315Sopenharmony_ci // The number of each HTTP status category, status[i] is status code 2402c593315Sopenharmony_ci // in the range [i*100, (i+1)*100). 2412c593315Sopenharmony_ci std::array<size_t, 6> status; 2422c593315Sopenharmony_ci // The statistics per request 2432c593315Sopenharmony_ci std::vector<RequestStat> req_stats; 2442c593315Sopenharmony_ci // The statistics per client 2452c593315Sopenharmony_ci std::vector<ClientStat> client_stats; 2462c593315Sopenharmony_ci // The number of UDP datagrams received. 2472c593315Sopenharmony_ci size_t udp_dgram_recv; 2482c593315Sopenharmony_ci // The number of UDP datagrams sent. 2492c593315Sopenharmony_ci size_t udp_dgram_sent; 2502c593315Sopenharmony_ci}; 2512c593315Sopenharmony_ci 2522c593315Sopenharmony_cienum ClientState { CLIENT_IDLE, CLIENT_CONNECTED }; 2532c593315Sopenharmony_ci 2542c593315Sopenharmony_ci// This type tells whether the client is in warmup phase or not or is over 2552c593315Sopenharmony_cienum class Phase { 2562c593315Sopenharmony_ci INITIAL_IDLE, // Initial idle state before warm-up phase 2572c593315Sopenharmony_ci WARM_UP, // Warm up phase when no measurements are done 2582c593315Sopenharmony_ci MAIN_DURATION, // Main measurement phase; if timing-based 2592c593315Sopenharmony_ci // test is not run, this is the default phase 2602c593315Sopenharmony_ci DURATION_OVER // This phase occurs after the measurements are over 2612c593315Sopenharmony_ci}; 2622c593315Sopenharmony_ci 2632c593315Sopenharmony_cistruct Client; 2642c593315Sopenharmony_ci 2652c593315Sopenharmony_ci// We use reservoir sampling method 2662c593315Sopenharmony_cistruct Sampling { 2672c593315Sopenharmony_ci // maximum number of samples 2682c593315Sopenharmony_ci size_t max_samples; 2692c593315Sopenharmony_ci // number of samples seen, including discarded samples. 2702c593315Sopenharmony_ci size_t n; 2712c593315Sopenharmony_ci}; 2722c593315Sopenharmony_ci 2732c593315Sopenharmony_cistruct Worker { 2742c593315Sopenharmony_ci MemchunkPool mcpool; 2752c593315Sopenharmony_ci std::mt19937 randgen; 2762c593315Sopenharmony_ci Stats stats; 2772c593315Sopenharmony_ci Sampling request_times_smp; 2782c593315Sopenharmony_ci Sampling client_smp; 2792c593315Sopenharmony_ci struct ev_loop *loop; 2802c593315Sopenharmony_ci SSL_CTX *ssl_ctx; 2812c593315Sopenharmony_ci Config *config; 2822c593315Sopenharmony_ci size_t progress_interval; 2832c593315Sopenharmony_ci uint32_t id; 2842c593315Sopenharmony_ci bool tls_info_report_done; 2852c593315Sopenharmony_ci bool app_info_report_done; 2862c593315Sopenharmony_ci size_t nconns_made; 2872c593315Sopenharmony_ci // number of clients this worker handles 2882c593315Sopenharmony_ci size_t nclients; 2892c593315Sopenharmony_ci // number of requests each client issues 2902c593315Sopenharmony_ci size_t nreqs_per_client; 2912c593315Sopenharmony_ci // at most nreqs_rem clients get an extra request 2922c593315Sopenharmony_ci size_t nreqs_rem; 2932c593315Sopenharmony_ci size_t rate; 2942c593315Sopenharmony_ci // maximum number of samples in this worker thread 2952c593315Sopenharmony_ci size_t max_samples; 2962c593315Sopenharmony_ci ev_timer timeout_watcher; 2972c593315Sopenharmony_ci // The next client ID this worker assigns 2982c593315Sopenharmony_ci uint32_t next_client_id; 2992c593315Sopenharmony_ci // Keeps track of the current phase (for timing-based experiment) for the 3002c593315Sopenharmony_ci // worker 3012c593315Sopenharmony_ci Phase current_phase; 3022c593315Sopenharmony_ci // We need to keep track of the clients in order to stop them when needed 3032c593315Sopenharmony_ci std::vector<Client *> clients; 3042c593315Sopenharmony_ci // This is only active when there is not a bounded number of requests 3052c593315Sopenharmony_ci // specified 3062c593315Sopenharmony_ci ev_timer duration_watcher; 3072c593315Sopenharmony_ci ev_timer warmup_watcher; 3082c593315Sopenharmony_ci 3092c593315Sopenharmony_ci Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients, 3102c593315Sopenharmony_ci size_t rate, size_t max_samples, Config *config); 3112c593315Sopenharmony_ci ~Worker(); 3122c593315Sopenharmony_ci Worker(Worker &&o) = default; 3132c593315Sopenharmony_ci void run(); 3142c593315Sopenharmony_ci void sample_req_stat(RequestStat *req_stat); 3152c593315Sopenharmony_ci void sample_client_stat(ClientStat *cstat); 3162c593315Sopenharmony_ci void report_progress(); 3172c593315Sopenharmony_ci void report_rate_progress(); 3182c593315Sopenharmony_ci // This function calls the destructors of all the clients. 3192c593315Sopenharmony_ci void stop_all_clients(); 3202c593315Sopenharmony_ci // This function frees a client from the list of clients for this Worker. 3212c593315Sopenharmony_ci void free_client(Client *); 3222c593315Sopenharmony_ci}; 3232c593315Sopenharmony_ci 3242c593315Sopenharmony_cistruct Stream { 3252c593315Sopenharmony_ci RequestStat req_stat; 3262c593315Sopenharmony_ci int status_success; 3272c593315Sopenharmony_ci Stream(); 3282c593315Sopenharmony_ci}; 3292c593315Sopenharmony_ci 3302c593315Sopenharmony_cistruct Client { 3312c593315Sopenharmony_ci DefaultMemchunks wb; 3322c593315Sopenharmony_ci std::unordered_map<int32_t, Stream> streams; 3332c593315Sopenharmony_ci ClientStat cstat; 3342c593315Sopenharmony_ci std::unique_ptr<Session> session; 3352c593315Sopenharmony_ci ev_io wev; 3362c593315Sopenharmony_ci ev_io rev; 3372c593315Sopenharmony_ci std::function<int(Client &)> readfn, writefn; 3382c593315Sopenharmony_ci Worker *worker; 3392c593315Sopenharmony_ci SSL *ssl; 3402c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 3412c593315Sopenharmony_ci struct { 3422c593315Sopenharmony_ci ngtcp2_crypto_conn_ref conn_ref; 3432c593315Sopenharmony_ci ev_timer pkt_timer; 3442c593315Sopenharmony_ci ngtcp2_conn *conn; 3452c593315Sopenharmony_ci ngtcp2_ccerr last_error; 3462c593315Sopenharmony_ci bool close_requested; 3472c593315Sopenharmony_ci FILE *qlog_file; 3482c593315Sopenharmony_ci 3492c593315Sopenharmony_ci struct { 3502c593315Sopenharmony_ci bool send_blocked; 3512c593315Sopenharmony_ci size_t num_blocked; 3522c593315Sopenharmony_ci size_t num_blocked_sent; 3532c593315Sopenharmony_ci struct { 3542c593315Sopenharmony_ci Address remote_addr; 3552c593315Sopenharmony_ci const uint8_t *data; 3562c593315Sopenharmony_ci size_t datalen; 3572c593315Sopenharmony_ci size_t gso_size; 3582c593315Sopenharmony_ci } blocked[2]; 3592c593315Sopenharmony_ci std::unique_ptr<uint8_t[]> data; 3602c593315Sopenharmony_ci } tx; 3612c593315Sopenharmony_ci } quic; 3622c593315Sopenharmony_ci#endif // ENABLE_HTTP3 3632c593315Sopenharmony_ci ev_timer request_timeout_watcher; 3642c593315Sopenharmony_ci addrinfo *next_addr; 3652c593315Sopenharmony_ci // Address for the current address. When try_new_connection() is 3662c593315Sopenharmony_ci // used and current_addr is not nullptr, it is used instead of 3672c593315Sopenharmony_ci // trying next address though next_addr. To try new address, set 3682c593315Sopenharmony_ci // nullptr to current_addr before calling connect(). 3692c593315Sopenharmony_ci addrinfo *current_addr; 3702c593315Sopenharmony_ci size_t reqidx; 3712c593315Sopenharmony_ci ClientState state; 3722c593315Sopenharmony_ci // The number of requests this client has to issue. 3732c593315Sopenharmony_ci size_t req_todo; 3742c593315Sopenharmony_ci // The number of requests left to issue 3752c593315Sopenharmony_ci size_t req_left; 3762c593315Sopenharmony_ci // The number of requests currently have started, but not abandoned 3772c593315Sopenharmony_ci // or finished. 3782c593315Sopenharmony_ci size_t req_inflight; 3792c593315Sopenharmony_ci // The number of requests this client has issued so far. 3802c593315Sopenharmony_ci size_t req_started; 3812c593315Sopenharmony_ci // The number of requests this client has done so far. 3822c593315Sopenharmony_ci size_t req_done; 3832c593315Sopenharmony_ci // The client id per worker 3842c593315Sopenharmony_ci uint32_t id; 3852c593315Sopenharmony_ci int fd; 3862c593315Sopenharmony_ci Address local_addr; 3872c593315Sopenharmony_ci ev_timer conn_active_watcher; 3882c593315Sopenharmony_ci ev_timer conn_inactivity_watcher; 3892c593315Sopenharmony_ci std::string selected_proto; 3902c593315Sopenharmony_ci bool new_connection_requested; 3912c593315Sopenharmony_ci // true if the current connection will be closed, and no more new 3922c593315Sopenharmony_ci // request cannot be processed. 3932c593315Sopenharmony_ci bool final; 3942c593315Sopenharmony_ci // rps_watcher is a timer to invoke callback periodically to 3952c593315Sopenharmony_ci // generate a new request. 3962c593315Sopenharmony_ci ev_timer rps_watcher; 3972c593315Sopenharmony_ci // The timestamp that starts the period which contributes to the 3982c593315Sopenharmony_ci // next request generation. 3992c593315Sopenharmony_ci std::chrono::steady_clock::time_point rps_duration_started; 4002c593315Sopenharmony_ci // The number of requests allowed by rps, but limited by stream 4012c593315Sopenharmony_ci // concurrency. 4022c593315Sopenharmony_ci size_t rps_req_pending; 4032c593315Sopenharmony_ci // The number of in-flight streams. req_inflight has similar value 4042c593315Sopenharmony_ci // but it only measures requests made during Phase::MAIN_DURATION. 4052c593315Sopenharmony_ci // rps_req_inflight measures the number of requests in all phases, 4062c593315Sopenharmony_ci // and it is only used if --rps is given. 4072c593315Sopenharmony_ci size_t rps_req_inflight; 4082c593315Sopenharmony_ci 4092c593315Sopenharmony_ci enum { ERR_CONNECT_FAIL = -100 }; 4102c593315Sopenharmony_ci 4112c593315Sopenharmony_ci Client(uint32_t id, Worker *worker, size_t req_todo); 4122c593315Sopenharmony_ci ~Client(); 4132c593315Sopenharmony_ci int make_socket(addrinfo *addr); 4142c593315Sopenharmony_ci int connect(); 4152c593315Sopenharmony_ci void disconnect(); 4162c593315Sopenharmony_ci void fail(); 4172c593315Sopenharmony_ci // Call this function when do_read() returns -1. This function 4182c593315Sopenharmony_ci // tries to connect to the remote host again if it is requested. If 4192c593315Sopenharmony_ci // so, this function returns 0, and this object should be retained. 4202c593315Sopenharmony_ci // Otherwise, this function returns -1, and this object should be 4212c593315Sopenharmony_ci // deleted. 4222c593315Sopenharmony_ci int try_again_or_fail(); 4232c593315Sopenharmony_ci void timeout(); 4242c593315Sopenharmony_ci void restart_timeout(); 4252c593315Sopenharmony_ci int submit_request(); 4262c593315Sopenharmony_ci void process_request_failure(); 4272c593315Sopenharmony_ci void process_timedout_streams(); 4282c593315Sopenharmony_ci void process_abandoned_streams(); 4292c593315Sopenharmony_ci void report_tls_info(); 4302c593315Sopenharmony_ci void report_app_info(); 4312c593315Sopenharmony_ci void terminate_session(); 4322c593315Sopenharmony_ci // Asks client to create new connection, instead of just fail. 4332c593315Sopenharmony_ci void try_new_connection(); 4342c593315Sopenharmony_ci 4352c593315Sopenharmony_ci int do_read(); 4362c593315Sopenharmony_ci int do_write(); 4372c593315Sopenharmony_ci 4382c593315Sopenharmony_ci // low-level I/O callback functions called by do_read/do_write 4392c593315Sopenharmony_ci int connected(); 4402c593315Sopenharmony_ci int read_clear(); 4412c593315Sopenharmony_ci int write_clear(); 4422c593315Sopenharmony_ci int tls_handshake(); 4432c593315Sopenharmony_ci int read_tls(); 4442c593315Sopenharmony_ci int write_tls(); 4452c593315Sopenharmony_ci 4462c593315Sopenharmony_ci int on_read(const uint8_t *data, size_t len); 4472c593315Sopenharmony_ci int on_write(); 4482c593315Sopenharmony_ci 4492c593315Sopenharmony_ci int connection_made(); 4502c593315Sopenharmony_ci 4512c593315Sopenharmony_ci void on_request(int32_t stream_id); 4522c593315Sopenharmony_ci void on_header(int32_t stream_id, const uint8_t *name, size_t namelen, 4532c593315Sopenharmony_ci const uint8_t *value, size_t valuelen); 4542c593315Sopenharmony_ci void on_status_code(int32_t stream_id, uint16_t status); 4552c593315Sopenharmony_ci // |success| == true means that the request/response was exchanged 4562c593315Sopenharmony_ci // |successfully, but it does not mean response carried successful 4572c593315Sopenharmony_ci // |HTTP status code. 4582c593315Sopenharmony_ci void on_stream_close(int32_t stream_id, bool success, bool final = false); 4592c593315Sopenharmony_ci // Returns RequestStat for |stream_id|. This function must be 4602c593315Sopenharmony_ci // called after on_request(stream_id), and before 4612c593315Sopenharmony_ci // on_stream_close(stream_id, ...). Otherwise, this will return 4622c593315Sopenharmony_ci // nullptr. 4632c593315Sopenharmony_ci RequestStat *get_req_stat(int32_t stream_id); 4642c593315Sopenharmony_ci 4652c593315Sopenharmony_ci void record_request_time(RequestStat *req_stat); 4662c593315Sopenharmony_ci void record_connect_start_time(); 4672c593315Sopenharmony_ci void record_connect_time(); 4682c593315Sopenharmony_ci void record_ttfb(); 4692c593315Sopenharmony_ci void clear_connect_times(); 4702c593315Sopenharmony_ci void record_client_start_time(); 4712c593315Sopenharmony_ci void record_client_end_time(); 4722c593315Sopenharmony_ci 4732c593315Sopenharmony_ci void signal_write(); 4742c593315Sopenharmony_ci 4752c593315Sopenharmony_ci#ifdef ENABLE_HTTP3 4762c593315Sopenharmony_ci // QUIC 4772c593315Sopenharmony_ci int quic_init(const sockaddr *local_addr, socklen_t local_addrlen, 4782c593315Sopenharmony_ci const sockaddr *remote_addr, socklen_t remote_addrlen); 4792c593315Sopenharmony_ci void quic_free(); 4802c593315Sopenharmony_ci int read_quic(); 4812c593315Sopenharmony_ci int write_quic(); 4822c593315Sopenharmony_ci int write_udp(const sockaddr *addr, socklen_t addrlen, const uint8_t *data, 4832c593315Sopenharmony_ci size_t datalen, size_t gso_size); 4842c593315Sopenharmony_ci void on_send_blocked(const ngtcp2_addr &remote_addr, const uint8_t *data, 4852c593315Sopenharmony_ci size_t datalen, size_t gso_size); 4862c593315Sopenharmony_ci int send_blocked_packet(); 4872c593315Sopenharmony_ci void quic_close_connection(); 4882c593315Sopenharmony_ci 4892c593315Sopenharmony_ci int quic_handshake_completed(); 4902c593315Sopenharmony_ci int quic_recv_stream_data(uint32_t flags, int64_t stream_id, 4912c593315Sopenharmony_ci const uint8_t *data, size_t datalen); 4922c593315Sopenharmony_ci int quic_acked_stream_data_offset(int64_t stream_id, size_t datalen); 4932c593315Sopenharmony_ci int quic_stream_close(int64_t stream_id, uint64_t app_error_code); 4942c593315Sopenharmony_ci int quic_stream_reset(int64_t stream_id, uint64_t app_error_code); 4952c593315Sopenharmony_ci int quic_stream_stop_sending(int64_t stream_id, uint64_t app_error_code); 4962c593315Sopenharmony_ci int quic_extend_max_local_streams(); 4972c593315Sopenharmony_ci int quic_extend_max_stream_data(int64_t stream_id); 4982c593315Sopenharmony_ci 4992c593315Sopenharmony_ci int quic_write_client_handshake(ngtcp2_encryption_level level, 5002c593315Sopenharmony_ci const uint8_t *data, size_t datalen); 5012c593315Sopenharmony_ci int quic_pkt_timeout(); 5022c593315Sopenharmony_ci void quic_restart_pkt_timer(); 5032c593315Sopenharmony_ci void quic_write_qlog(const void *data, size_t datalen); 5042c593315Sopenharmony_ci int quic_make_http3_session(); 5052c593315Sopenharmony_ci#endif // ENABLE_HTTP3 5062c593315Sopenharmony_ci}; 5072c593315Sopenharmony_ci 5082c593315Sopenharmony_ci} // namespace h2load 5092c593315Sopenharmony_ci 5102c593315Sopenharmony_ci#endif // H2LOAD_H 511