1 /*
2  * Copyright (c) 2018 Fastly, Kazuho
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to
6  * deal in the Software without restriction, including without limitation the
7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8  * sell copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20  * IN THE SOFTWARE.
21  */
22 #ifndef h2o__http3_common_h
23 #define h2o__http3_common_h
24 
25 #include <string.h>
26 #include <sys/socket.h>
27 #include "quicly.h"
28 #include "quicly/defaults.h"
29 #include "h2o/absprio.h"
30 #include "h2o/memory.h"
31 #include "h2o/socket.h"
32 #include "h2o/qpack.h"
33 
34 #define H2O_HTTP3_FRAME_TYPE_DATA 0
35 #define H2O_HTTP3_FRAME_TYPE_HEADERS 1
36 #define H2O_HTTP3_FRAME_TYPE_CANCEL_PUSH 3
37 #define H2O_HTTP3_FRAME_TYPE_SETTINGS 4
38 #define H2O_HTTP3_FRAME_TYPE_PUSH_PROMISE 5
39 #define H2O_HTTP3_FRAME_TYPE_GOAWAY 7
40 #define H2O_HTTP3_FRAME_TYPE_MAX_PUSH_ID 13
41 #define H2O_HTTP3_FRAME_TYPE_PRIORITY_UPDATE 15
42 
43 #define H2O_HTTP3_STREAM_TYPE_CONTROL 0
44 #define H2O_HTTP3_STREAM_TYPE_PUSH_STREAM 1
45 #define H2O_HTTP3_STREAM_TYPE_QPACK_ENCODER 2
46 #define H2O_HTTP3_STREAM_TYPE_QPACK_DECODER 3
47 #define H2O_HTTP3_STREAM_TYPE_REQUEST 0x4000000000000000 /* internal type */
48 
49 #define H2O_HTTP3_SETTINGS_QPACK_MAX_TABLE_CAPACITY 1
50 #define H2O_HTTP3_SETTINGS_MAX_FIELD_SECTION_SIZE 6
51 #define H2O_HTTP3_SETTINGS_QPACK_BLOCKED_STREAMS 7
52 #define H2O_HTTP3_SETTINGS_H3_DATAGRAM 0x276
53 
54 #define H2O_HTTP3_ERROR_NONE QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x100)
55 #define H2O_HTTP3_ERROR_GENERAL_PROTOCOL QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x101)
56 #define H2O_HTTP3_ERROR_INTERNAL QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x102)
57 #define H2O_HTTP3_ERROR_STREAM_CREATION QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x103)
58 #define H2O_HTTP3_ERROR_CLOSED_CRITICAL_STREAM QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x104)
59 #define H2O_HTTP3_ERROR_FRAME_UNEXPECTED QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x105)
60 #define H2O_HTTP3_ERROR_FRAME QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x106)
61 #define H2O_HTTP3_ERROR_EXCESSIVE_LOAD QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x107)
62 #define H2O_HTTP3_ERROR_ID QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x108)
63 #define H2O_HTTP3_ERROR_SETTINGS QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x109)
64 #define H2O_HTTP3_ERROR_MISSING_SETTINGS QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x10a)
65 #define H2O_HTTP3_ERROR_REQUEST_REJECTED QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x10b)
66 #define H2O_HTTP3_ERROR_REQUEST_CANCELLED QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x10c)
67 #define H2O_HTTP3_ERROR_REQUEST_INCOMPLETE QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x10d)
68 #define H2O_HTTP3_ERROR_EARLY_RESPONSE QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x10e)
69 #define H2O_HTTP3_ERROR_CONNECT_ERROR QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x10f)
70 #define H2O_HTTP3_ERROR_VERSION_FALLBACK QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x110)
71 #define H2O_HTTP3_ERROR_QPACK_DECOMPRESSION_FAILED QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x200)
72 #define H2O_HTTP3_ERROR_QPACK_ENCODER_STREAM QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x201)
73 #define H2O_HTTP3_ERROR_QPACK_DECODER_STREAM QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(0x202)
74 
75 #define H2O_HTTP3_ERROR_INCOMPLETE -1
76 #define H2O_HTTP3_ERROR_TRANSPORT -2
77 #define H2O_HTTP3_ERROR_USER1 -256
78 
79 /**
80  * maximum payload size excluding DATA frame; stream receive window MUST be at least as big as this + 16 bytes to hold the type and
81  * the length
82  */
83 #define H2O_HTTP3_MAX_FRAME_PAYLOAD_SIZE 16384
84 #define H2O_HTTP3_INITIAL_REQUEST_STREAM_WINDOW_SIZE (H2O_HTTP3_MAX_FRAME_PAYLOAD_SIZE * 2)
85 
86 typedef struct st_h2o_quic_ctx_t h2o_quic_ctx_t;
87 typedef struct st_h2o_quic_conn_t h2o_quic_conn_t;
88 typedef struct st_h2o_http3_conn_t h2o_http3_conn_t;
89 struct st_h2o_http3_ingress_unistream_t;
90 struct st_h2o_http3_egress_unistream_t;
91 struct kh_h2o_quic_idmap_s;
92 struct kh_h2o_http3_unauthmap_s;
93 
94 typedef enum en_h2o_http3_priority_element_type_t {
95     H2O_HTTP3_PRIORITY_ELEMENT_TYPE_REQUEST_STREAM,
96     H2O_HTTP3_PRIORITY_ELEMENT_TYPE_PUSH_STREAM,
97     H2O_HTTP3_PRIORITY_ELEMENT_TYPE_PLACEHOLDER,
98     /**
99      * root (when used as element dependency type)
100      */
101     H2O_HTTP3_PRIORITY_ELEMENT_TYPE_ROOT
102 } h2o_http3_priority_element_type_t;
103 
104 typedef struct st_h2o_http3_priority_update_frame_t {
105     uint64_t element_is_push : 1;
106     uint64_t element : 63;
107     h2o_absprio_t priority;
108 } h2o_http3_priority_update_frame_t;
109 
110 typedef struct st_h2o_http3_goaway_frame_t {
111     uint64_t stream_or_push_id;
112 } h2o_http3_goaway_frame_t;
113 
114 #define H2O_HTTP3_PRIORITY_UPDATE_FRAME_CAPACITY (1 /* len */ + 1 /* frame type */ + 8 + sizeof("u=1,i=?0") - 1)
115 uint8_t *h2o_http3_encode_priority_update_frame(uint8_t *dst, const h2o_http3_priority_update_frame_t *frame);
116 int h2o_http3_decode_priority_update_frame(h2o_http3_priority_update_frame_t *frame, const uint8_t *payload, size_t len,
117                                            const char **err_desc);
118 size_t h2o_http3_goaway_frame_capacity(quicly_stream_id_t stream_or_push_id);
119 uint8_t *h2o_http3_encode_goaway_frame(uint8_t *buff, quicly_stream_id_t stream_or_push_id);
120 int h2o_http3_decode_goaway_frame(h2o_http3_goaway_frame_t *frame, const uint8_t *payload, size_t len, const char **err_desc);
121 
122 /**
123  * special error value to be returned by h2o_quic_accept_cb, to indicate that packet decryption failed during quicly_accept
124  */
125 #define H2O_QUIC_ACCEPT_CONN_DECRYPTION_FAILED ((h2o_quic_conn_t *)1)
126 
127 /**
128  * Accepts a new QUIC connection
129  * @return a pointer to a new connection object upon success, NULL or H2O_QUIC_ACCEPT_CONN_DECRYPTION_FAILED upon failure.
130  */
131 typedef h2o_quic_conn_t *(*h2o_quic_accept_cb)(h2o_quic_ctx_t *ctx, quicly_address_t *destaddr, quicly_address_t *srcaddr,
132                                                quicly_decoded_packet_t *packet);
133 typedef void (*h2o_quic_notify_connection_update_cb)(h2o_quic_ctx_t *ctx, h2o_quic_conn_t *conn);
134 /**
135  * Forwards a packet to given node/thread.
136  * When `node_id` is NULL, the forwarded packet is an Initial or a 0-RTT packet.  Application should forward the packet to given
137  * thread, or if the thread points to the current thread (which happens when acceptor is set to NULL) forward the packet to the
138  * next generation process (graceful restart).
139  * When `node_id` is not NULL, the forwarded packet is an Handshake or a 1-RTT packet.  Application should forward the packet to
140  * given thread / node if the values are valid.  Otherwise, it should return false, which in turn triggers the code that checks if
141  * the packet is a stateless reset.
142  * @return true if packet was forwarded (or was forwardable), otherwise false
143  */
144 typedef int (*h2o_quic_forward_packets_cb)(h2o_quic_ctx_t *ctx, const uint64_t *node_id, uint32_t thread_id,
145                                            quicly_address_t *destaddr, quicly_address_t *srcaddr, uint8_t ttl,
146                                            quicly_decoded_packet_t *packets, size_t num_packets);
147 /**
148  * preprocess a received datagram (e.g., rewrite the sockaddr). Returns if the packet was modified.
149  */
150 typedef int (*h2o_quic_preprocess_packet_cb)(h2o_quic_ctx_t *ctx, struct msghdr *msghdr, quicly_address_t *destaddr,
151                                              quicly_address_t *srcaddr, uint8_t *ttl);
152 
153 /**
154  * Holds the counters. It is mere coincident that the members are equivalent with QUICLY_STATS_PREBUILT_FIELDS. The macro below can
155  * be used for generating expression that take all the members equally.
156  */
157 struct st_h2o_quic_aggregated_stats_t {
158     QUICLY_STATS_PREBUILT_FIELDS;
159 };
160 
161 typedef struct st_h2o_quic_stats_t {
162     /**
163      * number of quic packets received
164      */
165     uint64_t packet_received;
166     /**
167      * number of quic packets successfully used for a connection
168      */
169     uint64_t packet_processed;
170 
171     /**
172      * aggregated quicly stats
173      */
174     struct st_h2o_quic_aggregated_stats_t quicly;
175 } h2o_quic_stats_t;
176 
177 /* clang-format off */
178 #define H2O_QUIC_AGGREGATED_STATS_APPLY(func) \
179     func(num_packets.received, "num-packets.received") \
180     func(num_packets.decryption_failed, "num-packets.decryption-failed") \
181     func(num_packets.sent, "num-packets.sent") \
182     func(num_packets.lost, "num-packets.lost") \
183     func(num_packets.lost_time_threshold, "num-packets.lost-time-threshold") \
184     func(num_packets.ack_received, "num-packets.ack-received") \
185     func(num_packets.late_acked, "num-packets.late-acked") \
186     func(num_bytes.received, "num-bytes.received") \
187     func(num_bytes.sent, "num-bytes.sent") \
188     func(num_bytes.lost, "num-bytes.lost") \
189     func(num_bytes.stream_data_sent, "num-bytes.stream-data-sent") \
190     func(num_bytes.stream_data_resent, "num-bytes.stream-data-resent") \
191     func(num_frames_sent.padding, "num-frames-sent.padding") \
192     func(num_frames_sent.ping, "num-frames-sent.ping") \
193     func(num_frames_sent.ack, "num-frames-sent.ack") \
194     func(num_frames_sent.reset_stream, "num-frames-sent.reset_stream") \
195     func(num_frames_sent.stop_sending, "num-frames-sent.stop_sending") \
196     func(num_frames_sent.crypto, "num-frames-sent.crypto") \
197     func(num_frames_sent.new_token, "num-frames-sent.new_token") \
198     func(num_frames_sent.stream, "num-frames-sent.stream") \
199     func(num_frames_sent.max_data, "num-frames-sent.max_data") \
200     func(num_frames_sent.max_stream_data, "num-frames-sent.max_stream_data") \
201     func(num_frames_sent.max_streams_bidi, "num-frames-sent.max_streams_bidi") \
202     func(num_frames_sent.max_streams_uni, "num-frames-sent.max_streams_uni") \
203     func(num_frames_sent.data_blocked, "num-frames-sent.data_blocked") \
204     func(num_frames_sent.stream_data_blocked, "num-frames-sent.stream_data_blocked") \
205     func(num_frames_sent.streams_blocked, "num-frames-sent.streams_blocked") \
206     func(num_frames_sent.new_connection_id, "num-frames-sent.new_connection_id") \
207     func(num_frames_sent.retire_connection_id, "num-frames-sent.retire_connection_id") \
208     func(num_frames_sent.path_challenge, "num-frames-sent.path_challenge") \
209     func(num_frames_sent.path_response, "num-frames-sent.path_response") \
210     func(num_frames_sent.transport_close, "num-frames-sent.transport_close") \
211     func(num_frames_sent.application_close, "num-frames-sent.application_close") \
212     func(num_frames_sent.handshake_done, "num-frames-sent.handshake_done") \
213     func(num_frames_sent.datagram, "num-frames-sent.datagram") \
214     func(num_frames_sent.ack_frequency, "num-frames-sent.ack_frequency") \
215     func(num_frames_received.padding, "num-frames-received.padding") \
216     func(num_frames_received.ping, "num-frames-received.ping") \
217     func(num_frames_received.ack, "num-frames-received.ack") \
218     func(num_frames_received.reset_stream, "num-frames-received.reset_stream") \
219     func(num_frames_received.stop_sending, "num-frames-received.stop_sending") \
220     func(num_frames_received.crypto, "num-frames-received.crypto") \
221     func(num_frames_received.new_token, "num-frames-received.new_token") \
222     func(num_frames_received.stream, "num-frames-received.stream") \
223     func(num_frames_received.max_data, "num-frames-received.max_data") \
224     func(num_frames_received.max_stream_data, "num-frames-received.max_stream_data") \
225     func(num_frames_received.max_streams_bidi, "num-frames-received.max_streams_bidi") \
226     func(num_frames_received.max_streams_uni, "num-frames-received.max_streams_uni") \
227     func(num_frames_received.data_blocked, "num-frames-received.data_blocked") \
228     func(num_frames_received.stream_data_blocked, "num-frames-received.stream_data_blocked") \
229     func(num_frames_received.streams_blocked, "num-frames-received.streams_blocked") \
230     func(num_frames_received.new_connection_id, "num-frames-received.new_connection_id") \
231     func(num_frames_received.retire_connection_id, "num-frames-received.retire_connection_id") \
232     func(num_frames_received.path_challenge, "num-frames-received.path_challenge") \
233     func(num_frames_received.path_response, "num-frames-received.path_response") \
234     func(num_frames_received.transport_close, "num-frames-received.transport_close") \
235     func(num_frames_received.application_close, "num-frames-received.application_close") \
236     func(num_frames_received.handshake_done, "num-frames-received.handshake_done") \
237     func(num_frames_received.datagram, "num-frames-received.datagram") \
238     func(num_frames_received.ack_frequency, "num-frames-received.ack_frequency") \
239     func(num_ptos, "num-ptos")
240 /* clang-format on */
241 
242 struct st_h2o_quic_ctx_t {
243     /**
244      * the event loop
245      */
246     h2o_loop_t *loop;
247     /**
248      * underlying unbound socket
249      */
250     struct {
251         h2o_socket_t *sock;
252         struct sockaddr_storage addr;
253         socklen_t addrlen;
254         in_port_t *port; /* points to the port number in addr */
255     } sock;
256     /**
257      * quic context
258      */
259     quicly_context_t *quic;
260     /**
261      *
262      */
263     quicly_cid_plaintext_t next_cid;
264     /**
265      * hashmap of connections by quicly_cid_plaintext_t::master_id.
266      */
267     struct kh_h2o_quic_idmap_s *conns_by_id;
268     /**
269      * hashmap of connections being accepted. Keyed by 4-tuple. Exists to handle packets that do not use the server-generated CIDs.
270      */
271     struct kh_h2o_quic_acceptmap_s *conns_accepting;
272     /**
273      * callback to receive connection status changes (optional)
274      */
275     h2o_quic_notify_connection_update_cb notify_conn_update;
276     /**
277      * callback to accept new connections (optional)
278      */
279     h2o_quic_accept_cb acceptor;
280     /**
281      * 0 to disable load distribution of accepting connections by h2o (i.e. relies on the kernel's distribution based on 4-tuple)
282      */
283     uint32_t accept_thread_divisor;
284     /**
285      * callback to forward packets (optional)
286      */
287     h2o_quic_forward_packets_cb forward_packets;
288     /**
289      * TTL of a QUIC datagram. Used to prevent infinite forwarding of QUIC packets between nodes / threads.
290      */
291     uint8_t default_ttl;
292     /**
293      * boolean to indicate whether to use UDP GSO
294      */
295     uint8_t use_gso;
296     /**
297      * preprocessor that rewrites a forwarded datagram (optional)
298      */
299     h2o_quic_preprocess_packet_cb preprocess_packet;
300     /**
301      * quic stats
302      */
303     h2o_quic_stats_t *quic_stats;
304 };
305 
306 typedef struct st_h2o_quic_conn_callbacks_t {
307     void (*destroy_connection)(h2o_quic_conn_t *conn);
308 } h2o_quic_conn_callbacks_t;
309 
310 /**
311  * states of an HTTP/3 connection (not stream)
312  * mainly to see if a new request can be accepted
313  */
314 typedef enum enum_h2o_http3_conn_state_t {
315     H2O_HTTP3_CONN_STATE_OPEN,        /* accepting new connections */
316     H2O_HTTP3_CONN_STATE_HALF_CLOSED, /* no more accepting new streams */
317     H2O_HTTP3_CONN_STATE_IS_CLOSING   /* nothing should be sent */
318 } h2o_http3_conn_state_t;
319 
320 struct st_h2o_quic_conn_t {
321     /**
322      * context
323      */
324     h2o_quic_ctx_t *ctx;
325     /**
326      * underlying QUIC connection
327      */
328     quicly_conn_t *quic;
329     /**
330      * callbacks
331      */
332     const h2o_quic_conn_callbacks_t *callbacks;
333     /**
334      * the "transport" timer. Applications must have separate timer.
335      */
336     h2o_timer_t _timeout;
337     /**
338      *
339      */
340     uint64_t _accept_hashkey;
341 };
342 
343 typedef struct st_h2o_http3_qpack_context_t {
344     /**
345      * Our preferred table capacity for the encoder. The value actually used is MIN(this_value,
346      * peer_settings.encoder_table_capacity).
347      */
348     uint32_t encoder_table_capacity;
349 } h2o_http3_qpack_context_t;
350 
351 typedef struct st_h2o_http3_conn_callbacks_t {
352     h2o_quic_conn_callbacks_t super;
353     void (*handle_control_stream_frame)(h2o_http3_conn_t *conn, uint8_t type, const uint8_t *payload, size_t len);
354 } h2o_http3_conn_callbacks_t;
355 
356 struct st_h2o_http3_conn_t {
357     /**
358      *
359      */
360     h2o_quic_conn_t super;
361     /**
362      * connection state
363      */
364     h2o_http3_conn_state_t state;
365     /**
366      * QPACK states
367      */
368     struct {
369         const h2o_http3_qpack_context_t *ctx;
370         h2o_qpack_encoder_t *enc;
371         h2o_qpack_decoder_t *dec;
372     } qpack;
373     /**
374      *
375      */
376     struct {
377         uint64_t max_field_section_size;
378         unsigned h3_datagram : 1;
379     } peer_settings;
380     struct {
381         struct {
382             struct st_h2o_http3_ingress_unistream_t *control;
383             struct st_h2o_http3_ingress_unistream_t *qpack_encoder;
384             struct st_h2o_http3_ingress_unistream_t *qpack_decoder;
385         } ingress;
386         struct {
387             struct st_h2o_http3_egress_unistream_t *control;
388             struct st_h2o_http3_egress_unistream_t *qpack_encoder;
389             struct st_h2o_http3_egress_unistream_t *qpack_decoder;
390         } egress;
391     } _control_streams;
392 };
393 
394 #define H2O_HTTP3_CHECK_SUCCESS(expr)                                                                                              \
395     do {                                                                                                                           \
396         if (!(expr))                                                                                                               \
397             h2o_fatal(H2O_TO_STR(expr));                                                                                           \
398     } while (0)
399 
400 typedef struct st_h2o_http3_read_frame_t {
401     uint64_t type;
402     uint8_t _header_size;
403     const uint8_t *payload;
404     uint64_t length;
405 } h2o_http3_read_frame_t;
406 
407 extern const ptls_iovec_t h2o_http3_alpn[3];
408 
409 /**
410  * Sends UDP datagrams from specified source address to the specified destination. The returned value is a boolean indicating if the
411  * connection is still maintainable (false is returned when not being able to send a packet from the designated source address).
412  * When more than one datagram is provided, the size of all the datagrams must be the same except for the last datagram, so that
413  * the datagrams can be sent using GSO.
414  */
415 int h2o_quic_send_datagrams(h2o_quic_ctx_t *ctx, quicly_address_t *dest, quicly_address_t *src, struct iovec *datagrams,
416                             size_t num_datagrams);
417 /**
418  * creates a unidirectional stream object
419  */
420 void h2o_http3_on_create_unidirectional_stream(quicly_stream_t *qs);
421 /**
422  * returns a frame header (if BODY frame) or an entire frame
423  */
424 int h2o_http3_read_frame(h2o_http3_read_frame_t *frame, int is_client, uint64_t stream_type, const uint8_t **src,
425                          const uint8_t *src_end, const char **err_desc);
426 
427 void h2o_quic_init_context(h2o_quic_ctx_t *ctx, h2o_loop_t *loop, h2o_socket_t *sock, quicly_context_t *quic,
428                            h2o_quic_accept_cb acceptor, h2o_quic_notify_connection_update_cb notify_conn_update, uint8_t use_gso,
429                            h2o_quic_stats_t *quic_stats);
430 /**
431  *
432  */
433 void h2o_quic_dispose_context(h2o_quic_ctx_t *ctx);
434 /**
435  *
436  */
437 void h2o_quic_set_context_identifier(h2o_quic_ctx_t *ctx, uint32_t accept_thread_divisor, uint32_t thread_id, uint64_t node_id,
438                                      uint8_t ttl, h2o_quic_forward_packets_cb forward_cb,
439                                      h2o_quic_preprocess_packet_cb preprocess_cb);
440 /**
441  *
442  */
443 void h2o_quic_read_socket(h2o_quic_ctx_t *ctx, h2o_socket_t *sock);
444 /**
445  *
446  */
447 void h2o_quic_close_connection(h2o_quic_conn_t *conn, int err, const char *reason_phrase);
448 /**
449  *
450  */
451 void h2o_quic_close_all_connections(h2o_quic_ctx_t *ctx);
452 /**
453  *
454  */
455 size_t h2o_quic_num_connections(h2o_quic_ctx_t *ctx);
456 /**
457  *
458  */
459 void h2o_quic_init_conn(h2o_quic_conn_t *conn, h2o_quic_ctx_t *ctx, const h2o_quic_conn_callbacks_t *callbacks);
460 /**
461  *
462  */
463 void h2o_quic_dispose_conn(h2o_quic_conn_t *conn);
464 /**
465  *
466  */
467 void h2o_quic_setup(h2o_quic_conn_t *conn, quicly_conn_t *quic);
468 /**
469  * initializes a http3 connection
470  */
471 void h2o_http3_init_conn(h2o_http3_conn_t *conn, h2o_quic_ctx_t *ctx, const h2o_http3_conn_callbacks_t *callbacks,
472                          const h2o_http3_qpack_context_t *qpack_ctx);
473 /**
474  *
475  */
476 void h2o_http3_dispose_conn(h2o_http3_conn_t *conn);
477 /**
478  *
479  */
480 int h2o_http3_setup(h2o_http3_conn_t *conn, quicly_conn_t *quic);
481 /**
482  * sends packets immediately by calling quicly_send, sendmsg (returns 1 if success, 0 if the connection was destroyed)
483  */
484 int h2o_quic_send(h2o_quic_conn_t *conn);
485 /**
486  * updates receive buffer
487  */
488 void h2o_http3_update_recvbuf(h2o_buffer_t **buf, size_t off, const void *src, size_t len);
489 /**
490  * Schedules the transport timer. Application must call this function when it writes data to the connection (TODO better way to
491  * handle this?). The function is automatically called when packets are sent or received.
492  */
493 void h2o_quic_schedule_timer(h2o_quic_conn_t *conn);
494 /**
495  *
496  */
497 int h2o_http3_handle_settings_frame(h2o_http3_conn_t *conn, const uint8_t *payload, size_t length, const char **err_desc);
498 /**
499  *
500  */
501 void h2o_http3_send_qpack_stream_cancel(h2o_http3_conn_t *conn, quicly_stream_id_t stream_id);
502 /**
503  *
504  */
505 void h2o_http3_send_qpack_header_ack(h2o_http3_conn_t *conn, const void *bytes, size_t len);
506 /**
507  * Enqueue GOAWAY frame for sending
508  */
509 void h2o_http3_send_goaway_frame(h2o_http3_conn_t *conn, uint64_t stream_or_push_id);
510 /**
511  *
512  */
513 static int h2o_http3_has_received_settings(h2o_http3_conn_t *conn);
514 /**
515  * Returns a boolean indicating if the use of H3_DATAGRAM frame has been negotiated
516  */
517 int h2o_http3_can_use_h3_datagram(h2o_http3_conn_t *conn);
518 /**
519  * sends out H3 datagrams
520  */
521 void h2o_http3_send_h3_datagrams(h2o_http3_conn_t *conn, uint64_t flow_id, h2o_iovec_t *datagrams, size_t num_datagrams);
522 /**
523  * Decodes an H3 datagram. Returns the flow id if successful, or UINT64_MAX if not.
524  */
525 uint64_t h2o_http3_decode_h3_datagram(h2o_iovec_t *payload, const void *_src, size_t len);
526 
527 /* inline definitions */
528 
h2o_http3_has_received_settings(h2o_http3_conn_t * conn)529 inline int h2o_http3_has_received_settings(h2o_http3_conn_t *conn)
530 {
531     return conn->qpack.enc != NULL;
532 }
533 
534 #endif
535