changelog shortlog graph tags branches files raw help

Mercurial > demo / changeset: added quiche.h and some ui work

changeset 12: c520966de7fa
parent 11: d8f806f1d327
child 13: 1fedeaa5bfc5
author: ellis <ellis@rwest.io>
date: Mon, 15 May 2023 21:40:24 -0400
files: demo.asd ffi/quiche.h ui.lisp www/boot.html www/bootstrap.html www/css/w3.css www/favicon.ico www/robots.txt
description: added quiche.h and some ui work
     1.1--- a/demo.asd	Sun May 14 21:27:04 2023 -0400
     1.2+++ b/demo.asd	Mon May 15 21:40:24 2023 -0400
     1.3@@ -10,8 +10,8 @@
     1.4   :depends-on (:bordeaux-threads
     1.5 	       #+(or ccl sbcl)
     1.6 	       :clack
     1.7-	       :caveman2
     1.8 	       :clog
     1.9+	       :clog-web
    1.10 	       :cl-rocksdb
    1.11 	       :verbose
    1.12 	       :alexandria
     2.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2+++ b/ffi/quiche.h	Mon May 15 21:40:24 2023 -0400
     2.3@@ -0,0 +1,973 @@
     2.4+// Copyright (C) 2018-2019, Cloudflare, Inc.
     2.5+// All rights reserved.
     2.6+//
     2.7+// Redistribution and use in source and binary forms, with or without
     2.8+// modification, are permitted provided that the following conditions are
     2.9+// met:
    2.10+//
    2.11+//     * Redistributions of source code must retain the above copyright
    2.12+//       notice, this list of conditions and the following disclaimer.
    2.13+//
    2.14+//     * Redistributions in binary form must reproduce the above copyright
    2.15+//       notice, this list of conditions and the following disclaimer in the
    2.16+//       documentation and/or other materials provided with the distribution.
    2.17+//
    2.18+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    2.19+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    2.20+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    2.21+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
    2.22+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    2.23+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    2.24+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    2.25+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    2.26+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    2.27+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    2.28+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2.29+
    2.30+#ifndef QUICHE_H
    2.31+#define QUICHE_H
    2.32+
    2.33+#if defined(__cplusplus)
    2.34+extern "C" {
    2.35+#endif
    2.36+
    2.37+#include <stdint.h>
    2.38+#include <stdbool.h>
    2.39+#include <stddef.h>
    2.40+
    2.41+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
    2.42+#include <winsock2.h>
    2.43+#include <ws2tcpip.h>
    2.44+#include <time.h>
    2.45+#else
    2.46+#include <sys/socket.h>
    2.47+#include <sys/time.h>
    2.48+#endif
    2.49+
    2.50+#ifdef __unix__
    2.51+#include <sys/types.h>
    2.52+#endif
    2.53+#ifdef _MSC_VER
    2.54+#include <BaseTsd.h>
    2.55+#define ssize_t SSIZE_T
    2.56+#endif
    2.57+
    2.58+// QUIC transport API.
    2.59+//
    2.60+
    2.61+// The current QUIC wire version.
    2.62+#define QUICHE_PROTOCOL_VERSION 0x00000001
    2.63+
    2.64+// The maximum length of a connection ID.
    2.65+#define QUICHE_MAX_CONN_ID_LEN 20
    2.66+
    2.67+// The minimum length of Initial packets sent by a client.
    2.68+#define QUICHE_MIN_CLIENT_INITIAL_LEN 1200
    2.69+
    2.70+enum quiche_error {
    2.71+    // There is no more work to do.
    2.72+    QUICHE_ERR_DONE = -1,
    2.73+
    2.74+    // The provided buffer is too short.
    2.75+    QUICHE_ERR_BUFFER_TOO_SHORT = -2,
    2.76+
    2.77+    // The provided packet cannot be parsed because its version is unknown.
    2.78+    QUICHE_ERR_UNKNOWN_VERSION = -3,
    2.79+
    2.80+    // The provided packet cannot be parsed because it contains an invalid
    2.81+    // frame.
    2.82+    QUICHE_ERR_INVALID_FRAME = -4,
    2.83+
    2.84+    // The provided packet cannot be parsed.
    2.85+    QUICHE_ERR_INVALID_PACKET = -5,
    2.86+
    2.87+    // The operation cannot be completed because the connection is in an
    2.88+    // invalid state.
    2.89+    QUICHE_ERR_INVALID_STATE = -6,
    2.90+
    2.91+    // The operation cannot be completed because the stream is in an
    2.92+    // invalid state.
    2.93+    QUICHE_ERR_INVALID_STREAM_STATE = -7,
    2.94+
    2.95+    // The peer's transport params cannot be parsed.
    2.96+    QUICHE_ERR_INVALID_TRANSPORT_PARAM = -8,
    2.97+
    2.98+    // A cryptographic operation failed.
    2.99+    QUICHE_ERR_CRYPTO_FAIL = -9,
   2.100+
   2.101+    // The TLS handshake failed.
   2.102+    QUICHE_ERR_TLS_FAIL = -10,
   2.103+
   2.104+    // The peer violated the local flow control limits.
   2.105+    QUICHE_ERR_FLOW_CONTROL = -11,
   2.106+
   2.107+    // The peer violated the local stream limits.
   2.108+    QUICHE_ERR_STREAM_LIMIT = -12,
   2.109+
   2.110+    // The specified stream was stopped by the peer.
   2.111+    QUICHE_ERR_STREAM_STOPPED = -15,
   2.112+
   2.113+    // The specified stream was reset by the peer.
   2.114+    QUICHE_ERR_STREAM_RESET = -16,
   2.115+
   2.116+    // The received data exceeds the stream's final size.
   2.117+    QUICHE_ERR_FINAL_SIZE = -13,
   2.118+
   2.119+    // Error in congestion control.
   2.120+    QUICHE_ERR_CONGESTION_CONTROL = -14,
   2.121+
   2.122+    // Too many identifiers were provided.
   2.123+    QUICHE_ERR_ID_LIMIT = -17,
   2.124+
   2.125+    // Not enough available identifiers.
   2.126+    QUICHE_ERR_OUT_OF_IDENTIFIERS = -18,
   2.127+
   2.128+    // Error in key update.
   2.129+    QUICHE_ERR_KEY_UPDATE = -19,
   2.130+};
   2.131+
   2.132+// Returns a human readable string with the quiche version number.
   2.133+const char *quiche_version(void);
   2.134+
   2.135+// Enables logging. |cb| will be called with log messages
   2.136+int quiche_enable_debug_logging(void (*cb)(const char *line, void *argp),
   2.137+                                void *argp);
   2.138+
   2.139+// Stores configuration shared between multiple connections.
   2.140+typedef struct quiche_config quiche_config;
   2.141+
   2.142+// Creates a config object with the given version.
   2.143+quiche_config *quiche_config_new(uint32_t version);
   2.144+
   2.145+// Configures the given certificate chain.
   2.146+int quiche_config_load_cert_chain_from_pem_file(quiche_config *config,
   2.147+                                                const char *path);
   2.148+
   2.149+// Configures the given private key.
   2.150+int quiche_config_load_priv_key_from_pem_file(quiche_config *config,
   2.151+                                              const char *path);
   2.152+
   2.153+// Specifies a file where trusted CA certificates are stored for the purposes of certificate verification.
   2.154+int quiche_config_load_verify_locations_from_file(quiche_config *config,
   2.155+                                                  const char *path);
   2.156+
   2.157+// Specifies a directory where trusted CA certificates are stored for the purposes of certificate verification.
   2.158+int quiche_config_load_verify_locations_from_directory(quiche_config *config,
   2.159+                                                       const char *path);
   2.160+
   2.161+// Configures whether to verify the peer's certificate.
   2.162+void quiche_config_verify_peer(quiche_config *config, bool v);
   2.163+
   2.164+// Configures whether to send GREASE.
   2.165+void quiche_config_grease(quiche_config *config, bool v);
   2.166+
   2.167+// Enables logging of secrets.
   2.168+void quiche_config_log_keys(quiche_config *config);
   2.169+
   2.170+// Enables sending or receiving early data.
   2.171+void quiche_config_enable_early_data(quiche_config *config);
   2.172+
   2.173+// Configures the list of supported application protocols.
   2.174+int quiche_config_set_application_protos(quiche_config *config,
   2.175+                                         const uint8_t *protos,
   2.176+                                         size_t protos_len);
   2.177+
   2.178+// Sets the `max_idle_timeout` transport parameter, in milliseconds, default is
   2.179+// no timeout.
   2.180+void quiche_config_set_max_idle_timeout(quiche_config *config, uint64_t v);
   2.181+
   2.182+// Sets the `max_udp_payload_size transport` parameter.
   2.183+void quiche_config_set_max_recv_udp_payload_size(quiche_config *config, size_t v);
   2.184+
   2.185+// Sets the maximum outgoing UDP payload size.
   2.186+void quiche_config_set_max_send_udp_payload_size(quiche_config *config, size_t v);
   2.187+
   2.188+// Sets the `initial_max_data` transport parameter.
   2.189+void quiche_config_set_initial_max_data(quiche_config *config, uint64_t v);
   2.190+
   2.191+// Sets the `initial_max_stream_data_bidi_local` transport parameter.
   2.192+void quiche_config_set_initial_max_stream_data_bidi_local(quiche_config *config, uint64_t v);
   2.193+
   2.194+// Sets the `initial_max_stream_data_bidi_remote` transport parameter.
   2.195+void quiche_config_set_initial_max_stream_data_bidi_remote(quiche_config *config, uint64_t v);
   2.196+
   2.197+// Sets the `initial_max_stream_data_uni` transport parameter.
   2.198+void quiche_config_set_initial_max_stream_data_uni(quiche_config *config, uint64_t v);
   2.199+
   2.200+// Sets the `initial_max_streams_bidi` transport parameter.
   2.201+void quiche_config_set_initial_max_streams_bidi(quiche_config *config, uint64_t v);
   2.202+
   2.203+// Sets the `initial_max_streams_uni` transport parameter.
   2.204+void quiche_config_set_initial_max_streams_uni(quiche_config *config, uint64_t v);
   2.205+
   2.206+// Sets the `ack_delay_exponent` transport parameter.
   2.207+void quiche_config_set_ack_delay_exponent(quiche_config *config, uint64_t v);
   2.208+
   2.209+// Sets the `max_ack_delay` transport parameter.
   2.210+void quiche_config_set_max_ack_delay(quiche_config *config, uint64_t v);
   2.211+
   2.212+// Sets the `disable_active_migration` transport parameter.
   2.213+void quiche_config_set_disable_active_migration(quiche_config *config, bool v);
   2.214+
   2.215+enum quiche_cc_algorithm {
   2.216+    QUICHE_CC_RENO = 0,
   2.217+    QUICHE_CC_CUBIC = 1,
   2.218+    QUICHE_CC_BBR = 2,
   2.219+};
   2.220+
   2.221+// Sets the congestion control algorithm used.
   2.222+void quiche_config_set_cc_algorithm(quiche_config *config, enum quiche_cc_algorithm algo);
   2.223+
   2.224+// Configures whether to use HyStart++.
   2.225+void quiche_config_enable_hystart(quiche_config *config, bool v);
   2.226+
   2.227+// Configures whether to enable pacing (enabled by default).
   2.228+void quiche_config_enable_pacing(quiche_config *config, bool v);
   2.229+
   2.230+// Configures max pacing rate to be used.
   2.231+void quiche_config_set_max_pacing_rate(quiche_config *config, uint64_t v);
   2.232+
   2.233+// Configures whether to enable receiving DATAGRAM frames.
   2.234+void quiche_config_enable_dgram(quiche_config *config, bool enabled,
   2.235+                                size_t recv_queue_len,
   2.236+                                size_t send_queue_len);
   2.237+
   2.238+// Sets the maximum connection window.
   2.239+void quiche_config_set_max_connection_window(quiche_config *config, uint64_t v);
   2.240+
   2.241+// Sets the maximum stream window.
   2.242+void quiche_config_set_max_stream_window(quiche_config *config, uint64_t v);
   2.243+
   2.244+// Sets the limit of active connection IDs.
   2.245+void quiche_config_set_active_connection_id_limit(quiche_config *config, uint64_t v);
   2.246+
   2.247+// Sets the initial stateless reset token. |v| must contain 16 bytes, otherwise the behaviour is undefined.
   2.248+void quiche_config_set_stateless_reset_token(quiche_config *config, const uint8_t *v);
   2.249+
   2.250+// Frees the config object.
   2.251+void quiche_config_free(quiche_config *config);
   2.252+
   2.253+// Extracts version, type, source / destination connection ID and address
   2.254+// verification token from the packet in |buf|.
   2.255+int quiche_header_info(const uint8_t *buf, size_t buf_len, size_t dcil,
   2.256+                       uint32_t *version, uint8_t *type,
   2.257+                       uint8_t *scid, size_t *scid_len,
   2.258+                       uint8_t *dcid, size_t *dcid_len,
   2.259+                       uint8_t *token, size_t *token_len);
   2.260+
   2.261+// A QUIC connection.
   2.262+typedef struct quiche_conn quiche_conn;
   2.263+
   2.264+// Creates a new server-side connection.
   2.265+quiche_conn *quiche_accept(const uint8_t *scid, size_t scid_len,
   2.266+                           const uint8_t *odcid, size_t odcid_len,
   2.267+                           const struct sockaddr *local, size_t local_len,
   2.268+                           const struct sockaddr *peer, size_t peer_len,
   2.269+                           quiche_config *config);
   2.270+
   2.271+// Creates a new client-side connection.
   2.272+quiche_conn *quiche_connect(const char *server_name,
   2.273+                            const uint8_t *scid, size_t scid_len,
   2.274+                            const struct sockaddr *local, size_t local_len,
   2.275+                            const struct sockaddr *peer, size_t peer_len,
   2.276+                            quiche_config *config);
   2.277+
   2.278+// Writes a version negotiation packet.
   2.279+ssize_t quiche_negotiate_version(const uint8_t *scid, size_t scid_len,
   2.280+                                 const uint8_t *dcid, size_t dcid_len,
   2.281+                                 uint8_t *out, size_t out_len);
   2.282+
   2.283+// Writes a retry packet.
   2.284+ssize_t quiche_retry(const uint8_t *scid, size_t scid_len,
   2.285+                     const uint8_t *dcid, size_t dcid_len,
   2.286+                     const uint8_t *new_scid, size_t new_scid_len,
   2.287+                     const uint8_t *token, size_t token_len,
   2.288+                     uint32_t version, uint8_t *out, size_t out_len);
   2.289+
   2.290+// Returns true if the given protocol version is supported.
   2.291+bool quiche_version_is_supported(uint32_t version);
   2.292+
   2.293+quiche_conn *quiche_conn_new_with_tls(const uint8_t *scid, size_t scid_len,
   2.294+                                      const uint8_t *odcid, size_t odcid_len,
   2.295+                                      const struct sockaddr *local, size_t local_len,
   2.296+                                      const struct sockaddr *peer, size_t peer_len,
   2.297+                                      quiche_config *config, void *ssl,
   2.298+                                      bool is_server);
   2.299+
   2.300+// Enables keylog to the specified file path. Returns true on success.
   2.301+bool quiche_conn_set_keylog_path(quiche_conn *conn, const char *path);
   2.302+
   2.303+// Enables keylog to the specified file descriptor. Unix only.
   2.304+void quiche_conn_set_keylog_fd(quiche_conn *conn, int fd);
   2.305+
   2.306+// Enables qlog to the specified file path. Returns true on success.
   2.307+bool quiche_conn_set_qlog_path(quiche_conn *conn, const char *path,
   2.308+                          const char *log_title, const char *log_desc);
   2.309+
   2.310+// Enables qlog to the specified file descriptor. Unix only.
   2.311+void quiche_conn_set_qlog_fd(quiche_conn *conn, int fd, const char *log_title,
   2.312+                             const char *log_desc);
   2.313+
   2.314+// Configures the given session for resumption.
   2.315+int quiche_conn_set_session(quiche_conn *conn, const uint8_t *buf, size_t buf_len);
   2.316+
   2.317+typedef struct {
   2.318+    // The remote address the packet was received from.
   2.319+    struct sockaddr *from;
   2.320+    socklen_t from_len;
   2.321+
   2.322+    // The local address the packet was received on.
   2.323+    struct sockaddr *to;
   2.324+    socklen_t to_len;
   2.325+} quiche_recv_info;
   2.326+
   2.327+// Processes QUIC packets received from the peer.
   2.328+ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len,
   2.329+                         const quiche_recv_info *info);
   2.330+
   2.331+typedef struct {
   2.332+    // The local address the packet should be sent from.
   2.333+    struct sockaddr_storage from;
   2.334+    socklen_t from_len;
   2.335+
   2.336+    // The remote address the packet should be sent to.
   2.337+    struct sockaddr_storage to;
   2.338+    socklen_t to_len;
   2.339+
   2.340+    // The time to send the packet out.
   2.341+    struct timespec at;
   2.342+} quiche_send_info;
   2.343+
   2.344+// Writes a single QUIC packet to be sent to the peer.
   2.345+ssize_t quiche_conn_send(quiche_conn *conn, uint8_t *out, size_t out_len,
   2.346+                         quiche_send_info *out_info);
   2.347+
   2.348+// Returns the size of the send quantum, in bytes.
   2.349+size_t quiche_conn_send_quantum(const quiche_conn *conn);
   2.350+
   2.351+// Reads contiguous data from a stream.
   2.352+ssize_t quiche_conn_stream_recv(quiche_conn *conn, uint64_t stream_id,
   2.353+                                uint8_t *out, size_t buf_len, bool *fin);
   2.354+
   2.355+// Writes data to a stream.
   2.356+ssize_t quiche_conn_stream_send(quiche_conn *conn, uint64_t stream_id,
   2.357+                                const uint8_t *buf, size_t buf_len, bool fin);
   2.358+
   2.359+// The side of the stream to be shut down.
   2.360+enum quiche_shutdown {
   2.361+    QUICHE_SHUTDOWN_READ = 0,
   2.362+    QUICHE_SHUTDOWN_WRITE = 1,
   2.363+};
   2.364+
   2.365+// Sets the priority for a stream.
   2.366+int quiche_conn_stream_priority(quiche_conn *conn, uint64_t stream_id,
   2.367+                                uint8_t urgency, bool incremental);
   2.368+
   2.369+// Shuts down reading or writing from/to the specified stream.
   2.370+int quiche_conn_stream_shutdown(quiche_conn *conn, uint64_t stream_id,
   2.371+                                enum quiche_shutdown direction, uint64_t err);
   2.372+
   2.373+// Returns the stream's send capacity in bytes.
   2.374+ssize_t quiche_conn_stream_capacity(const quiche_conn *conn, uint64_t stream_id);
   2.375+
   2.376+// Returns true if the stream has data that can be read.
   2.377+bool quiche_conn_stream_readable(const quiche_conn *conn, uint64_t stream_id);
   2.378+
   2.379+// Returns the next stream that has data to read, or -1 if no such stream is
   2.380+// available.
   2.381+int64_t quiche_conn_stream_readable_next(quiche_conn *conn);
   2.382+
   2.383+// Returns true if the stream has enough send capacity.
   2.384+//
   2.385+// On error a value lower than 0 is returned.
   2.386+int quiche_conn_stream_writable(quiche_conn *conn, uint64_t stream_id, size_t len);
   2.387+
   2.388+// Returns the next stream that can be written to, or -1 if no such stream is
   2.389+// available.
   2.390+int64_t quiche_conn_stream_writable_next(quiche_conn *conn);
   2.391+
   2.392+// Returns true if all the data has been read from the specified stream.
   2.393+bool quiche_conn_stream_finished(const quiche_conn *conn, uint64_t stream_id);
   2.394+
   2.395+typedef struct quiche_stream_iter quiche_stream_iter;
   2.396+
   2.397+// Returns an iterator over streams that have outstanding data to read.
   2.398+quiche_stream_iter *quiche_conn_readable(const quiche_conn *conn);
   2.399+
   2.400+// Returns an iterator over streams that can be written to.
   2.401+quiche_stream_iter *quiche_conn_writable(const quiche_conn *conn);
   2.402+
   2.403+// Returns the maximum possible size of egress UDP payloads.
   2.404+size_t quiche_conn_max_send_udp_payload_size(const quiche_conn *conn);
   2.405+
   2.406+// Returns the amount of time until the next timeout event, in nanoseconds.
   2.407+uint64_t quiche_conn_timeout_as_nanos(const quiche_conn *conn);
   2.408+
   2.409+// Returns the amount of time until the next timeout event, in milliseconds.
   2.410+uint64_t quiche_conn_timeout_as_millis(const quiche_conn *conn);
   2.411+
   2.412+// Processes a timeout event.
   2.413+void quiche_conn_on_timeout(quiche_conn *conn);
   2.414+
   2.415+// Closes the connection with the given error and reason.
   2.416+int quiche_conn_close(quiche_conn *conn, bool app, uint64_t err,
   2.417+                      const uint8_t *reason, size_t reason_len);
   2.418+
   2.419+// Returns a string uniquely representing the connection.
   2.420+void quiche_conn_trace_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
   2.421+
   2.422+// Returns the source connection ID.
   2.423+void quiche_conn_source_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
   2.424+
   2.425+// Returns the destination connection ID.
   2.426+void quiche_conn_destination_id(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
   2.427+
   2.428+// Returns the negotiated ALPN protocol.
   2.429+void quiche_conn_application_proto(const quiche_conn *conn, const uint8_t **out,
   2.430+                                   size_t *out_len);
   2.431+
   2.432+// Returns the peer's leaf certificate (if any) as a DER-encoded buffer.
   2.433+void quiche_conn_peer_cert(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
   2.434+
   2.435+// Returns the serialized cryptographic session for the connection.
   2.436+void quiche_conn_session(const quiche_conn *conn, const uint8_t **out, size_t *out_len);
   2.437+
   2.438+// Returns true if the connection handshake is complete.
   2.439+bool quiche_conn_is_established(const quiche_conn *conn);
   2.440+
   2.441+// Returns true if the connection has a pending handshake that has progressed
   2.442+// enough to send or receive early data.
   2.443+bool quiche_conn_is_in_early_data(const quiche_conn *conn);
   2.444+
   2.445+// Returns whether there is stream or DATAGRAM data available to read.
   2.446+bool quiche_conn_is_readable(const quiche_conn *conn);
   2.447+
   2.448+// Returns true if the connection is draining.
   2.449+bool quiche_conn_is_draining(const quiche_conn *conn);
   2.450+
   2.451+// Returns the number of bidirectional streams that can be created
   2.452+// before the peer's stream count limit is reached.
   2.453+uint64_t quiche_conn_peer_streams_left_bidi(const quiche_conn *conn);
   2.454+
   2.455+// Returns the number of unidirectional streams that can be created
   2.456+// before the peer's stream count limit is reached.
   2.457+uint64_t quiche_conn_peer_streams_left_uni(const quiche_conn *conn);
   2.458+
   2.459+// Returns true if the connection is closed.
   2.460+bool quiche_conn_is_closed(const quiche_conn *conn);
   2.461+
   2.462+// Returns true if the connection was closed due to the idle timeout.
   2.463+bool quiche_conn_is_timed_out(const quiche_conn *conn);
   2.464+
   2.465+// Returns true if a connection error was received, and updates the provided
   2.466+// parameters accordingly.
   2.467+bool quiche_conn_peer_error(const quiche_conn *conn,
   2.468+                            bool *is_app,
   2.469+                            uint64_t *error_code,
   2.470+                            const uint8_t **reason,
   2.471+                            size_t *reason_len);
   2.472+
   2.473+// Returns true if a connection error was queued or sent, and updates the provided
   2.474+// parameters accordingly.
   2.475+bool quiche_conn_local_error(const quiche_conn *conn,
   2.476+                             bool *is_app,
   2.477+                             uint64_t *error_code,
   2.478+                             const uint8_t **reason,
   2.479+                             size_t *reason_len);
   2.480+
   2.481+// Initializes the stream's application data.
   2.482+//
   2.483+// Stream data can only be initialized once. Additional calls to this method
   2.484+// will fail.
   2.485+//
   2.486+// Note that the application is responsible for freeing the data.
   2.487+int quiche_conn_stream_init_application_data(quiche_conn *conn,
   2.488+                                             uint64_t stream_id,
   2.489+                                             void *data);
   2.490+
   2.491+// Returns the stream's application data, if any was initialized.
   2.492+void *quiche_conn_stream_application_data(quiche_conn *conn, uint64_t stream_id);
   2.493+
   2.494+// Fetches the next stream from the given iterator. Returns false if there are
   2.495+// no more elements in the iterator.
   2.496+bool quiche_stream_iter_next(quiche_stream_iter *iter, uint64_t *stream_id);
   2.497+
   2.498+// Frees the given stream iterator object.
   2.499+void quiche_stream_iter_free(quiche_stream_iter *iter);
   2.500+
   2.501+typedef struct {
   2.502+    // The number of QUIC packets received on this connection.
   2.503+    size_t recv;
   2.504+
   2.505+    // The number of QUIC packets sent on this connection.
   2.506+    size_t sent;
   2.507+
   2.508+    // The number of QUIC packets that were lost.
   2.509+    size_t lost;
   2.510+
   2.511+    // The number of sent QUIC packets with retransmitted data.
   2.512+    size_t retrans;
   2.513+
   2.514+    // The number of sent bytes.
   2.515+    uint64_t sent_bytes;
   2.516+
   2.517+    // The number of received bytes.
   2.518+    uint64_t recv_bytes;
   2.519+
   2.520+    // The number of bytes lost.
   2.521+    uint64_t lost_bytes;
   2.522+
   2.523+    // The number of stream bytes retransmitted.
   2.524+    uint64_t stream_retrans_bytes;
   2.525+
   2.526+    // The number of known paths for the connection.
   2.527+    size_t paths_count;
   2.528+
   2.529+    // The maximum idle timeout.
   2.530+    uint64_t peer_max_idle_timeout;
   2.531+
   2.532+    // The maximum UDP payload size.
   2.533+    uint64_t peer_max_udp_payload_size;
   2.534+
   2.535+    // The initial flow control maximum data for the connection.
   2.536+    uint64_t peer_initial_max_data;
   2.537+
   2.538+    // The initial flow control maximum data for local bidirectional streams.
   2.539+    uint64_t peer_initial_max_stream_data_bidi_local;
   2.540+
   2.541+    // The initial flow control maximum data for remote bidirectional streams.
   2.542+    uint64_t peer_initial_max_stream_data_bidi_remote;
   2.543+
   2.544+    // The initial flow control maximum data for unidirectional streams.
   2.545+    uint64_t peer_initial_max_stream_data_uni;
   2.546+
   2.547+    // The initial maximum bidirectional streams.
   2.548+    uint64_t peer_initial_max_streams_bidi;
   2.549+
   2.550+    // The initial maximum unidirectional streams.
   2.551+    uint64_t peer_initial_max_streams_uni;
   2.552+
   2.553+    // The ACK delay exponent.
   2.554+    uint64_t peer_ack_delay_exponent;
   2.555+
   2.556+    // The max ACK delay.
   2.557+    uint64_t peer_max_ack_delay;
   2.558+
   2.559+    // Whether active migration is disabled.
   2.560+    bool peer_disable_active_migration;
   2.561+
   2.562+    // The active connection ID limit.
   2.563+    uint64_t peer_active_conn_id_limit;
   2.564+
   2.565+    // DATAGRAM frame extension parameter, if any.
   2.566+    ssize_t peer_max_datagram_frame_size;
   2.567+} quiche_stats;
   2.568+
   2.569+// Collects and returns statistics about the connection.
   2.570+void quiche_conn_stats(const quiche_conn *conn, quiche_stats *out);
   2.571+
   2.572+typedef struct {
   2.573+    // The local address used by this path.
   2.574+    struct sockaddr_storage local_addr;
   2.575+    socklen_t local_addr_len;
   2.576+
   2.577+    // The peer address seen by this path.
   2.578+    struct sockaddr_storage peer_addr;
   2.579+    socklen_t peer_addr_len;
   2.580+
   2.581+    // The validation state of the path.
   2.582+    ssize_t validation_state;
   2.583+
   2.584+    // Whether this path is active.
   2.585+    bool active;
   2.586+
   2.587+    // The number of QUIC packets received on this path.
   2.588+    size_t recv;
   2.589+
   2.590+    // The number of QUIC packets sent on this path.
   2.591+    size_t sent;
   2.592+
   2.593+    // The number of QUIC packets that were lost on this path.
   2.594+    size_t lost;
   2.595+
   2.596+    // The number of sent QUIC packets with retransmitted data on this path.
   2.597+    size_t retrans;
   2.598+
   2.599+    // The estimated round-trip time of the path (in nanoseconds).
   2.600+    uint64_t rtt;
   2.601+
   2.602+    // The size of the path's congestion window in bytes.
   2.603+    size_t cwnd;
   2.604+
   2.605+    // The number of sent bytes on this path.
   2.606+    uint64_t sent_bytes;
   2.607+
   2.608+    // The number of received bytes on this path.
   2.609+    uint64_t recv_bytes;
   2.610+
   2.611+    // The number of bytes lost on this path.
   2.612+    uint64_t lost_bytes;
   2.613+
   2.614+    // The number of stream bytes retransmitted on this path.
   2.615+    uint64_t stream_retrans_bytes;
   2.616+
   2.617+    // The current PMTU for the path.
   2.618+    size_t pmtu;
   2.619+
   2.620+    // The most recent data delivery rate estimate in bytes/s.
   2.621+    uint64_t delivery_rate;
   2.622+} quiche_path_stats;
   2.623+
   2.624+
   2.625+// Collects and returns statistics about the specified path for the connection.
   2.626+//
   2.627+// The `idx` argument represent the path's index (also see the `paths_count`
   2.628+// field of `quiche_stats`).
   2.629+int quiche_conn_path_stats(const quiche_conn *conn, size_t idx, quiche_path_stats *out);
   2.630+
   2.631+// Returns whether or not this is a server-side connection.
   2.632+bool quiche_conn_is_server(const quiche_conn *conn);
   2.633+
   2.634+// Returns the maximum DATAGRAM payload that can be sent.
   2.635+ssize_t quiche_conn_dgram_max_writable_len(const quiche_conn *conn);
   2.636+
   2.637+// Returns the length of the first stored DATAGRAM.
   2.638+ssize_t quiche_conn_dgram_recv_front_len(const quiche_conn *conn);
   2.639+
   2.640+// Returns the number of items in the DATAGRAM receive queue.
   2.641+ssize_t quiche_conn_dgram_recv_queue_len(const quiche_conn *conn);
   2.642+
   2.643+// Returns the total size of all items in the DATAGRAM receive queue.
   2.644+ssize_t quiche_conn_dgram_recv_queue_byte_size(const quiche_conn *conn);
   2.645+
   2.646+// Returns the number of items in the DATAGRAM send queue.
   2.647+ssize_t quiche_conn_dgram_send_queue_len(const quiche_conn *conn);
   2.648+
   2.649+// Returns the total size of all items in the DATAGRAM send queue.
   2.650+ssize_t quiche_conn_dgram_send_queue_byte_size(const quiche_conn *conn);
   2.651+
   2.652+// Reads the first received DATAGRAM.
   2.653+ssize_t quiche_conn_dgram_recv(quiche_conn *conn, uint8_t *buf,
   2.654+                               size_t buf_len);
   2.655+
   2.656+// Sends data in a DATAGRAM frame.
   2.657+ssize_t quiche_conn_dgram_send(quiche_conn *conn, const uint8_t *buf,
   2.658+                               size_t buf_len);
   2.659+
   2.660+// Purges queued outgoing DATAGRAMs matching the predicate.
   2.661+void quiche_conn_dgram_purge_outgoing(quiche_conn *conn,
   2.662+                                      bool (*f)(uint8_t *, size_t));
   2.663+
   2.664+// Schedule an ack-eliciting packet on the active path.
   2.665+ssize_t quiche_conn_send_ack_eliciting(quiche_conn *conn);
   2.666+
   2.667+// Schedule an ack-eliciting packet on the specified path.
   2.668+ssize_t quiche_conn_send_ack_eliciting_on_path(quiche_conn *conn,
   2.669+                           const struct sockaddr *local, size_t local_len,
   2.670+                           const struct sockaddr *peer, size_t peer_len);
   2.671+
   2.672+// Frees the connection object.
   2.673+void quiche_conn_free(quiche_conn *conn);
   2.674+
   2.675+
   2.676+// HTTP/3 API
   2.677+//
   2.678+
   2.679+// List of ALPN tokens of supported HTTP/3 versions.
   2.680+#define QUICHE_H3_APPLICATION_PROTOCOL "\x02h3\x05h3-29\x05h3-28\x05h3-27"
   2.681+
   2.682+enum quiche_h3_error {
   2.683+    // There is no error or no work to do
   2.684+    QUICHE_H3_ERR_DONE = -1,
   2.685+
   2.686+    // The provided buffer is too short.
   2.687+    QUICHE_H3_ERR_BUFFER_TOO_SHORT = -2,
   2.688+
   2.689+    // Internal error in the HTTP/3 stack.
   2.690+    QUICHE_H3_ERR_INTERNAL_ERROR = -3,
   2.691+
   2.692+    // Endpoint detected that the peer is exhibiting behavior that causes.
   2.693+    // excessive load.
   2.694+    QUICHE_H3_ERR_EXCESSIVE_LOAD = -4,
   2.695+
   2.696+    // Stream ID or Push ID greater that current maximum was
   2.697+    // used incorrectly, such as exceeding a limit, reducing a limit,
   2.698+    // or being reused.
   2.699+    QUICHE_H3_ERR_ID_ERROR= -5,
   2.700+
   2.701+    // The endpoint detected that its peer created a stream that it will not
   2.702+    // accept.
   2.703+    QUICHE_H3_ERR_STREAM_CREATION_ERROR = -6,
   2.704+
   2.705+    // A required critical stream was closed.
   2.706+    QUICHE_H3_ERR_CLOSED_CRITICAL_STREAM = -7,
   2.707+
   2.708+    // No SETTINGS frame at beginning of control stream.
   2.709+    QUICHE_H3_ERR_MISSING_SETTINGS = -8,
   2.710+
   2.711+    // A frame was received which is not permitted in the current state.
   2.712+    QUICHE_H3_ERR_FRAME_UNEXPECTED = -9,
   2.713+
   2.714+    // Frame violated layout or size rules.
   2.715+    QUICHE_H3_ERR_FRAME_ERROR = -10,
   2.716+
   2.717+    // QPACK Header block decompression failure.
   2.718+    QUICHE_H3_ERR_QPACK_DECOMPRESSION_FAILED = -11,
   2.719+
   2.720+    // -12 was previously used for TransportError, skip it
   2.721+
   2.722+    // The underlying QUIC stream (or connection) doesn't have enough capacity
   2.723+    // for the operation to complete. The application should retry later on.
   2.724+    QUICHE_H3_ERR_STREAM_BLOCKED = -13,
   2.725+
   2.726+    // Error in the payload of a SETTINGS frame.
   2.727+    QUICHE_H3_ERR_SETTINGS_ERROR = -14,
   2.728+
   2.729+    // Server rejected request.
   2.730+    QUICHE_H3_ERR_REQUEST_REJECTED = -15,
   2.731+
   2.732+    // Request or its response cancelled.
   2.733+    QUICHE_H3_ERR_REQUEST_CANCELLED = -16,
   2.734+
   2.735+    // Client's request stream terminated without containing a full-formed
   2.736+    // request.
   2.737+    QUICHE_H3_ERR_REQUEST_INCOMPLETE = -17,
   2.738+
   2.739+    // An HTTP message was malformed and cannot be processed.
   2.740+    QUICHE_H3_ERR_MESSAGE_ERROR = -18,
   2.741+
   2.742+    // The TCP connection established in response to a CONNECT request was
   2.743+    // reset or abnormally closed.
   2.744+    QUICHE_H3_ERR_CONNECT_ERROR = -19,
   2.745+
   2.746+    // The requested operation cannot be served over HTTP/3. Peer should retry
   2.747+    // over HTTP/1.1.
   2.748+    QUICHE_H3_ERR_VERSION_FALLBACK = -20,
   2.749+
   2.750+    // The following QUICHE_H3_TRANSPORT_ERR_* errors are propagated
   2.751+    // from the QUIC transport layer.
   2.752+
   2.753+    // See QUICHE_ERR_DONE.
   2.754+    QUICHE_H3_TRANSPORT_ERR_DONE = QUICHE_ERR_DONE - 1000,
   2.755+
   2.756+    // See QUICHE_ERR_BUFFER_TOO_SHORT.
   2.757+    QUICHE_H3_TRANSPORT_ERR_BUFFER_TOO_SHORT = QUICHE_ERR_BUFFER_TOO_SHORT - 1000,
   2.758+
   2.759+    // See QUICHE_ERR_UNKNOWN_VERSION.
   2.760+    QUICHE_H3_TRANSPORT_ERR_UNKNOWN_VERSION = QUICHE_ERR_UNKNOWN_VERSION - 1000,
   2.761+
   2.762+    // See QUICHE_ERR_INVALID_FRAME.
   2.763+    QUICHE_H3_TRANSPORT_ERR_INVALID_FRAME = QUICHE_ERR_INVALID_FRAME - 1000,
   2.764+
   2.765+    // See QUICHE_ERR_INVALID_PACKET.
   2.766+    QUICHE_H3_TRANSPORT_ERR_INVALID_PACKET = QUICHE_ERR_INVALID_PACKET - 1000,
   2.767+
   2.768+    // See QUICHE_ERR_INVALID_STATE.
   2.769+    QUICHE_H3_TRANSPORT_ERR_INVALID_STATE = QUICHE_ERR_INVALID_STATE - 1000,
   2.770+
   2.771+    // See QUICHE_ERR_INVALID_STREAM_STATE.
   2.772+    QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE = QUICHE_ERR_INVALID_STREAM_STATE - 1000,
   2.773+
   2.774+    // See QUICHE_ERR_INVALID_TRANSPORT_PARAM.
   2.775+    QUICHE_H3_TRANSPORT_ERR_INVALID_TRANSPORT_PARAM = QUICHE_ERR_INVALID_TRANSPORT_PARAM - 1000,
   2.776+
   2.777+    // See QUICHE_ERR_CRYPTO_FAIL.
   2.778+    QUICHE_H3_TRANSPORT_ERR_CRYPTO_FAIL = QUICHE_ERR_CRYPTO_FAIL - 1000,
   2.779+
   2.780+    // See QUICHE_ERR_TLS_FAIL.
   2.781+    QUICHE_H3_TRANSPORT_ERR_TLS_FAIL = QUICHE_ERR_TLS_FAIL - 1000,
   2.782+
   2.783+    // See QUICHE_ERR_FLOW_CONTROL.
   2.784+    QUICHE_H3_TRANSPORT_ERR_FLOW_CONTROL = QUICHE_ERR_FLOW_CONTROL - 1000,
   2.785+
   2.786+    // See QUICHE_ERR_STREAM_LIMIT.
   2.787+    QUICHE_H3_TRANSPORT_ERR_STREAM_LIMIT = QUICHE_ERR_STREAM_LIMIT - 1000,
   2.788+
   2.789+    // See QUICHE_ERR_STREAM_STOPPED.
   2.790+    QUICHE_H3_TRANSPORT_ERR_STREAM_STOPPED = QUICHE_ERR_STREAM_STOPPED - 1000,
   2.791+
   2.792+    // See QUICHE_ERR_STREAM_RESET.
   2.793+    QUICHE_H3_TRANSPORT_ERR_STREAM_RESET = QUICHE_ERR_STREAM_RESET - 1000,
   2.794+
   2.795+    // See QUICHE_ERR_FINAL_SIZE.
   2.796+    QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE = QUICHE_ERR_FINAL_SIZE - 1000,
   2.797+
   2.798+    // See QUICHE_ERR_CONGESTION_CONTROL.
   2.799+    QUICHE_H3_TRANSPORT_ERR_CONGESTION_CONTROL = QUICHE_ERR_CONGESTION_CONTROL - 1000,
   2.800+
   2.801+    // See QUICHE_ERR_ID_LIMIT.
   2.802+    QUICHE_H3_TRANSPORT_ERR_ID_LIMIT = QUICHE_ERR_ID_LIMIT - 1000,
   2.803+
   2.804+    // See QUICHE_ERR_OUT_OF_IDENTIFIERS.
   2.805+    QUICHE_H3_TRANSPORT_ERR_OUT_OF_IDENTIFIERS = QUICHE_ERR_OUT_OF_IDENTIFIERS - 1000,
   2.806+
   2.807+    // See QUICHE_ERR_KEY_UPDATE.
   2.808+    QUICHE_H3_TRANSPORT_ERR_KEY_UPDATE = QUICHE_ERR_KEY_UPDATE - 1000,
   2.809+};
   2.810+
   2.811+// Stores configuration shared between multiple connections.
   2.812+typedef struct quiche_h3_config quiche_h3_config;
   2.813+
   2.814+// Creates an HTTP/3 config object with default settings values.
   2.815+quiche_h3_config *quiche_h3_config_new(void);
   2.816+
   2.817+// Sets the `SETTINGS_MAX_FIELD_SECTION_SIZE` setting.
   2.818+void quiche_h3_config_set_max_field_section_size(quiche_h3_config *config, uint64_t v);
   2.819+
   2.820+// Sets the `SETTINGS_QPACK_MAX_TABLE_CAPACITY` setting.
   2.821+void quiche_h3_config_set_qpack_max_table_capacity(quiche_h3_config *config, uint64_t v);
   2.822+
   2.823+// Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting.
   2.824+void quiche_h3_config_set_qpack_blocked_streams(quiche_h3_config *config, uint64_t v);
   2.825+
   2.826+// Sets the `SETTINGS_ENABLE_CONNECT_PROTOCOL` setting.
   2.827+void quiche_h3_config_enable_extended_connect(quiche_h3_config *config, bool enabled);
   2.828+
   2.829+// Frees the HTTP/3 config object.
   2.830+void quiche_h3_config_free(quiche_h3_config *config);
   2.831+
   2.832+// An HTTP/3 connection.
   2.833+typedef struct quiche_h3_conn quiche_h3_conn;
   2.834+
   2.835+// Creates a new server-side connection.
   2.836+quiche_h3_conn *quiche_h3_accept(quiche_conn *quiche_conn,
   2.837+                                 quiche_h3_config *config);
   2.838+
   2.839+// Creates a new HTTP/3 connection using the provided QUIC connection.
   2.840+quiche_h3_conn *quiche_h3_conn_new_with_transport(quiche_conn *quiche_conn,
   2.841+                                                  quiche_h3_config *config);
   2.842+
   2.843+enum quiche_h3_event_type {
   2.844+    QUICHE_H3_EVENT_HEADERS,
   2.845+    QUICHE_H3_EVENT_DATA,
   2.846+    QUICHE_H3_EVENT_FINISHED,
   2.847+    QUICHE_H3_EVENT_DATAGRAM,
   2.848+    QUICHE_H3_EVENT_GOAWAY,
   2.849+    QUICHE_H3_EVENT_RESET,
   2.850+    QUICHE_H3_EVENT_PRIORITY_UPDATE,
   2.851+};
   2.852+
   2.853+typedef struct quiche_h3_event quiche_h3_event;
   2.854+
   2.855+// Processes HTTP/3 data received from the peer.
   2.856+int64_t quiche_h3_conn_poll(quiche_h3_conn *conn, quiche_conn *quic_conn,
   2.857+                            quiche_h3_event **ev);
   2.858+
   2.859+// Returns the type of the event.
   2.860+enum quiche_h3_event_type quiche_h3_event_type(quiche_h3_event *ev);
   2.861+
   2.862+// Iterates over the headers in the event.
   2.863+//
   2.864+// The `cb` callback will be called for each header in `ev`. `cb` should check
   2.865+// the validity of pseudo-headers and headers. If `cb` returns any value other
   2.866+// than `0`, processing will be interrupted and the value is returned to the
   2.867+// caller.
   2.868+int quiche_h3_event_for_each_header(quiche_h3_event *ev,
   2.869+                                    int (*cb)(uint8_t *name, size_t name_len,
   2.870+                                              uint8_t *value, size_t value_len,
   2.871+                                              void *argp),
   2.872+                                    void *argp);
   2.873+
   2.874+// Iterates over the peer's HTTP/3 settings.
   2.875+//
   2.876+// The `cb` callback will be called for each setting in `conn`.
   2.877+// If `cb` returns any value other than `0`, processing will be interrupted and
   2.878+// the value is returned to the caller.
   2.879+int quiche_h3_for_each_setting(quiche_h3_conn *conn,
   2.880+                               int (*cb)(uint64_t identifier,
   2.881+                                         uint64_t value, void *argp),
   2.882+                               void *argp);
   2.883+
   2.884+// Check whether data will follow the headers on the stream.
   2.885+bool quiche_h3_event_headers_has_body(quiche_h3_event *ev);
   2.886+
   2.887+// Check whether or not extended connection is enabled by the peer
   2.888+bool quiche_h3_extended_connect_enabled_by_peer(quiche_h3_conn *conn);
   2.889+
   2.890+// Frees the HTTP/3 event object.
   2.891+void quiche_h3_event_free(quiche_h3_event *ev);
   2.892+
   2.893+typedef struct {
   2.894+    const uint8_t *name;
   2.895+    size_t name_len;
   2.896+
   2.897+    const uint8_t *value;
   2.898+    size_t value_len;
   2.899+} quiche_h3_header;
   2.900+
   2.901+// Extensible Priorities parameters.
   2.902+typedef struct {
   2.903+    uint8_t urgency;
   2.904+    bool incremental;
   2.905+} quiche_h3_priority;
   2.906+
   2.907+// Sends an HTTP/3 request.
   2.908+int64_t quiche_h3_send_request(quiche_h3_conn *conn, quiche_conn *quic_conn,
   2.909+                               quiche_h3_header *headers, size_t headers_len,
   2.910+                               bool fin);
   2.911+
   2.912+// Sends an HTTP/3 response on the specified stream with default priority.
   2.913+int quiche_h3_send_response(quiche_h3_conn *conn, quiche_conn *quic_conn,
   2.914+                            uint64_t stream_id, quiche_h3_header *headers,
   2.915+                            size_t headers_len, bool fin);
   2.916+
   2.917+// Sends an HTTP/3 response on the specified stream with specified priority.
   2.918+int quiche_h3_send_response_with_priority(quiche_h3_conn *conn,
   2.919+                            quiche_conn *quic_conn, uint64_t stream_id,
   2.920+                            quiche_h3_header *headers, size_t headers_len,
   2.921+                            quiche_h3_priority *priority, bool fin);
   2.922+
   2.923+// Sends an HTTP/3 body chunk on the given stream.
   2.924+ssize_t quiche_h3_send_body(quiche_h3_conn *conn, quiche_conn *quic_conn,
   2.925+                            uint64_t stream_id, uint8_t *body, size_t body_len,
   2.926+                            bool fin);
   2.927+
   2.928+// Reads request or response body data into the provided buffer.
   2.929+ssize_t quiche_h3_recv_body(quiche_h3_conn *conn, quiche_conn *quic_conn,
   2.930+                            uint64_t stream_id, uint8_t *out, size_t out_len);
   2.931+
   2.932+// Try to parse an Extensible Priority field value.
   2.933+int quiche_h3_parse_extensible_priority(uint8_t *priority,
   2.934+                                        size_t priority_len,
   2.935+                                        quiche_h3_priority *parsed);
   2.936+
   2.937+/// Sends a PRIORITY_UPDATE frame on the control stream with specified
   2.938+/// request stream ID and priority.
   2.939+int quiche_h3_send_priority_update_for_request(quiche_h3_conn *conn,
   2.940+                                               quiche_conn *quic_conn,
   2.941+                                               uint64_t stream_id,
   2.942+                                               quiche_h3_priority *priority);
   2.943+
   2.944+// Take the last received PRIORITY_UPDATE frame for a stream.
   2.945+//
   2.946+// The `cb` callback will be called once. `cb` should check the validity of
   2.947+// priority field value contents. If `cb` returns any value other than `0`,
   2.948+// processing will be interrupted and the value is returned to the caller.
   2.949+int quiche_h3_take_last_priority_update(quiche_h3_conn *conn,
   2.950+                                        uint64_t prioritized_element_id,
   2.951+                                        int (*cb)(uint8_t  *priority_field_value,
   2.952+                                                  uint64_t priority_field_value_len,
   2.953+                                                  void *argp),
   2.954+                                        void *argp);
   2.955+
   2.956+// Returns whether the peer enabled HTTP/3 DATAGRAM frame support.
   2.957+bool quiche_h3_dgram_enabled_by_peer(quiche_h3_conn *conn,
   2.958+                                     quiche_conn *quic_conn);
   2.959+
   2.960+// Writes data to the DATAGRAM send queue.
   2.961+ssize_t quiche_h3_send_dgram(quiche_h3_conn *conn, quiche_conn *quic_conn,
   2.962+                            uint64_t flow_id, uint8_t *data, size_t data_len);
   2.963+
   2.964+// Reads data from the DATAGRAM receive queue.
   2.965+ssize_t quiche_h3_recv_dgram(quiche_h3_conn *conn, quiche_conn *quic_conn,
   2.966+                            uint64_t *flow_id, size_t *flow_id_len,
   2.967+                            uint8_t *out, size_t out_len);
   2.968+
   2.969+// Frees the HTTP/3 connection object.
   2.970+void quiche_h3_conn_free(quiche_h3_conn *conn);
   2.971+
   2.972+#if defined(__cplusplus)
   2.973+}  // extern C
   2.974+#endif
   2.975+
   2.976+#endif // QUICHE_H
     3.1--- a/ui.lisp	Sun May 14 21:27:04 2023 -0400
     3.2+++ b/ui.lisp	Mon May 15 21:40:24 2023 -0400
     3.3@@ -1,6 +1,29 @@
     3.4 (in-package :demo)
     3.5+
     3.6+(defparameter ui-server-port 8080)
     3.7+(defparameter ui-server-host "0.0.0.0")
     3.8+
     3.9+(defclass ui-element (clog-element) ()
    3.10+  (:documentation "UI Element Object."))
    3.11+
    3.12+(defgeneric create-ui-element (obj &key hidden class id mode)
    3.13+  (:documentation "Create a new ui-element as a child of OBJ."))
    3.14+(defmethod create-ui-element ((obj clog:clog-obj)
    3.15+			      &key (class nil)
    3.16+				(hidden nil)
    3.17+				(id nil)
    3.18+				(mode 'auto))
    3.19+  (let ((new (clog:create-div obj
    3.20+			      :class class
    3.21+			      :hidden hidden
    3.22+			      :id id
    3.23+			      :mode mode)))
    3.24+    (clog:set-geometry new :width 200 :height 100)
    3.25+    (change-class new 'ui-element)))
    3.26+			      
    3.27 (defun on-new-window (body)
    3.28   "Handle new window event."
    3.29+  (clog:debug-mode body)
    3.30   (let ((elt (clog:create-child body "<h1>foobar</h1>")))
    3.31     (clog:set-on-click
    3.32      elt
    3.33@@ -9,5 +32,12 @@
    3.34 
    3.35 (defun start-ui ()
    3.36   "Start the UI."
    3.37-  (clog:initialize #'on-new-window)
    3.38+  (clog:initialize #'on-new-window
    3.39+		   :extended-routing t
    3.40+		   :host ui-server-host
    3.41+		   :port ui-server-port)
    3.42   (clog:open-browser))
    3.43+
    3.44+(defun stop-ui ()
    3.45+  "Stop the UI."
    3.46+  (clog:shutdown))
     4.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2+++ b/www/boot.html	Mon May 15 21:40:24 2023 -0400
     4.3@@ -0,0 +1,17 @@
     4.4+<!doctype HTML>
     4.5+<HTML>
     4.6+   <HEAD>
     4.7+      <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
     4.8+      <meta http-equiv="Pragma" content="no-cache" />
     4.9+      <meta http-equiv="Expires" content="0" />
    4.10+      <meta charset="utf-8">
    4.11+      <meta name="viewport" content="width=device-width, initial-scale=1">
    4.12+      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    4.13+      <script src="/js/boot.js" type="text/javascript"></script>
    4.14+      <noscript><%= (@ meta) %></noscript>
    4.15+   </HEAD>
    4.16+<BODY>
    4.17+  <noscript><%= (@ body) %></noscript>
    4.18+</BODY>
    4.19+<noscript>Your browser must support JavaScript and be HTML 5 compilant to see this site.</noscript>
    4.20+</HTML>
     5.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2+++ b/www/bootstrap.html	Mon May 15 21:40:24 2023 -0400
     5.3@@ -0,0 +1,19 @@
     5.4+<!doctype HTML>
     5.5+<HTML>
     5.6+   <HEAD>
     5.7+      <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
     5.8+      <meta http-equiv="Pragma" content="no-cache" />
     5.9+      <meta http-equiv="Expires" content="0" />
    5.10+      <meta charset="utf-8">
    5.11+      <meta name="viewport" content="width=device-width, initial-scale=1">
    5.12+      <script src="/js/jquery.min.js" type="text/javascript"></script>
    5.13+      <script src="/js/boot.js" type="text/javascript"></script>
    5.14+      <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
    5.15+      <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js" crossorigin="anonymous"></script>
    5.16+      <noscript><%= (@ meta) %></noscript>
    5.17+   </HEAD>
    5.18+<BODY>
    5.19+  <noscript><%= (@ body) %></noscript>
    5.20+</BODY>
    5.21+<noscript>Your browser must support JavaScript and be HTML 5 compilant to see this site.</noscript>
    5.22+</HTML>
     6.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2+++ b/www/css/w3.css	Mon May 15 21:40:24 2023 -0400
     6.3@@ -0,0 +1,235 @@
     6.4+/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
     6.5+html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
     6.6+/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
     6.7+html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
     6.8+article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
     6.9+audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
    6.10+audio:not([controls]){display:none;height:0}[hidden],template{display:none}
    6.11+a{background-color:transparent}a:active,a:hover{outline-width:0}
    6.12+abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
    6.13+b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
    6.14+small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
    6.15+sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
    6.16+code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
    6.17+button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
    6.18+button,input{overflow:visible}button,select{text-transform:none}
    6.19+button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
    6.20+button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
    6.21+button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
    6.22+fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
    6.23+legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
    6.24+[type=checkbox],[type=radio]{padding:0}
    6.25+[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
    6.26+[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
    6.27+[type=search]::-webkit-search-decoration{-webkit-appearance:none}
    6.28+::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
    6.29+/* End extract */
    6.30+html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
    6.31+h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
    6.32+.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
    6.33+h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
    6.34+hr{border:0;border-top:1px solid #eee;margin:20px 0}
    6.35+.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
    6.36+.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
    6.37+.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
    6.38+.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
    6.39+.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
    6.40+.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
    6.41+.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
    6.42+.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
    6.43+.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
    6.44+.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}   
    6.45+.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
    6.46+.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
    6.47+.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
    6.48+.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
    6.49+.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
    6.50+.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
    6.51+.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
    6.52+.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
    6.53+.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
    6.54+.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
    6.55+.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
    6.56+.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
    6.57+.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
    6.58+.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
    6.59+.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
    6.60+.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
    6.61+.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
    6.62+.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
    6.63+.w3-main,#main{transition:margin-left .4s}
    6.64+.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
    6.65+.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
    6.66+.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
    6.67+.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
    6.68+.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
    6.69+.w3-bar .w3-button{white-space:normal}
    6.70+.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
    6.71+.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
    6.72+.w3-responsive{display:block;overflow-x:auto}
    6.73+.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
    6.74+.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
    6.75+.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
    6.76+.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
    6.77+.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
    6.78+.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
    6.79+@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
    6.80+.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
    6.81+.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
    6.82+@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
    6.83+.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
    6.84+.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
    6.85+.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
    6.86+.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
    6.87+.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
    6.88+.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
    6.89+.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
    6.90+@media (max-width:1205px){.w3-auto{max-width:95%}}
    6.91+@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
    6.92+.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}	
    6.93+.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
    6.94+.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
    6.95+@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
    6.96+@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
    6.97+@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
    6.98+@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
    6.99+.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
   6.100+.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
   6.101+.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
   6.102+.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
   6.103+.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
   6.104+.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
   6.105+.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
   6.106+.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
   6.107+.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
   6.108+.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
   6.109+.w3-display-position{position:absolute}
   6.110+.w3-circle{border-radius:50%}
   6.111+.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
   6.112+.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
   6.113+.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
   6.114+.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
   6.115+.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
   6.116+.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
   6.117+.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
   6.118+.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
   6.119+.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
   6.120+.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
   6.121+.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
   6.122+.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
   6.123+.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
   6.124+.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
   6.125+.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
   6.126+.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
   6.127+.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
   6.128+.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
   6.129+.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
   6.130+.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
   6.131+.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
   6.132+.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
   6.133+.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
   6.134+.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
   6.135+.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
   6.136+.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
   6.137+.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
   6.138+.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
   6.139+.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
   6.140+.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
   6.141+.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
   6.142+.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
   6.143+.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
   6.144+.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
   6.145+.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
   6.146+.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
   6.147+.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
   6.148+.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
   6.149+.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
   6.150+.w3-left{float:left!important}.w3-right{float:right!important}
   6.151+.w3-button:hover{color:#000!important;background-color:#ccc!important}
   6.152+.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
   6.153+.w3-hover-none:hover{box-shadow:none!important}
   6.154+/* Colors */
   6.155+.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
   6.156+.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
   6.157+.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
   6.158+.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
   6.159+.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
   6.160+.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
   6.161+.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
   6.162+.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
   6.163+.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
   6.164+.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
   6.165+.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
   6.166+.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
   6.167+.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
   6.168+.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
   6.169+.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
   6.170+.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
   6.171+.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
   6.172+.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
   6.173+.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
   6.174+.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
   6.175+.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
   6.176+.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
   6.177+.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
   6.178+.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
   6.179+.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
   6.180+.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
   6.181+.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
   6.182+.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
   6.183+.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
   6.184+.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
   6.185+.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
   6.186+.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
   6.187+.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
   6.188+.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
   6.189+.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
   6.190+.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
   6.191+.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
   6.192+.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
   6.193+.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
   6.194+.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
   6.195+.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
   6.196+.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
   6.197+.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
   6.198+.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
   6.199+.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
   6.200+.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
   6.201+.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
   6.202+.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
   6.203+.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
   6.204+.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
   6.205+.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
   6.206+.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
   6.207+.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
   6.208+.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
   6.209+.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
   6.210+.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
   6.211+.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
   6.212+.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
   6.213+.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
   6.214+.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
   6.215+.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
   6.216+.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
   6.217+.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
   6.218+.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
   6.219+.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
   6.220+.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
   6.221+.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
   6.222+.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
   6.223+.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
   6.224+.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
   6.225+.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
   6.226+.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
   6.227+.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
   6.228+.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
   6.229+.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
   6.230+.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
   6.231+.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
   6.232+.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
   6.233+.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
   6.234+.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
   6.235+.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
   6.236+.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
   6.237+.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
   6.238+.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}
     8.1--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2+++ b/www/robots.txt	Mon May 15 21:40:24 2023 -0400
     8.3@@ -0,0 +1,2 @@
     8.4+User-agent: *
     8.5+Disallow: