#include "shrpx_live_check.h"
#include "shrpx_connect_blocker.h"
#include "shrpx_dns_tracker.h"
+#ifdef ENABLE_HTTP3
+# include "shrpx_quic_connection_handler.h"
+# include "shrpx_quic.h"
+#endif // ENABLE_HTTP3
#include "allocator.h"
using namespace nghttp2;
class MemcachedDispatcher;
struct UpstreamAddr;
class ConnectionHandler;
+#ifdef ENABLE_HTTP3
+class QUICListener;
+#endif // ENABLE_HTTP3
#ifdef HAVE_MRUBY
namespace mruby {
if (d == 0) {
return rhs.seq < lhs.seq;
}
- return d <= MAX_DOWNSTREAM_ADDR_WEIGHT;
+ return d <= 2 * MAX_DOWNSTREAM_ADDR_WEIGHT - 1;
}
};
if (d == 0) {
return rhs.seq < lhs.seq;
}
- return d <= MAX_DOWNSTREAM_ADDR_WEIGHT;
+ return d <= 2 * MAX_DOWNSTREAM_ADDR_WEIGHT - 1;
}
};
: balloc(1024, 1024),
affinity{SessionAffinity::NONE},
redirect_if_not_tls{false},
+ dnf{false},
timeout{} {}
SharedDownstreamAddr(const SharedDownstreamAddr &) = delete;
// true if this group requires that client connection must be TLS,
// and the request must be redirected to https URI.
bool redirect_if_not_tls;
+ // true if a request should not be forwarded to a backend.
+ bool dnf;
// Timeouts for backend connection.
struct {
ev_tstamp read;
struct WorkerStat {
size_t num_connections;
+ size_t num_close_waits;
};
+#ifdef ENABLE_HTTP3
+struct QUICPacket {
+ QUICPacket(size_t upstream_addr_index, const Address &remote_addr,
+ const Address &local_addr, const uint8_t *data, size_t datalen)
+ : upstream_addr_index{upstream_addr_index},
+ remote_addr{remote_addr},
+ local_addr{local_addr},
+ data{data, data + datalen} {}
+ QUICPacket() {}
+ size_t upstream_addr_index;
+ Address remote_addr;
+ Address local_addr;
+ std::vector<uint8_t> data;
+};
+#endif // ENABLE_HTTP3
+
enum class WorkerEventType {
NEW_CONNECTION = 0x01,
REOPEN_LOG = 0x02,
GRACEFUL_SHUTDOWN = 0x03,
REPLACE_DOWNSTREAM = 0x04,
+#ifdef ENABLE_HTTP3
+ QUIC_PKT_FORWARD = 0x05,
+#endif // ENABLE_HTTP3
};
struct WorkerEvent {
};
std::shared_ptr<TicketKeys> ticket_keys;
std::shared_ptr<DownstreamConfig> downstreamconf;
+#ifdef ENABLE_HTTP3
+ std::unique_ptr<QUICPacket> quic_pkt;
+#endif // ENABLE_HTTP3
};
class Worker {
Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
SSL_CTX *tls_session_cache_memcached_ssl_ctx,
tls::CertLookupTree *cert_tree,
+#ifdef ENABLE_HTTP3
+ SSL_CTX *quic_sv_ssl_ctx, tls::CertLookupTree *quic_cert_tree,
+ const uint8_t *cid_prefix, size_t cid_prefixlen,
+# ifdef HAVE_LIBBPF
+ size_t index,
+# endif // HAVE_LIBBPF
+#endif // ENABLE_HTTP3
const std::shared_ptr<TicketKeys> &ticket_keys,
ConnectionHandler *conn_handler,
std::shared_ptr<DownstreamConfig> downstreamconf);
void run_async();
void wait();
void process_events();
- void send(const WorkerEvent &event);
+ void send(WorkerEvent event);
tls::CertLookupTree *get_cert_lookup_tree() const;
+#ifdef ENABLE_HTTP3
+ tls::CertLookupTree *get_quic_cert_lookup_tree() const;
+#endif // ENABLE_HTTP3
// These 2 functions make a lock m_ to get/set ticket keys
// atomically.
struct ev_loop *get_loop() const;
SSL_CTX *get_sv_ssl_ctx() const;
SSL_CTX *get_cl_ssl_ctx() const;
+#ifdef ENABLE_HTTP3
+ SSL_CTX *get_quic_sv_ssl_ctx() const;
+#endif // ENABLE_HTTP3
void set_graceful_shutdown(bool f);
bool get_graceful_shutdown() const;
ConnectionHandler *get_connection_handler() const;
+#ifdef ENABLE_HTTP3
+ QUICConnectionHandler *get_quic_connection_handler();
+
+ int setup_quic_server_socket();
+
+ const uint8_t *get_cid_prefix() const;
+
+# ifdef HAVE_LIBBPF
+ bool should_attach_bpf() const;
+
+ bool should_update_bpf_map() const;
+
+ uint32_t compute_sk_index() const;
+# endif // HAVE_LIBBPF
+
+ int create_quic_server_socket(UpstreamAddr &addr);
+
+ // Returns a pointer to UpstreamAddr which matches |local_addr|.
+ const UpstreamAddr *find_quic_upstream_addr(const Address &local_addr);
+#endif // ENABLE_HTTP3
+
DNSTracker *get_dns_tracker();
private:
#ifndef NOTHREADS
std::future<void> fut_;
#endif // NOTHREADS
+#if defined(ENABLE_HTTP3) && defined(HAVE_LIBBPF)
+ // Unique index of this worker.
+ size_t index_;
+#endif // ENABLE_HTTP3 && HAVE_LIBBPF
std::mutex m_;
std::deque<WorkerEvent> q_;
std::mt19937 randgen_;
WorkerStat worker_stat_;
DNSTracker dns_tracker_;
+#ifdef ENABLE_HTTP3
+ std::array<uint8_t, SHRPX_QUIC_CID_PREFIXLEN> cid_prefix_;
+ std::vector<UpstreamAddr> quic_upstream_addrs_;
+ std::vector<std::unique_ptr<QUICListener>> quic_listeners_;
+#endif // ENABLE_HTTP3
+
std::shared_ptr<DownstreamConfig> downstreamconf_;
std::unique_ptr<MemcachedDispatcher> session_cache_memcached_dispatcher_;
#ifdef HAVE_MRUBY
SSL_CTX *cl_ssl_ctx_;
tls::CertLookupTree *cert_tree_;
ConnectionHandler *conn_handler_;
+#ifdef ENABLE_HTTP3
+ SSL_CTX *quic_sv_ssl_ctx_;
+ tls::CertLookupTree *quic_cert_tree_;
+
+ QUICConnectionHandler quic_conn_handler_;
+#endif // ENABLE_HTTP3
#ifndef HAVE_ATOMIC_STD_SHARED_PTR
std::mutex ticket_keys_m_;
// nullptr. This function may schedule live check.
void downstream_failure(DownstreamAddr *addr, const Address *raddr);
+#ifdef ENABLE_HTTP3
+// Creates unpredictable SHRPX_QUIC_CID_PREFIXLEN bytes sequence which
+// is used as a prefix of QUIC Connection ID. This function returns
+// -1 on failure. |server_id| must be 2 bytes long.
+int create_cid_prefix(uint8_t *cid_prefix, const uint8_t *server_id);
+#endif // ENABLE_HTTP3
+
} // namespace shrpx
#endif // SHRPX_WORKER_H