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