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