• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2018-2019, Cloudflare, Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 //       notice, this list of conditions and the following disclaimer.
10 //
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #ifndef QUICHE_H
28 #define QUICHE_H
29 
30 #if defined(__cplusplus)
31 extern "C" {
32 #endif
33 
34 #include <stdint.h>
35 #include <stdbool.h>
36 #include <stddef.h>
37 #ifdef __unix__
38 #include <sys/types.h>
39 #endif
40 #ifdef _MSC_VER
41 #include <BaseTsd.h>
42 #define ssize_t SSIZE_T
43 #endif
44 
45 // QUIC transport API.
46 //
47 
48 // The current QUIC wire version.
49 #define QUICHE_PROTOCOL_VERSION 0x00000001
50 
51 // The maximum length of a connection ID.
52 #define QUICHE_MAX_CONN_ID_LEN 20
53 
54 // The minimum length of Initial packets sent by a client.
55 #define QUICHE_MIN_CLIENT_INITIAL_LEN 1200
56 
57 enum quiche_error {
58     // There is no more work to do.
59     QUICHE_ERR_DONE = -1,
60 
61     // The provided buffer is too short.
62     QUICHE_ERR_BUFFER_TOO_SHORT = -2,
63 
64     // The provided packet cannot be parsed because its version is unknown.
65     QUICHE_ERR_UNKNOWN_VERSION = -3,
66 
67     // The provided packet cannot be parsed because it contains an invalid
68     // frame.
69     QUICHE_ERR_INVALID_FRAME = -4,
70 
71     // The provided packet cannot be parsed.
72     QUICHE_ERR_INVALID_PACKET = -5,
73 
74     // The operation cannot be completed because the connection is in an
75     // invalid state.
76     QUICHE_ERR_INVALID_STATE = -6,
77 
78     // The operation cannot be completed because the stream is in an
79     // invalid state.
80     QUICHE_ERR_INVALID_STREAM_STATE = -7,
81 
82     // The peer's transport params cannot be parsed.
83     QUICHE_ERR_INVALID_TRANSPORT_PARAM = -8,
84 
85     // A cryptographic operation failed.
86     QUICHE_ERR_CRYPTO_FAIL = -9,
87 
88     // The TLS handshake failed.
89     QUICHE_ERR_TLS_FAIL = -10,
90 
91     // The peer violated the local flow control limits.
92     QUICHE_ERR_FLOW_CONTROL = -11,
93 
94     // The peer violated the local stream limits.
95     QUICHE_ERR_STREAM_LIMIT = -12,
96 
97     // The specified stream was stopped by the peer.
98     QUICHE_ERR_STREAM_STOPPED = -15,
99 
100     // The received data exceeds the stream's final size.
101     QUICHE_ERR_FINAL_SIZE = -13,
102 
103     // Error in congestion control.
104     QUICHE_ERR_CONGESTION_CONTROL = -14,
105 };
106 
107 // Returns a human readable string with the quiche version number.
108 const char *quiche_version(void);
109 
110 // Enables logging. |cb| will be called with log messages
111 int quiche_enable_debug_logging(void (*cb)(const char *line, void *argp),
112                                 void *argp);
113 
114 // Stores configuration shared between multiple connections.
115 typedef struct Config quiche_config;
116 
117 // Creates a config object with the given version.
118 quiche_config *quiche_config_new(uint32_t version);
119 
120 // Configures the given certificate chain.
121 int quiche_config_load_cert_chain_from_pem_file(quiche_config *config,
122                                                 const char *path);
123 
124 // Configures the given private key.
125 int quiche_config_load_priv_key_from_pem_file(quiche_config *config,
126                                               const char *path);
127 
128 // Specifies a file where trusted CA certificates are stored for the purposes of certificate verification.
129 int quiche_config_load_verify_locations_from_file(quiche_config *config,
130                                                   const char *path);
131 
132 // Configures whether to verify the peer's certificate.
133 void quiche_config_verify_peer(quiche_config *config, bool v);
134 
135 // Configures whether to send GREASE.
136 void quiche_config_grease(quiche_config *config, bool v);
137 
138 // Enables logging of secrets.
139 void quiche_config_log_keys(quiche_config *config);
140 
141 // Enables sending or receiving early data.
142 void quiche_config_enable_early_data(quiche_config *config);
143 
144 // Configures the list of supported application protocols.
145 int quiche_config_set_application_protos(quiche_config *config,
146                                          const uint8_t *protos,
147                                          size_t protos_len);
148 
149 // Sets the `max_idle_timeout` transport parameter, in milliseconds, default is
150 // no timeout.
151 void quiche_config_set_max_idle_timeout(quiche_config *config, uint64_t v);
152 
153 // Sets the `max_udp_payload_size transport` parameter.
154 void quiche_config_set_max_recv_udp_payload_size(quiche_config *config, size_t v);
155 
156 // Sets the maximum outgoing UDP payload size.
157 void quiche_config_set_max_send_udp_payload_size(quiche_config *config, size_t v);
158 
159 // Sets the `initial_max_data` transport parameter.
160 void quiche_config_set_initial_max_data(quiche_config *config, uint64_t v);
161 
162 // Sets the `initial_max_stream_data_bidi_local` transport parameter.
163 void quiche_config_set_initial_max_stream_data_bidi_local(quiche_config *config, uint64_t v);
164 
165 // Sets the `initial_max_stream_data_bidi_remote` transport parameter.
166 void quiche_config_set_initial_max_stream_data_bidi_remote(quiche_config *config, uint64_t v);
167 
168 // Sets the `initial_max_stream_data_uni` transport parameter.
169 void quiche_config_set_initial_max_stream_data_uni(quiche_config *config, uint64_t v);
170 
171 // Sets the `initial_max_streams_bidi` transport parameter.
172 void quiche_config_set_initial_max_streams_bidi(quiche_config *config, uint64_t v);
173 
174 // Sets the `initial_max_streams_uni` transport parameter.
175 void quiche_config_set_initial_max_streams_uni(quiche_config *config, uint64_t v);
176 
177 // Sets the `ack_delay_exponent` transport parameter.
178 void quiche_config_set_ack_delay_exponent(quiche_config *config, uint64_t v);
179 
180 // Sets the `max_ack_delay` transport parameter.
181 void quiche_config_set_max_ack_delay(quiche_config *config, uint64_t v);
182 
183 // Sets the `disable_active_migration` transport parameter.
184 void quiche_config_set_disable_active_migration(quiche_config *config, bool v);
185 
186 enum quiche_cc_algorithm {
187     QUICHE_CC_RENO = 0,
188     QUICHE_CC_CUBIC = 1,
189 };
190 
191 // Sets the congestion control algorithm used.
192 void quiche_config_set_cc_algorithm(quiche_config *config, enum quiche_cc_algorithm algo);
193 
194 // Configures whether to use HyStart++.
195 void quiche_config_enable_hystart(quiche_config *config, bool v);
196 
197 // Configures whether to enable receiving DATAGRAM frames.
198 void quiche_config_enable_dgram(quiche_config *config, bool enabled,
199                                 size_t recv_queue_len,
200                                 size_t send_queue_len);
201 
202 // Frees the config object.
203 void quiche_config_free(quiche_config *config);
204 
205 // Extracts version, type, source / destination connection ID and address
206 // verification token from the packet in |buf|.
207 int quiche_header_info(const uint8_t *buf, size_t buf_len, size_t dcil,
208                        uint32_t *version, uint8_t *type,
209                        uint8_t *scid, size_t *scid_len,
210                        uint8_t *dcid, size_t *dcid_len,
211                        uint8_t *token, size_t *token_len);
212 
213 // A QUIC connection.
214 typedef struct Connection quiche_conn;
215 
216 // Creates a new server-side connection.
217 quiche_conn *quiche_accept(const uint8_t *scid, size_t scid_len,
218                            const uint8_t *odcid, size_t odcid_len,
219                            const struct sockaddr *from, size_t from_len,
220                            quiche_config *config);
221 
222 // Creates a new client-side connection.
223 quiche_conn *quiche_connect(const char *server_name,
224                             const uint8_t *scid, size_t scid_len,
225                             const struct sockaddr *to, size_t to_len,
226                             quiche_config *config);
227 
228 // Writes a version negotiation packet.
229 ssize_t quiche_negotiate_version(const uint8_t *scid, size_t scid_len,
230                                  const uint8_t *dcid, size_t dcid_len,
231                                  uint8_t *out, size_t out_len);
232 
233 // Writes a retry packet.
234 ssize_t quiche_retry(const uint8_t *scid, size_t scid_len,
235                      const uint8_t *dcid, size_t dcid_len,
236                      const uint8_t *new_scid, size_t new_scid_len,
237                      const uint8_t *token, size_t token_len,
238                      uint32_t version, uint8_t *out, size_t out_len);
239 
240 // Returns true if the given protocol version is supported.
241 bool quiche_version_is_supported(uint32_t version);
242 
243 quiche_conn *quiche_conn_new_with_tls(const uint8_t *scid, size_t scid_len,
244                                       const uint8_t *odcid, size_t odcid_len,
245                                       const struct sockaddr *peer, size_t peer_len,
246                                       quiche_config *config, void *ssl,
247                                       bool is_server);
248 
249 // Enables keylog to the specified file path. Returns true on success.
250 bool quiche_conn_set_keylog_path(quiche_conn *conn, const char *path);
251 
252 // Enables keylog to the specified file descriptor. Unix only.
253 void quiche_conn_set_keylog_fd(quiche_conn *conn, int fd);
254 
255 // Enables qlog to the specified file path. Returns true on success.
256 bool quiche_conn_set_qlog_path(quiche_conn *conn, const char *path,
257                           const char *log_title, const char *log_desc);
258 
259 // Enables qlog to the specified file descriptor. Unix only.
260 void quiche_conn_set_qlog_fd(quiche_conn *conn, int fd, const char *log_title,
261                              const char *log_desc);
262 
263 // Configures the given session for resumption.
264 int quiche_conn_set_session(quiche_conn *conn, const uint8_t *buf, size_t buf_len);
265 
266 typedef struct {
267     struct sockaddr *from;
268     socklen_t from_len;
269 } quiche_recv_info;
270 
271 // Processes QUIC packets received from the peer.
272 ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len,
273                          const quiche_recv_info *info);
274 
275 typedef struct {
276     // The address the packet should be sent to.
277     struct sockaddr_storage to;
278     socklen_t to_len;
279 
280     // The time to send the packet out.
281     struct timespec at;
282 } quiche_send_info;
283 
284 // Writes a single QUIC packet to be sent to the peer.
285 ssize_t quiche_conn_send(quiche_conn *conn, uint8_t *out, size_t out_len,
286                          quiche_send_info *out_info);
287 
288 // Reads contiguous data from a stream.
289 ssize_t quiche_conn_stream_recv(quiche_conn *conn, uint64_t stream_id,
290                                 uint8_t *out, size_t buf_len, bool *fin);
291 
292 // Writes data to a stream.
293 ssize_t quiche_conn_stream_send(quiche_conn *conn, uint64_t stream_id,
294                                 const uint8_t *buf, size_t buf_len, bool fin);
295 
296 enum quiche_shutdown {
297     QUICHE_SHUTDOWN_READ = 0,
298     QUICHE_SHUTDOWN_WRITE = 1,
299 };
300 
301 // Sets the priority for a stream.
302 int quiche_conn_stream_priority(quiche_conn *conn, uint64_t stream_id,
303                                 uint8_t urgency, bool incremental);
304 
305 // Shuts down reading or writing from/to the specified stream.
306 int quiche_conn_stream_shutdown(quiche_conn *conn, uint64_t stream_id,
307                                 enum quiche_shutdown direction, uint64_t err);
308 
309 ssize_t quiche_conn_stream_capacity(quiche_conn *conn, uint64_t stream_id);
310 
311 bool quiche_conn_stream_readable(quiche_conn *conn, uint64_t stream_id);
312 
313 // Returns true if all the data has been read from the specified stream.
314 bool quiche_conn_stream_finished(quiche_conn *conn, uint64_t stream_id);
315 
316 typedef struct StreamIter quiche_stream_iter;
317 
318 // Returns an iterator over streams that have outstanding data to read.
319 quiche_stream_iter *quiche_conn_readable(quiche_conn *conn);
320 
321 // Returns an iterator over streams that can be written to.
322 quiche_stream_iter *quiche_conn_writable(quiche_conn *conn);
323 
324 // Returns the maximum possible size of egress UDP payloads.
325 size_t quiche_conn_max_send_udp_payload_size(quiche_conn *conn);
326 
327 // Returns the amount of time until the next timeout event, in nanoseconds.
328 uint64_t quiche_conn_timeout_as_nanos(quiche_conn *conn);
329 
330 // Returns the amount of time until the next timeout event, in milliseconds.
331 uint64_t quiche_conn_timeout_as_millis(quiche_conn *conn);
332 
333 // Processes a timeout event.
334 void quiche_conn_on_timeout(quiche_conn *conn);
335 
336 // Closes the connection with the given error and reason.
337 int quiche_conn_close(quiche_conn *conn, bool app, uint64_t err,
338                       const uint8_t *reason, size_t reason_len);
339 
340 // Returns a string uniquely representing the connection.
341 void quiche_conn_trace_id(quiche_conn *conn, const uint8_t **out, size_t *out_len);
342 
343 // Returns the source connection ID.
344 void quiche_conn_source_id(quiche_conn *conn, const uint8_t **out, size_t *out_len);
345 
346 // Returns the destination connection ID.
347 void quiche_conn_destination_id(quiche_conn *conn, const uint8_t **out, size_t *out_len);
348 
349 // Returns the negotiated ALPN protocol.
350 void quiche_conn_application_proto(quiche_conn *conn, const uint8_t **out,
351                                    size_t *out_len);
352 
353 // Returns the serialized cryptographic session for the connection.
354 void quiche_conn_session(quiche_conn *conn, const uint8_t **out, size_t *out_len);
355 
356 // Returns true if the connection handshake is complete.
357 bool quiche_conn_is_established(quiche_conn *conn);
358 
359 // Returns true if the connection has a pending handshake that has progressed
360 // enough to send or receive early data.
361 bool quiche_conn_is_in_early_data(quiche_conn *conn);
362 
363 // Returns whether there is stream or DATAGRAM data available to read.
364 bool quiche_conn_is_readable(quiche_conn *conn);
365 
366 // Returns true if the connection is draining.
367 bool quiche_conn_is_draining(quiche_conn *conn);
368 
369 // Returns the number of bidirectional streams that can be created
370 // before the peer's stream count limit is reached.
371 uint64_t quiche_conn_peer_streams_left_bidi(quiche_conn *conn);
372 
373 // Returns the number of unidirectional streams that can be created
374 // before the peer's stream count limit is reached.
375 uint64_t quiche_conn_peer_streams_left_uni(quiche_conn *conn);
376 
377 // Returns true if the connection is closed.
378 bool quiche_conn_is_closed(quiche_conn *conn);
379 
380 // Returns true if a connection error was received, and updates the provided
381 // parameters accordingly.
382 bool quiche_conn_peer_error(quiche_conn *conn,
383                             bool *is_app,
384                             uint64_t *error_code,
385                             const uint8_t **reason,
386                             size_t *reason_len);
387 
388 // Initializes the stream's application data.
389 //
390 // Stream data can only be initialized once. Additional calls to this method
391 // will fail.
392 //
393 // Note that the application is responsible for freeing the data.
394 int quiche_conn_stream_init_application_data(quiche_conn *conn,
395                                              uint64_t stream_id,
396                                              void *data);
397 
398 // Returns the stream's application data, if any was initialized.
399 void *quiche_conn_stream_application_data(quiche_conn *conn, uint64_t stream_id);
400 
401 // Fetches the next stream from the given iterator. Returns false if there are
402 // no more elements in the iterator.
403 bool quiche_stream_iter_next(quiche_stream_iter *iter, uint64_t *stream_id);
404 
405 // Frees the given stream iterator object.
406 void quiche_stream_iter_free(quiche_stream_iter *iter);
407 
408 typedef struct {
409     // The number of QUIC packets received on this connection.
410     size_t recv;
411 
412     // The number of QUIC packets sent on this connection.
413     size_t sent;
414 
415     // The number of QUIC packets that were lost.
416     size_t lost;
417 
418     // The estimated round-trip time of the connection (in nanoseconds).
419     uint64_t rtt;
420 
421     // The size of the connection's congestion window in bytes.
422     size_t cwnd;
423 
424     // The estimated data delivery rate in bytes/s.
425     uint64_t delivery_rate;
426 } quiche_stats;
427 
428 // Collects and returns statistics about the connection.
429 void quiche_conn_stats(quiche_conn *conn, quiche_stats *out);
430 
431 // Returns the maximum DATAGRAM payload that can be sent.
432 ssize_t quiche_conn_dgram_max_writable_len(quiche_conn *conn);
433 
434 // Returns the length of the first stored DATAGRAM.
435 ssize_t quiche_conn_dgram_recv_front_len(quiche_conn *conn);
436 
437 // Returns the number of items in the DATAGRAM receive queue.
438 ssize_t quiche_conn_dgram_recv_queue_len(quiche_conn *conn);
439 
440 ///Returns the total size of all items in the DATAGRAM receive queue.
441 ssize_t quiche_conn_dgram_recv_queue_byte_size(quiche_conn *conn);
442 
443 // Returns the number of items in the DATAGRAM send queue.
444 ssize_t quiche_conn_dgram_send_queue_len(quiche_conn *conn);
445 
446 // Returns the total size of all items in the DATAGRAM send queue.
447 ssize_t quiche_conn_dgram_send_queue_byte_size(quiche_conn *conn);
448 
449 // Reads the first received DATAGRAM.
450 ssize_t quiche_conn_dgram_recv(quiche_conn *conn, uint8_t *buf,
451                                size_t buf_len);
452 
453 // Sends data in a DATAGRAM frame.
454 ssize_t quiche_conn_dgram_send(quiche_conn *conn, const uint8_t *buf,
455                                size_t buf_len);
456 
457 // Purges queued outgoing DATAGRAMs matching the predicate.
458 void quiche_conn_dgram_purge_outgoing(quiche_conn *conn,
459                                       bool (*f)(uint8_t *, size_t));
460 
461 // Frees the connection object.
462 void quiche_conn_free(quiche_conn *conn);
463 
464 
465 // HTTP/3 API
466 //
467 
468 // List of ALPN tokens of supported HTTP/3 versions.
469 #define QUICHE_H3_APPLICATION_PROTOCOL "\x02h3\x05h3-29\x05h3-28\x05h3-27"
470 
471 enum quiche_h3_error {
472     /// There is no error or no work to do
473     QUICHE_H3_ERR_DONE = -1,
474 
475     /// The provided buffer is too short.
476     QUICHE_H3_ERR_BUFFER_TOO_SHORT = -2,
477 
478     /// Internal error in the HTTP/3 stack.
479     QUICHE_H3_ERR_INTERNAL_ERROR = -3,
480 
481     /// Endpoint detected that the peer is exhibiting behavior that causes.
482     /// excessive load.
483     QUICHE_H3_ERR_EXCESSIVE_LOAD = -4,
484 
485     /// Stream ID or Push ID greater that current maximum was
486     /// used incorrectly, such as exceeding a limit, reducing a limit,
487     /// or being reused.
488     QUICHE_H3_ERR_ID_ERROR= -5,
489 
490     /// The endpoint detected that its peer created a stream that it will not
491     /// accept.
492     QUICHE_H3_ERR_STREAM_CREATION_ERROR = -6,
493 
494     /// A required critical stream was closed.
495     QUICHE_H3_ERR_CLOSED_CRITICAL_STREAM = -7,
496 
497     /// No SETTINGS frame at beginning of control stream.
498     QUICHE_H3_ERR_MISSING_SETTINGS = -8,
499 
500     /// A frame was received which is not permitted in the current state.
501     QUICHE_H3_ERR_FRAME_UNEXPECTED = -9,
502 
503     /// Frame violated layout or size rules.
504     QUICHE_H3_ERR_FRAME_ERROR = -10,
505 
506     /// QPACK Header block decompression failure.
507     QUICHE_H3_ERR_QPACK_DECOMPRESSION_FAILED = -11,
508 
509     /// Error originated from the transport layer.
510     QUICHE_H3_ERR_TRANSPORT_ERROR = -12,
511 
512     /// The underlying QUIC stream (or connection) doesn't have enough capacity
513     /// for the operation to complete. The application should retry later on.
514     QUICHE_H3_ERR_STREAM_BLOCKED = -13,
515 
516     /// Error in the payload of a SETTINGS frame.
517     QUICHE_H3_ERR_SETTINGS_ERROR = -14,
518 
519     /// Server rejected request.
520     QUICHE_H3_ERR_REQUEST_REJECTED = -15,
521 
522     /// Request or its response cancelled.
523     QUICHE_H3_ERR_REQUEST_CANCELLED = -16,
524 
525     /// Client's request stream terminated without containing a full-formed
526     /// request.
527     QUICHE_H3_ERR_REQUEST_INCOMPLETE = -17,
528 
529     /// An HTTP message was malformed and cannot be processed.
530     QUICHE_H3_ERR_MESSAGE_ERROR = -18,
531 
532     // The TCP connection established in response to a CONNECT request was
533     /// reset or abnormally closed.
534     QUICHE_H3_ERR_CONNECT_ERROR = -19,
535 
536     /// The requested operation cannot be served over HTTP/3. Peer should retry
537     /// over HTTP/1.1.
538     QUICHE_H3_ERR_VERSION_FALLBACK = -20,
539 };
540 
541 // Stores configuration shared between multiple connections.
542 typedef struct Http3Config quiche_h3_config;
543 
544 // Creates an HTTP/3 config object with default settings values.
545 quiche_h3_config *quiche_h3_config_new(void);
546 
547 // Sets the `SETTINGS_MAX_HEADER_LIST_SIZE` setting.
548 void quiche_h3_config_set_max_header_list_size(quiche_h3_config *config, uint64_t v);
549 
550 // Sets the `SETTINGS_QPACK_MAX_TABLE_CAPACITY` setting.
551 void quiche_h3_config_set_qpack_max_table_capacity(quiche_h3_config *config, uint64_t v);
552 
553 // Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` setting.
554 void quiche_h3_config_set_qpack_blocked_streams(quiche_h3_config *config, uint64_t v);
555 
556 // Frees the HTTP/3 config object.
557 void quiche_h3_config_free(quiche_h3_config *config);
558 
559 // A QUIC connection.
560 typedef struct Http3Connection quiche_h3_conn;
561 
562 // Creates a new server-side connection.
563 quiche_h3_conn *quiche_h3_accept(quiche_conn *quiche_conn,
564                                  quiche_h3_config *config);
565 
566 // Creates a new HTTP/3 connection using the provided QUIC connection.
567 quiche_h3_conn *quiche_h3_conn_new_with_transport(quiche_conn *quiche_conn,
568                                                   quiche_h3_config *config);
569 
570 enum quiche_h3_event_type {
571     QUICHE_H3_EVENT_HEADERS,
572     QUICHE_H3_EVENT_DATA,
573     QUICHE_H3_EVENT_FINISHED,
574     QUICHE_H3_EVENT_DATAGRAM,
575     QUICHE_H3_EVENT_GOAWAY,
576 };
577 
578 typedef struct Http3Event quiche_h3_event;
579 
580 // Processes HTTP/3 data received from the peer.
581 int64_t quiche_h3_conn_poll(quiche_h3_conn *conn, quiche_conn *quic_conn,
582                             quiche_h3_event **ev);
583 
584 // Returns the type of the event.
585 enum quiche_h3_event_type quiche_h3_event_type(quiche_h3_event *ev);
586 
587 // Iterates over the headers in the event.
588 //
589 // The `cb` callback will be called for each header in `ev`. `cb` should check
590 // the validity of pseudo-headers and headers. If `cb` returns any value other
591 // than `0`, processing will be interrupted and the value is returned to the
592 // caller.
593 int quiche_h3_event_for_each_header(quiche_h3_event *ev,
594                                     int (*cb)(uint8_t *name, size_t name_len,
595                                               uint8_t *value, size_t value_len,
596                                               void *argp),
597                                     void *argp);
598 
599 // Check whether data will follow the headers on the stream.
600 bool quiche_h3_event_headers_has_body(quiche_h3_event *ev);
601 
602 // Frees the HTTP/3 event object.
603 void quiche_h3_event_free(quiche_h3_event *ev);
604 
605 typedef struct {
606     const uint8_t *name;
607     size_t name_len;
608 
609     const uint8_t *value;
610     size_t value_len;
611 } quiche_h3_header;
612 
613 // Sends an HTTP/3 request.
614 int64_t quiche_h3_send_request(quiche_h3_conn *conn, quiche_conn *quic_conn,
615                                quiche_h3_header *headers, size_t headers_len,
616                                bool fin);
617 
618 // Sends an HTTP/3 response on the specified stream with default priority.
619 int quiche_h3_send_response(quiche_h3_conn *conn, quiche_conn *quic_conn,
620                             uint64_t stream_id, quiche_h3_header *headers,
621                             size_t headers_len, bool fin);
622 
623 // Sends an HTTP/3 response on the specified stream with specified priority.
624 int quiche_h3_send_response_with_priority(quiche_h3_conn *conn,
625                             quiche_conn *quic_conn, uint64_t stream_id,
626                             quiche_h3_header *headers, size_t headers_len,
627                             const char *priority, bool fin);
628 
629 // Sends an HTTP/3 body chunk on the given stream.
630 ssize_t quiche_h3_send_body(quiche_h3_conn *conn, quiche_conn *quic_conn,
631                             uint64_t stream_id, uint8_t *body, size_t body_len,
632                             bool fin);
633 
634 // Reads request or response body data into the provided buffer.
635 ssize_t quiche_h3_recv_body(quiche_h3_conn *conn, quiche_conn *quic_conn,
636                             uint64_t stream_id, uint8_t *out, size_t out_len);
637 
638 // Returns whether the peer enabled HTTP/3 DATAGRAM frame support.
639 bool quiche_h3_dgram_enabled_by_peer(quiche_h3_conn *conn,
640                                      quiche_conn *quic_conn);
641 
642 // Writes data to the DATAGRAM send queue.
643 ssize_t quiche_h3_send_dgram(quiche_h3_conn *conn, quiche_conn *quic_conn,
644                             uint64_t flow_id, uint8_t *data, size_t data_len);
645 
646 // Reads data from the DATAGRAM receive queue.
647 ssize_t quiche_h3_recv_dgram(quiche_h3_conn *conn, quiche_conn *quic_conn,
648                             uint64_t *flow_id, size_t *flow_id_len,
649                             uint8_t *out, size_t out_len);
650 
651 // Frees the HTTP/3 connection object.
652 void quiche_h3_conn_free(quiche_h3_conn *conn);
653 
654 #if defined(__cplusplus)
655 }  // extern C
656 #endif
657 
658 #endif // QUICHE_H
659