1 /*
2 * Copyright (c) 2017 Fastly, Kazuho Oku
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 quicly_h
23 #define quicly_h
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 #include <netinet/in.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 #include "picotls.h"
36 #include "quicly/constants.h"
37 #include "quicly/frame.h"
38 #include "quicly/local_cid.h"
39 #include "quicly/linklist.h"
40 #include "quicly/loss.h"
41 #include "quicly/cc.h"
42 #include "quicly/rate.h"
43 #include "quicly/recvstate.h"
44 #include "quicly/sendstate.h"
45 #include "quicly/maxsender.h"
46 #include "quicly/cid.h"
47 #include "quicly/remote_cid.h"
48
49 /* invariants! */
50 #define QUICLY_LONG_HEADER_BIT 0x80
51 #define QUICLY_QUIC_BIT 0x40
52 #define QUICLY_KEY_PHASE_BIT 0x4
53 #define QUICLY_LONG_HEADER_RESERVED_BITS 0xc
54 #define QUICLY_SHORT_HEADER_RESERVED_BITS 0x18
55
56 #define QUICLY_PACKET_TYPE_INITIAL (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0)
57 #define QUICLY_PACKET_TYPE_0RTT (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0x10)
58 #define QUICLY_PACKET_TYPE_HANDSHAKE (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0x20)
59 #define QUICLY_PACKET_TYPE_RETRY (QUICLY_LONG_HEADER_BIT | QUICLY_QUIC_BIT | 0x30)
60 #define QUICLY_PACKET_TYPE_BITMASK 0xf0
61
62 #define QUICLY_PACKET_IS_LONG_HEADER(first_byte) (((first_byte)&QUICLY_LONG_HEADER_BIT) != 0)
63
64 /**
65 * Version 1.
66 */
67 #define QUICLY_PROTOCOL_VERSION_1 0x1
68 /**
69 * The current version being supported. At the moment, it is draft-29.
70 */
71 #define QUICLY_PROTOCOL_VERSION_DRAFT29 0xff00001d
72 /**
73 * Draft-27 is also supported.
74 */
75 #define QUICLY_PROTOCOL_VERSION_DRAFT27 0xff00001b
76
77 #define QUICLY_PACKET_IS_INITIAL(first_byte) (((first_byte)&0xf0) == 0xc0)
78
79 #define QUICLY_STATELESS_RESET_PACKET_MIN_LEN 39
80
81 #define QUICLY_MAX_PN_SIZE 4 /* maximum defined by the RFC used for calculating header protection sampling offset */
82 #define QUICLY_SEND_PN_SIZE 2 /* size of PN used for sending */
83
84 #define QUICLY_AEAD_BASE_LABEL "tls13 quic "
85
86 typedef union st_quicly_address_t {
87 struct sockaddr sa;
88 struct sockaddr_in sin;
89 struct sockaddr_in6 sin6;
90 } quicly_address_t;
91
92 typedef struct st_quicly_context_t quicly_context_t;
93 typedef struct st_quicly_stream_t quicly_stream_t;
94 typedef struct st_quicly_send_context_t quicly_send_context_t;
95 typedef struct st_quicly_address_token_plaintext_t quicly_address_token_plaintext_t;
96
97 #define QUICLY_CALLBACK_TYPE0(ret, name) \
98 typedef struct st_quicly_##name##_t { \
99 ret (*cb)(struct st_quicly_##name##_t * self); \
100 } quicly_##name##_t
101
102 #define QUICLY_CALLBACK_TYPE(ret, name, ...) \
103 typedef struct st_quicly_##name##_t { \
104 ret (*cb)(struct st_quicly_##name##_t * self, __VA_ARGS__); \
105 } quicly_##name##_t
106
107 /**
108 * stream scheduler
109 */
110 typedef struct st_quicly_stream_scheduler_t {
111 /**
112 * returns if there's any data to send.
113 * @param conn_is_flow_capped if the connection-level flow control window is currently saturated
114 */
115 int (*can_send)(struct st_quicly_stream_scheduler_t *sched, quicly_conn_t *conn, int conn_is_saturated);
116 /**
117 * Called by quicly to emit stream data. The scheduler should repeatedly choose a stream and call `quicly_send_stream` until
118 * `quicly_can_send_stream` returns false.
119 */
120 int (*do_send)(struct st_quicly_stream_scheduler_t *sched, quicly_conn_t *conn, quicly_send_context_t *s);
121 /**
122 *
123 */
124 int (*update_state)(struct st_quicly_stream_scheduler_t *sched, quicly_stream_t *stream);
125 } quicly_stream_scheduler_t;
126
127 /**
128 * called when stream is being open. Application is expected to create it's corresponding state and tie it to stream->data.
129 */
130 QUICLY_CALLBACK_TYPE(int, stream_open, quicly_stream_t *stream);
131 /**
132 *
133 */
134 QUICLY_CALLBACK_TYPE(void, receive_datagram_frame, quicly_conn_t *conn, ptls_iovec_t payload);
135 /**
136 * called when the connection is closed by remote peer
137 */
138 QUICLY_CALLBACK_TYPE(void, closed_by_remote, quicly_conn_t *conn, int err, uint64_t frame_type, const char *reason,
139 size_t reason_len);
140 /**
141 * Returns current time in milliseconds. The returned value MUST monotonically increase (i.e., it is the responsibility of the
142 * callback implementation to guarantee that the returned value never goes back to the past).
143 */
144 QUICLY_CALLBACK_TYPE0(int64_t, now);
145 /**
146 * called when a NEW_TOKEN token is received on a connection
147 */
148 QUICLY_CALLBACK_TYPE(int, save_resumption_token, quicly_conn_t *conn, ptls_iovec_t token);
149 /**
150 *
151 */
152 QUICLY_CALLBACK_TYPE(int, generate_resumption_token, quicly_conn_t *conn, ptls_buffer_t *buf,
153 quicly_address_token_plaintext_t *token);
154 /**
155 * called to initialize a congestion controller for a new connection.
156 * should in turn call one of the quicly_cc_*_init functions from cc.h with customized parameters.
157 */
158 QUICLY_CALLBACK_TYPE(void, init_cc, quicly_cc_t *cc, uint32_t initcwnd, int64_t now);
159 /**
160 * reference counting.
161 * delta must be either 1 or -1.
162 */
163 QUICLY_CALLBACK_TYPE(void, update_open_count, ssize_t delta);
164
165 /**
166 * crypto offload API
167 */
168 typedef struct st_quicly_crypto_engine_t {
169 /**
170 * Callback used for setting up the header protection keys / packet protection keys. The callback MUST initialize or replace
171 * `header_protect_ctx` and `packet_protect_ctx` as specified by QUIC-TLS. This callback might be called more than once for
172 * 1-RTT epoch, when the key is updated. In such case, there is no need to update the header protection context, and therefore
173 * `header_protect_ctx` will be NULL.
174 *
175 * @param header_protect_ctx address of where the header protection context should be written. Might be NULL when called to
176 * handle 1-RTT Key Update.
177 * @param packet_protect_ctx address of where the packet protection context should be written.
178 * @param secret the secret from which the protection keys is derived. The length of the secret is
179 `hash->digest_size`.
180 * @note At the moment, the callback is not invoked for Initial keys when running as server.
181 */
182 int (*setup_cipher)(struct st_quicly_crypto_engine_t *engine, quicly_conn_t *conn, size_t epoch, int is_enc,
183 ptls_cipher_context_t **header_protect_ctx, ptls_aead_context_t **packet_protect_ctx,
184 ptls_aead_algorithm_t *aead, ptls_hash_algorithm_t *hash, const void *secret);
185 /**
186 * Callback used for encrypting the send packet. The engine must AEAD-encrypt the payload using `packet_protect_ctx` and apply
187 * header protection using `header_protect_ctx`. Quicly does not read or write the content of the UDP datagram payload after
188 * this function is called. Therefore, an engine might retain the information provided by this function, and protect the packet
189 * and the header at a later moment (e.g., hardware crypto offload).
190 */
191 void (*encrypt_packet)(struct st_quicly_crypto_engine_t *engine, quicly_conn_t *conn, ptls_cipher_context_t *header_protect_ctx,
192 ptls_aead_context_t *packet_protect_ctx, ptls_iovec_t datagram, size_t first_byte_at,
193 size_t payload_from, uint64_t packet_number, int coalesced);
194 } quicly_crypto_engine_t;
195
196 /**
197 * data structure used for self-tracing
198 */
199 typedef struct st_quicly_tracer_t {
200 /**
201 * NULL when not used
202 */
203 void (*cb)(void *ctx, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
204 /**
205 *
206 */
207 void *ctx;
208 } quicly_tracer_t;
209
210 typedef struct st_quicly_max_stream_data_t {
211 uint64_t bidi_local, bidi_remote, uni;
212 } quicly_max_stream_data_t;
213
214 /**
215 * Transport Parameters; the struct contains "configuration parameters", ODCID is managed separately
216 */
217 typedef struct st_quicly_transport_parameters_t {
218 /**
219 * in octets
220 */
221 quicly_max_stream_data_t max_stream_data;
222 /**
223 * in octets
224 */
225 uint64_t max_data;
226 /**
227 * in milliseconds
228 */
229 uint64_t max_idle_timeout;
230 /**
231 *
232 */
233 uint64_t max_streams_bidi;
234 /**
235 *
236 */
237 uint64_t max_streams_uni;
238 /**
239 *
240 */
241 uint64_t max_udp_payload_size;
242 /**
243 * quicly ignores the value set for quicly_context_t::transport_parameters
244 */
245 uint8_t ack_delay_exponent;
246 /**
247 * in milliseconds; quicly ignores the value set for quicly_context_t::transport_parameters
248 */
249 uint16_t max_ack_delay;
250 /**
251 * Delayed-ack extension. UINT64_MAX indicates that the extension is disabled or that the peer does not support it. Any local
252 * value other than UINT64_MAX indicates that the use of the extension should be negotiated.
253 */
254 uint64_t min_ack_delay_usec;
255 /**
256 *
257 */
258 uint8_t disable_active_migration : 1;
259 /**
260 *
261 */
262 uint64_t active_connection_id_limit;
263 /**
264 *
265 */
266 uint16_t max_datagram_frame_size;
267 } quicly_transport_parameters_t;
268
269 struct st_quicly_context_t {
270 /**
271 * tls context to use
272 */
273 ptls_context_t *tls;
274 /**
275 * Maximum size of packets that we are willing to send when path-specific information is unavailable. As a path-specific
276 * optimization, quicly acting as a server expands this value to `min(local.tp.max_udp_payload_size,
277 * remote.tp.max_udp_payload_size, max_size_of_incoming_datagrams)` when it receives the Transport Parameters from the client.
278 */
279 uint16_t initial_egress_max_udp_payload_size;
280 /**
281 * loss detection parameters
282 */
283 quicly_loss_conf_t loss;
284 /**
285 * transport parameters
286 */
287 quicly_transport_parameters_t transport_params;
288 /**
289 * number of packets that can be sent without a key update
290 */
291 uint64_t max_packets_per_key;
292 /**
293 * maximum number of bytes that can be transmitted on a CRYPTO stream (per each epoch)
294 */
295 uint64_t max_crypto_bytes;
296 /**
297 * initial CWND in terms of packet numbers
298 */
299 uint32_t initcwnd_packets;
300 /**
301 * (client-only) Initial QUIC protocol version used by the client. Setting this to a greased version will enforce version
302 * negotiation.
303 */
304 uint32_t initial_version;
305 /**
306 * (server-only) amplification limit before the peer address is validated
307 */
308 uint16_t pre_validation_amplification_limit;
309 /**
310 * How frequent the endpoint should induce ACKs from the peer, relative to RTT (or CWND) multiplied by 1024. As an example, 128
311 * will request the peer to send one ACK every 1/8 RTT (or CWND). 0 disables the use of the delayed-ack extension.
312 */
313 uint16_t ack_frequency;
314 /**
315 * expand client hello so that it does not fit into one datagram
316 */
317 unsigned expand_client_hello : 1;
318 /**
319 *
320 */
321 quicly_cid_encryptor_t *cid_encryptor;
322 /**
323 * callback called when a new stream is opened by remote peer
324 */
325 quicly_stream_open_t *stream_open;
326 /**
327 * callbacks for scheduling stream data
328 */
329 quicly_stream_scheduler_t *stream_scheduler;
330 /**
331 * callback for receiving datagram frame
332 */
333 quicly_receive_datagram_frame_t *receive_datagram_frame;
334 /**
335 * callback called when a connection is closed by remote peer
336 */
337 quicly_closed_by_remote_t *closed_by_remote;
338 /**
339 * returns current time in milliseconds
340 */
341 quicly_now_t *now;
342 /**
343 * called wen a NEW_TOKEN token is being received
344 */
345 quicly_save_resumption_token_t *save_resumption_token;
346 /**
347 *
348 */
349 quicly_generate_resumption_token_t *generate_resumption_token;
350 /**
351 * crypto engine (offload API)
352 */
353 quicly_crypto_engine_t *crypto_engine;
354 /**
355 * initializes a congestion controller for given connection.
356 */
357 quicly_init_cc_t *init_cc;
358 /**
359 * optional refcount callback
360 */
361 quicly_update_open_count_t *update_open_count;
362 };
363
364 /**
365 * connection state
366 */
367 typedef enum {
368 /**
369 * before observing the first message from remote peer
370 */
371 QUICLY_STATE_FIRSTFLIGHT,
372 /**
373 * internal state used to indicate that the connection has not been provided to the application (and therefore might not have
374 * application data being associated)
375 */
376 QUICLY_STATE_ACCEPTING,
377 /**
378 * while connected
379 */
380 QUICLY_STATE_CONNECTED,
381 /**
382 * sending close, but haven't seen the remote peer sending close
383 */
384 QUICLY_STATE_CLOSING,
385 /**
386 * we do not send CLOSE (at the moment), enter draining mode when receiving CLOSE
387 */
388 QUICLY_STATE_DRAINING
389 } quicly_state_t;
390
391 struct st_quicly_conn_streamgroup_state_t {
392 uint32_t num_streams;
393 quicly_stream_id_t next_stream_id;
394 };
395
396 /**
397 * Values that do not need to be gathered upon the invocation of `quicly_get_stats`. We use typedef to define the same fields in
398 * the same order for quicly_stats_t and `struct st_quicly_conn_public_t::stats`.
399 */
400 #define QUICLY_STATS_PREBUILT_FIELDS \
401 struct { \
402 /** \
403 * Total number of packets received. \
404 */ \
405 uint64_t received; \
406 /** \
407 * Total number of packets that failed decryption. \
408 */ \
409 uint64_t decryption_failed; \
410 /** \
411 * Total number of packets sent. \
412 */ \
413 uint64_t sent; \
414 /** \
415 * Total number of packets marked lost. \
416 */ \
417 uint64_t lost; \
418 /** \
419 * Total number of packets marked lost via time-threshold loss detection. \
420 */ \
421 uint64_t lost_time_threshold; \
422 /** \
423 * Total number of packets for which acknowledgements have been received. \
424 */ \
425 uint64_t ack_received; \
426 /** \
427 * Total number of packets for which acknowledgements were received after being marked lost. \
428 */ \
429 uint64_t late_acked; \
430 } num_packets; \
431 struct { \
432 /** \
433 * Total bytes received, at UDP datagram-level. Used for determining the amplification limit. \
434 */ \
435 uint64_t received; \
436 /** \
437 * Total bytes sent, at UDP datagram-level. \
438 */ \
439 uint64_t sent; \
440 /** \
441 * Total bytes sent but lost, at UDP datagram-level. \
442 */ \
443 uint64_t lost; \
444 /** \
445 * Total number of bytes for which acknowledgements have been received. \
446 */ \
447 uint64_t ack_received; \
448 /** \
449 * Total amount of stream-level payload being sent \
450 */ \
451 uint64_t stream_data_sent; \
452 /** \
453 * Total amount of stream-level payload being resent \
454 */ \
455 uint64_t stream_data_resent; \
456 } num_bytes; \
457 /** \
458 * Total number of each frame being sent / received. \
459 */ \
460 struct { \
461 uint64_t padding, ping, ack, reset_stream, stop_sending, crypto, new_token, stream, max_data, max_stream_data, \
462 max_streams_bidi, max_streams_uni, data_blocked, stream_data_blocked, streams_blocked, new_connection_id, \
463 retire_connection_id, path_challenge, path_response, transport_close, application_close, handshake_done, datagram, \
464 ack_frequency; \
465 } num_frames_sent, num_frames_received; \
466 /** \
467 * Total number of PTOs observed during the connection. \
468 */ \
469 uint64_t num_ptos
470
471 typedef struct st_quicly_stats_t {
472 /**
473 * The pre-built fields. This MUST be the first member of `quicly_stats_t` so that we can use `memcpy`.
474 */
475 QUICLY_STATS_PREBUILT_FIELDS;
476 /**
477 * RTT stats.
478 */
479 quicly_rtt_t rtt;
480 /**
481 * Congestion control stats (experimental; TODO cherry-pick what can be exposed as part of a stable API).
482 */
483 quicly_cc_t cc;
484 /**
485 * Estimated delivery rate, in bytes/second.
486 */
487 quicly_rate_t delivery_rate;
488 } quicly_stats_t;
489
490 /**
491 * The state of the default stream scheduler.
492 * `active` is a linked-list of streams for which STREAM frames can be emitted. `blocked` is a linked-list of streams that have
493 * something to be sent but are currently blocked by the connection-level flow control.
494 * When the `can_send` callback of the default stream scheduler is invoked with the `conn_is_saturated` flag set, connections that
495 * are blocked are eventually moved to the `blocked` list. When the callback is invoked without the flag being set, all the
496 * connections in the `blocked` list is moved to the `active` list and the `in_saturated_mode` is cleared.
497 */
498 struct st_quicly_default_scheduler_state_t {
499 quicly_linklist_t active;
500 quicly_linklist_t blocked;
501 };
502
503 typedef void (*quicly_trace_cb)(void *ctx, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
504
505 struct _st_quicly_conn_public_t {
506 quicly_context_t *ctx;
507 quicly_state_t state;
508 struct {
509 /**
510 * connection IDs being issued to the remote peer.
511 * `quicly_conn_public_t::local.cid_set.plaintext.master_id has to be located right after `ctx` and `state`, as probes rely
512 * on that assumption.
513 */
514 quicly_local_cid_set_t cid_set;
515 /**
516 * the local address (may be AF_UNSPEC)
517 */
518 quicly_address_t address;
519 /**
520 * the SCID used in long header packets. Equiavalent to local_cid[seq=0]. Retaining the value separately is the easiest way
521 * of staying away from the complexity caused by remote peer sending RCID frames before the handshake concludes.
522 */
523 quicly_cid_t long_header_src_cid;
524 /**
525 * stream-level limits
526 */
527 struct st_quicly_conn_streamgroup_state_t bidi, uni;
528 } local;
529 struct {
530 /**
531 * CIDs received from the remote peer
532 */
533 quicly_remote_cid_set_t cid_set;
534 /**
535 * the remote address (cannot be AF_UNSPEC)
536 */
537 quicly_address_t address;
538 struct st_quicly_conn_streamgroup_state_t bidi, uni;
539 quicly_transport_parameters_t transport_params;
540 struct {
541 unsigned validated : 1;
542 unsigned send_probe : 1;
543 } address_validation;
544 /**
545 * largest value of Retire Prior To field observed so far
546 */
547 uint64_t largest_retire_prior_to;
548 } remote;
549 /**
550 * Retains the original DCID used by the client. Servers use this to route packets incoming packets. Clients use this when
551 * validating the Transport Parameters sent by the server.
552 */
553 quicly_cid_t original_dcid;
554 struct st_quicly_default_scheduler_state_t _default_scheduler;
555 struct {
556 QUICLY_STATS_PREBUILT_FIELDS;
557 } stats;
558 uint32_t version;
559 void *data;
560 /**
561 * trace callback (cb != NULL when used)
562 */
563 quicly_tracer_t tracer;
564 };
565
566 typedef enum {
567 /**
568 * initial state
569 */
570 QUICLY_SENDER_STATE_NONE,
571 /**
572 * to be sent. Changes to UNACKED when sent out by quicly_send
573 */
574 QUICLY_SENDER_STATE_SEND,
575 /**
576 * inflight. changes to SEND (when packet is deemed lost), or ACKED (when packet is ACKed)
577 */
578 QUICLY_SENDER_STATE_UNACKED,
579 /**
580 * the sent value acknowledged by remote peer
581 */
582 QUICLY_SENDER_STATE_ACKED,
583 } quicly_sender_state_t;
584
585 /**
586 * API that allows applications to specify it's own send / receive buffer. The callback should be assigned by the
587 * `quicly_context_t::on_stream_open` callback.
588 */
589 typedef struct st_quicly_stream_callbacks_t {
590 /**
591 * called when the stream is destroyed
592 */
593 void (*on_destroy)(quicly_stream_t *stream, int err);
594 /**
595 * called whenever data can be retired from the send buffer, specifying the amount that can be newly removed
596 */
597 void (*on_send_shift)(quicly_stream_t *stream, size_t delta);
598 /**
599 * asks the application to fill the frame payload. `off` is the offset within the buffer (the beginning position of the buffer
600 * changes as `on_send_shift` is invoked). `len` is an in/out argument that specifies the size of the buffer / amount of data
601 * being written. `wrote_all` is a boolean out parameter indicating if the application has written all the available data.
602 * As this callback is triggered by calling quicly_stream_sync_sendbuf (stream, 1) when tx data is present, it assumes data
603 * to be available - that is `len` return value should be non-zero.
604 */
605 void (*on_send_emit)(quicly_stream_t *stream, size_t off, void *dst, size_t *len, int *wrote_all);
606 /**
607 * called when a STOP_SENDING frame is received. Do not call `quicly_reset_stream` in response. The stream will be
608 * automatically reset by quicly.
609 */
610 void (*on_send_stop)(quicly_stream_t *stream, int err);
611 /**
612 * called when data is newly received. `off` is the offset within the buffer (the beginning position changes as the application
613 * calls `quicly_stream_sync_recvbuf`. Applications should consult `quicly_stream_t::recvstate` to see if it has contiguous
614 * input.
615 */
616 void (*on_receive)(quicly_stream_t *stream, size_t off, const void *src, size_t len);
617 /**
618 * called when a RESET_STREAM frame is received
619 */
620 void (*on_receive_reset)(quicly_stream_t *stream, int err);
621 } quicly_stream_callbacks_t;
622
623 struct st_quicly_stream_t {
624 /**
625 *
626 */
627 quicly_conn_t *conn;
628 /**
629 * stream id
630 */
631 quicly_stream_id_t stream_id;
632 /**
633 *
634 */
635 const quicly_stream_callbacks_t *callbacks;
636 /**
637 * send buffer
638 */
639 quicly_sendstate_t sendstate;
640 /**
641 * receive buffer
642 */
643 quicly_recvstate_t recvstate;
644 /**
645 *
646 */
647 void *data;
648 /**
649 *
650 */
651 unsigned streams_blocked : 1;
652 /**
653 *
654 */
655 struct {
656 /**
657 * send window
658 */
659 uint64_t max_stream_data;
660 /**
661 *
662 */
663 struct {
664 quicly_sender_state_t sender_state;
665 uint16_t error_code;
666 } stop_sending;
667 /**
668 * reset_stream
669 */
670 struct {
671 /**
672 * STATE_NONE until RST is generated
673 */
674 quicly_sender_state_t sender_state;
675 uint16_t error_code;
676 } reset_stream;
677 /**
678 * sends receive window updates to remote peer
679 */
680 quicly_maxsender_t max_stream_data_sender;
681 /**
682 * send state of STREAM_DATA_BLOCKED frames corresponding to the current max_stream_data value
683 */
684 quicly_sender_state_t blocked;
685 /**
686 * linklist of pending streams
687 */
688 struct {
689 quicly_linklist_t control; /* links to conn_t::control (or to conn_t::streams_blocked if the blocked flag is set) */
690 quicly_linklist_t default_scheduler;
691 } pending_link;
692 } _send_aux;
693 /**
694 *
695 */
696 struct {
697 /**
698 * size of the receive window
699 */
700 uint32_t window;
701 /**
702 * Maximum number of ranges (i.e. gaps + 1) permitted in `recvstate.ranges`.
703 * As discussed in https://github.com/h2o/quicly/issues/278, this value should be propotional to the size of the receive
704 * window, so that the receive window can be maintained even in the worst case, where every one of the two packets being
705 * sent are received.
706 */
707 uint32_t max_ranges;
708 } _recv_aux;
709 };
710
711 typedef struct st_quicly_decoded_packet_t {
712 /**
713 * octets of the entire packet
714 */
715 ptls_iovec_t octets;
716 /**
717 * Connection ID(s)
718 */
719 struct {
720 /**
721 * destination CID
722 */
723 struct {
724 /**
725 * CID visible on wire
726 */
727 ptls_iovec_t encrypted;
728 /**
729 * The decrypted CID, or `quicly_cid_plaintext_invalid`. Assuming that `cid_encryptor` is non-NULL, this variable would
730 * contain a valid value whenever `might_be_client_generated` is false. When `might_be_client_generated` is true, this
731 * value might be set to `quicly_cid_plaintext_invalid`. Note however that, as the CID itself is not authenticated,
732 * a packet might be bogus regardless of the value of the CID.
733 * When `cid_encryptor` is NULL, the value is always set to `quicly_cid_plaintext_invalid`.
734 */
735 quicly_cid_plaintext_t plaintext;
736 /**
737 * If destination CID might be one generated by a client. This flag would be set for Initial and 0-RTT packets.
738 */
739 unsigned might_be_client_generated : 1;
740 } dest;
741 /**
742 * source CID; {NULL, 0} if is a short header packet
743 */
744 ptls_iovec_t src;
745 } cid;
746 /**
747 * version; 0 if is a short header packet
748 */
749 uint32_t version;
750 /**
751 * token if available; otherwise {NULL, 0}
752 */
753 ptls_iovec_t token;
754 /**
755 * starting offset of data (i.e., version-dependent area of a long header packet (version numbers in case of VN), AEAD tag (in
756 * case of retry), encrypted PN (if decrypted.pn is UINT64_MAX) or data (if decrypted_pn is not UINT64_MAX))
757 */
758 size_t encrypted_off;
759 /**
760 * size of the UDP datagram; set to zero if this is not the first QUIC packet within the datagram
761 */
762 size_t datagram_size;
763 /**
764 * when decrypted.pn is not UINT64_MAX, indicates that the packet has been decrypted prior to being passed to `quicly_receive`.
765 */
766 struct {
767 uint64_t pn;
768 uint64_t key_phase;
769 } decrypted;
770 /**
771 *
772 */
773 enum {
774 QUICLY__DECODED_PACKET_CACHED_MAYBE_STATELESS_RESET = 0,
775 QUICLY__DECODED_PACKET_CACHED_IS_STATELESS_RESET,
776 QUICLY__DECODED_PACKET_CACHED_NOT_STATELESS_RESET
777 } _is_stateless_reset_cached;
778 } quicly_decoded_packet_t;
779
780 struct st_quicly_address_token_plaintext_t {
781 enum { QUICLY_ADDRESS_TOKEN_TYPE_RETRY, QUICLY_ADDRESS_TOKEN_TYPE_RESUMPTION } type;
782 uint64_t issued_at;
783 quicly_address_t local, remote;
784 union {
785 struct {
786 quicly_cid_t original_dcid;
787 quicly_cid_t client_cid;
788 quicly_cid_t server_cid;
789 } retry;
790 struct {
791 uint8_t bytes[256];
792 size_t len;
793 } resumption;
794 };
795 struct {
796 uint8_t bytes[256];
797 size_t len;
798 } appdata;
799 };
800
801 /**
802 * zero-terminated list of protocol versions being supported by quicly
803 */
804 extern const uint32_t quicly_supported_versions[];
805 /**
806 * returns a boolean indicating if given protocol version is supported
807 */
808 static int quicly_is_supported_version(uint32_t version);
809 /**
810 * Extracts QUIC packets from a datagram pointed to by `src` and `len`. If successful, the function returns the size of the QUIC
811 * packet being decoded. Otherwise, SIZE_MAX is returned.
812 * `off` is an I/O argument that takes starting offset of the QUIC packet to be decoded as input, and returns the starting offset of
813 * the next QUIC packet. A typical loop that handles an UDP datagram would look like:
814 *
815 * size_t off = 0;
816 * while (off < dgram.size) {
817 * if (quicly_decode_packet(ctx, &packet, dgram.bytes, dgram.size, &off) == SIZE_MAX)
818 * break;
819 * handle_quic_packet(&packet);
820 * }
821 */
822 size_t quicly_decode_packet(quicly_context_t *ctx, quicly_decoded_packet_t *packet, const uint8_t *datagram, size_t datagram_size,
823 size_t *off);
824 /**
825 *
826 */
827 uint64_t quicly_determine_packet_number(uint32_t truncated, size_t num_bits, uint64_t expected);
828 /**
829 *
830 */
831 static quicly_context_t *quicly_get_context(quicly_conn_t *conn);
832 /**
833 *
834 */
835 static const quicly_cid_plaintext_t *quicly_get_master_id(quicly_conn_t *conn);
836 /**
837 *
838 */
839 static const quicly_cid_t *quicly_get_original_dcid(quicly_conn_t *conn);
840 /**
841 *
842 */
843 static const quicly_cid_t *quicly_get_remote_cid(quicly_conn_t *conn);
844 /**
845 *
846 */
847 static const quicly_transport_parameters_t *quicly_get_remote_transport_parameters(quicly_conn_t *conn);
848 /**
849 *
850 */
851 static quicly_state_t quicly_get_state(quicly_conn_t *conn);
852 /**
853 *
854 */
855 int quicly_connection_is_ready(quicly_conn_t *conn);
856 /**
857 *
858 */
859 static uint32_t quicly_num_streams(quicly_conn_t *conn);
860 /**
861 *
862 */
863 uint32_t quicly_num_streams_by_group(quicly_conn_t *conn, int uni, int locally_initiated);
864 /**
865 *
866 */
867 static int quicly_is_client(quicly_conn_t *conn);
868 /**
869 *
870 */
871 static quicly_stream_id_t quicly_get_local_next_stream_id(quicly_conn_t *conn, int uni);
872 /**
873 *
874 */
875 static quicly_stream_id_t quicly_get_remote_next_stream_id(quicly_conn_t *conn, int uni);
876 /**
877 * Returns the local address of the connection. This may be AF_UNSPEC, indicating that the operating system is choosing the address.
878 */
879 static struct sockaddr *quicly_get_sockname(quicly_conn_t *conn);
880 /**
881 * Returns the remote address of the connection. This would never be AF_UNSPEC.
882 */
883 static struct sockaddr *quicly_get_peername(quicly_conn_t *conn);
884 /**
885 *
886 */
887 int quicly_get_stats(quicly_conn_t *conn, quicly_stats_t *stats);
888 /**
889 *
890 */
891 int quicly_get_delivery_rate(quicly_conn_t *conn, quicly_rate_t *delivery_rate);
892 /**
893 *
894 */
895 void quicly_get_max_data(quicly_conn_t *conn, uint64_t *send_permitted, uint64_t *sent, uint64_t *consumed);
896 /**
897 *
898 */
899 static uint32_t quicly_get_protocol_version(quicly_conn_t *conn);
900 /**
901 *
902 */
903 static void **quicly_get_data(quicly_conn_t *conn);
904 /**
905 *
906 */
907 static quicly_tracer_t *quicly_get_tracer(quicly_conn_t *conn);
908 /**
909 * destroys a connection object.
910 */
911 void quicly_free(quicly_conn_t *conn);
912 /**
913 * closes the connection. `err` is the application error code using the coalesced scheme (see QUICLY_ERROR_* macros), or zero (no
914 * error; indicating idle close). An application should continue calling quicly_recieve and quicly_send, until they return
915 * QUICLY_ERROR_FREE_CONNECTION. At this point, it is should call quicly_free.
916 */
917 int quicly_close(quicly_conn_t *conn, int err, const char *reason_phrase);
918 /**
919 *
920 */
921 int64_t quicly_get_first_timeout(quicly_conn_t *conn);
922 /**
923 *
924 */
925 uint64_t quicly_get_next_expected_packet_number(quicly_conn_t *conn);
926 /**
927 * returns if the connection is currently blocked by connection-level flow control.
928 */
929 int quicly_is_blocked(quicly_conn_t *conn);
930 /**
931 * Returns if stream data can be sent.
932 * When the connection is blocked by the connection-level flow control (see `quicly_is_blocked`), `at_stream_level` should be set to
933 * false to see if any retransmissions are to be done. Otherwise, `at_stream_level` should be set to true to test the stream-level
934 * flow control.
935 */
936 int quicly_stream_can_send(quicly_stream_t *stream, int at_stream_level);
937 /**
938 * checks if quicly_send_stream can be invoked
939 * @return a boolean indicating if quicly_send_stream can be called immediately
940 */
941 int quicly_can_send_data(quicly_conn_t *conn, quicly_send_context_t *s);
942 /**
943 * Sends data of given stream. Called by stream scheduler. Only streams that can send some data or EOS should be specified. It is
944 * the responsibilty of the stream scheduler to maintain a list of such streams.
945 */
946 int quicly_send_stream(quicly_stream_t *stream, quicly_send_context_t *s);
947 /**
948 * Builds a Version Negotiation packet. The generated packet might include a greasing version.
949 * * @param versions zero-terminated list of versions to advertise; use `quicly_supported_versions` for sending the list of
950 * protocol versions supported by quicly
951 */
952 size_t quicly_send_version_negotiation(quicly_context_t *ctx, ptls_iovec_t dest_cid, ptls_iovec_t src_cid, const uint32_t *versions,
953 void *payload);
954 /**
955 *
956 */
957 int quicly_retry_calc_cidpair_hash(ptls_hash_algorithm_t *sha256, ptls_iovec_t client_cid, ptls_iovec_t server_cid,
958 uint64_t *value);
959 /**
960 * Builds a UDP datagram containing a Retry packet.
961 * @param retry_aead_cache pointer to `ptls_aead_context_t *` that the function can store a AEAD context for future reuse. The
962 * cache cannot be shared between multiple threads. Can be set to NULL when caching is unnecessary.
963 * @param payload buffer used for building the packet
964 * @return size of the UDP datagram payload being built, or otherwise SIZE_MAX to indicate failure
965 */
966 size_t quicly_send_retry(quicly_context_t *ctx, ptls_aead_context_t *token_encrypt_ctx, uint32_t protocol_version,
967 struct sockaddr *dest_addr, ptls_iovec_t dest_cid, struct sockaddr *src_addr, ptls_iovec_t src_cid,
968 ptls_iovec_t odcid, ptls_iovec_t token_prefix, ptls_iovec_t appdata,
969 ptls_aead_context_t **retry_aead_cache, uint8_t *payload);
970 /**
971 * Builds UDP datagrams to be sent for given connection.
972 * @param [out] dest destination address
973 * @param [out] src source address
974 * @param [out] datagrams vector of iovecs pointing to the payloads of UDP datagrams. Each iovec represens a single UDP
975 * datagram.
976 * @param [in,out] num_datagrams Upon entry, the application provides the number of entries that the `packets` vector can contain.
977 * Upon return, contains the number of packet vectors emitted by `quicly_send`.
978 * @param buf buffer used for building UDP datagrams. It is guaranteed that the first datagram would be built
979 * from the address provided by `buf`, and that succeeding packets (if any) will be contiguously laid
980 * out. This constraint reduces the number of vectors that need to be passed to the kernel when using
981 * GSO.
982 * @return 0 if successful, otherwise an error. When an error is returned, the caller must call `quicly_close` to discard the
983 * connection context.
984 */
985 int quicly_send(quicly_conn_t *conn, quicly_address_t *dest, quicly_address_t *src, struct iovec *datagrams, size_t *num_datagrams,
986 void *buf, size_t bufsize);
987 /**
988 *
989 */
990 size_t quicly_send_close_invalid_token(quicly_context_t *ctx, uint32_t protocol_version, ptls_iovec_t dest_cid,
991 ptls_iovec_t src_cid, const char *err_desc, void *datagram);
992 /**
993 *
994 */
995 size_t quicly_send_stateless_reset(quicly_context_t *ctx, const void *src_cid, void *payload);
996 /**
997 *
998 */
999 int quicly_send_resumption_token(quicly_conn_t *conn);
1000 /**
1001 *
1002 */
1003 int quicly_receive(quicly_conn_t *conn, struct sockaddr *dest_addr, struct sockaddr *src_addr, quicly_decoded_packet_t *packet);
1004 /**
1005 * consults if the incoming packet identified by (dest_addr, src_addr, decoded) belongs to the given connection
1006 */
1007 int quicly_is_destination(quicly_conn_t *conn, struct sockaddr *dest_addr, struct sockaddr *src_addr,
1008 quicly_decoded_packet_t *decoded);
1009 /**
1010 *
1011 */
1012 int quicly_encode_transport_parameter_list(ptls_buffer_t *buf, const quicly_transport_parameters_t *params,
1013 const quicly_cid_t *original_dcid, const quicly_cid_t *initial_scid,
1014 const quicly_cid_t *retry_scid, const void *stateless_reset_token, size_t expand_by);
1015 /**
1016 * Decodes the Transport Parameters.
1017 * For the four optional output parameters (`original_dcid`, `initial_scid`, `retry_scid`, `stateless_reset_token`), this function
1018 * returns an error if NULL were supplied as the arguments and the corresponding Transport Parameters were received.
1019 * If corresponding Transport Parameters were not found for any of the non-null connection ID slots, an error is returned.
1020 * Stateless reset is an optional feature of QUIC, and therefore no error is returned when the vector for storing the token is
1021 * provided and the corresponding Transport Parameter is missing. In that case, the provided vector remains unmodified. The caller
1022 * pre-fills the vector with an unpredictable value (i.e. random), then calls this function to set the stateless reset token to the
1023 * value supplied by peer.
1024 */
1025 int quicly_decode_transport_parameter_list(quicly_transport_parameters_t *params, quicly_cid_t *original_dcid,
1026 quicly_cid_t *initial_scid, quicly_cid_t *retry_scid, void *stateless_reset_token,
1027 const uint8_t *src, const uint8_t *end);
1028 /**
1029 * Initiates a new connection.
1030 * @param new_cid the CID to be used for the connection. path_id is ignored.
1031 */
1032 int quicly_connect(quicly_conn_t **conn, quicly_context_t *ctx, const char *server_name, struct sockaddr *dest_addr,
1033 struct sockaddr *src_addr, const quicly_cid_plaintext_t *new_cid, ptls_iovec_t address_token,
1034 ptls_handshake_properties_t *handshake_properties,
1035 const quicly_transport_parameters_t *resumed_transport_params);
1036 /**
1037 * accepts a new connection
1038 * @param new_cid The CID to be used for the connection. When an error is being returned, the application can reuse the CID
1039 * provided to the function.
1040 * @param address_token An validated address validation token, if any. Applications MUST validate the address validation token
1041 * before calling this function, dropping the ones that failed to validate. When a token is supplied,
1042 * `quicly_accept` will consult the values being supplied assuming that the remote peer's address has been
1043 * validated.
1044 */
1045 int quicly_accept(quicly_conn_t **conn, quicly_context_t *ctx, struct sockaddr *dest_addr, struct sockaddr *src_addr,
1046 quicly_decoded_packet_t *packet, quicly_address_token_plaintext_t *address_token,
1047 const quicly_cid_plaintext_t *new_cid, ptls_handshake_properties_t *handshake_properties);
1048 /**
1049 *
1050 */
1051 ptls_t *quicly_get_tls(quicly_conn_t *conn);
1052 /**
1053 *
1054 */
1055 quicly_stream_id_t quicly_get_ingress_max_streams(quicly_conn_t *conn, int uni);
1056 /**
1057 * Iterates through each stream. When the callback returns a non-zero value, bails out from the iteration, returning the returned
1058 * value.
1059 */
1060 int quicly_foreach_stream(quicly_conn_t *conn, void *thunk, int (*cb)(void *thunk, quicly_stream_t *stream));
1061 /**
1062 *
1063 */
1064 quicly_stream_t *quicly_get_stream(quicly_conn_t *conn, quicly_stream_id_t stream_id);
1065 /**
1066 *
1067 */
1068 int quicly_open_stream(quicly_conn_t *conn, quicly_stream_t **stream, int unidirectional);
1069 /**
1070 * This function returns a stream that is already open, or if the given ID refers to a stream that can be opened by the peer but is
1071 * yet-to-be opened, the functions opens that stream and returns it. Otherwise, `*stream` is set to NULL.
1072 * This function can be used when implementing application protocols that send references to other streams on a stream (e.g.,
1073 * PRIORITY_UPDATE frame of HTTP/3), however note that the peer might complain if the endpoint sends a frame that refers to a peer-
1074 * initiated stream for which the peer has not yet sent anything.
1075 * Invocation of this function might open not only the stream that is referred to by the `stream_id` but also other streams.
1076 */
1077 int quicly_get_or_open_stream(quicly_conn_t *conn, uint64_t stream_id, quicly_stream_t **stream);
1078 /**
1079 *
1080 */
1081 void quicly_reset_stream(quicly_stream_t *stream, int err);
1082 /**
1083 *
1084 */
1085 void quicly_request_stop(quicly_stream_t *stream, int err);
1086 /**
1087 *
1088 */
1089 static int quicly_stop_requested(quicly_stream_t *stream);
1090 /**
1091 *
1092 */
1093 int quicly_stream_sync_sendbuf(quicly_stream_t *stream, int activate);
1094 /**
1095 *
1096 */
1097 void quicly_stream_sync_recvbuf(quicly_stream_t *stream, size_t shift_amount);
1098 /**
1099 *
1100 */
1101 static uint32_t quicly_stream_get_receive_window(quicly_stream_t *stream);
1102 /**
1103 *
1104 */
1105 static void quicly_stream_set_receive_window(quicly_stream_t *stream, uint32_t window);
1106 /**
1107 *
1108 */
1109 static int quicly_stream_is_client_initiated(quicly_stream_id_t stream_id);
1110 /**
1111 *
1112 */
1113 static int quicly_stream_is_unidirectional(quicly_stream_id_t stream_id);
1114 /**
1115 *
1116 */
1117 static int quicly_stream_has_send_side(int is_client, quicly_stream_id_t stream_id);
1118 /**
1119 *
1120 */
1121 static int quicly_stream_has_receive_side(int is_client, quicly_stream_id_t stream_id);
1122 /**
1123 *
1124 */
1125 static int quicly_stream_is_self_initiated(quicly_stream_t *stream);
1126 /**
1127 * Sends QUIC DATAGRAM frames. Some of the frames being provided may get dropped.
1128 * Notes:
1129 * * At the moment, emission of QUIC packets carrying DATAGRAM frames is not congestion controlled.
1130 * * While the API is designed to look like synchronous, application still has to call `quicly_send` for the time being.
1131 */
1132 void quicly_send_datagram_frames(quicly_conn_t *conn, ptls_iovec_t *datagrams, size_t num_datagrams);
1133 /**
1134 * Sets CC to the specified type. Returns a boolean indicating if the operation was successful.
1135 */
1136 int quicly_set_cc(quicly_conn_t *conn, quicly_cc_type_t *cc);
1137 /**
1138 *
1139 */
1140 void quicly_amend_ptls_context(ptls_context_t *ptls);
1141 /**
1142 * Encrypts an address token by serializing the plaintext structure and appending an authentication tag.
1143 *
1144 * @param random_bytes PRNG
1145 * @param aead the AEAD context to be used for decrypting the token
1146 * @param buf buffer to where the token being built is appended
1147 * @param start_off Specifies the start offset of the token. When `start_off < buf->off`, the bytes in between will be
1148 * considered as part of the token and will be covered by the AEAD. Applications can use this location to embed
1149 * the identifier of the AEAD key being used.
1150 * @param plaintext the token to be encrypted
1151 */
1152 int quicly_encrypt_address_token(void (*random_bytes)(void *, size_t), ptls_aead_context_t *aead, ptls_buffer_t *buf,
1153 size_t start_off, const quicly_address_token_plaintext_t *plaintext);
1154 /**
1155 * Decrypts an address token.
1156 * If decryption succeeds, returns zero. If the token is unusable due to decryption failure, returns PTLS_DECODE_ERROR. If the token
1157 * is unusable and the connection should be reset, returns QUICLY_ERROR_INVALID_TOKEN.
1158 */
1159 int quicly_decrypt_address_token(ptls_aead_context_t *aead, quicly_address_token_plaintext_t *plaintext, const void *src,
1160 size_t len, size_t prefix_len, const char **err_desc);
1161 /**
1162 * Builds authentication data for TLS session ticket. 0-RTT can be accepted only when the auth_data of the original connection and
1163 * the new connection are identical.
1164 */
1165 int quicly_build_session_ticket_auth_data(ptls_buffer_t *auth_data, const quicly_context_t *ctx);
1166 /**
1167 *
1168 */
1169 static void quicly_byte_to_hex(char *dst, uint8_t v);
1170 /**
1171 *
1172 */
1173 socklen_t quicly_get_socklen(struct sockaddr *sa);
1174 /**
1175 * Builds a safe string. Supplied buffer MUST be 4x + 1 bytes bigger than the input.
1176 */
1177 char *quicly_escape_unsafe_string(char *dst, const void *bytes, size_t len);
1178 /**
1179 *
1180 */
1181 char *quicly_hexdump(const uint8_t *bytes, size_t len, size_t indent);
1182 /**
1183 *
1184 */
1185 void quicly_stream_noop_on_destroy(quicly_stream_t *stream, int err);
1186 /**
1187 *
1188 */
1189 void quicly_stream_noop_on_send_shift(quicly_stream_t *stream, size_t delta);
1190 /**
1191 *
1192 */
1193 void quicly_stream_noop_on_send_emit(quicly_stream_t *stream, size_t off, void *dst, size_t *len, int *wrote_all);
1194 /**
1195 *
1196 */
1197 void quicly_stream_noop_on_send_stop(quicly_stream_t *stream, int err);
1198 /**
1199 *
1200 */
1201 void quicly_stream_noop_on_receive(quicly_stream_t *stream, size_t off, const void *src, size_t len);
1202 /**
1203 *
1204 */
1205 void quicly_stream_noop_on_receive_reset(quicly_stream_t *stream, int err);
1206
1207 extern const quicly_stream_callbacks_t quicly_stream_noop_callbacks;
1208
1209 /* inline definitions */
1210
quicly_is_supported_version(uint32_t version)1211 inline int quicly_is_supported_version(uint32_t version)
1212 {
1213 switch (version) {
1214 case QUICLY_PROTOCOL_VERSION_1:
1215 case QUICLY_PROTOCOL_VERSION_DRAFT29:
1216 case QUICLY_PROTOCOL_VERSION_DRAFT27:
1217 return 1;
1218 default:
1219 return 0;
1220 }
1221 }
1222
quicly_get_state(quicly_conn_t * conn)1223 inline quicly_state_t quicly_get_state(quicly_conn_t *conn)
1224 {
1225 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1226 return c->state;
1227 }
1228
quicly_num_streams(quicly_conn_t * conn)1229 inline uint32_t quicly_num_streams(quicly_conn_t *conn)
1230 {
1231 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1232 return c->local.bidi.num_streams + c->local.uni.num_streams + c->remote.bidi.num_streams + c->remote.uni.num_streams;
1233 }
1234
quicly_get_context(quicly_conn_t * conn)1235 inline quicly_context_t *quicly_get_context(quicly_conn_t *conn)
1236 {
1237 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1238 return c->ctx;
1239 }
1240
quicly_get_master_id(quicly_conn_t * conn)1241 inline const quicly_cid_plaintext_t *quicly_get_master_id(quicly_conn_t *conn)
1242 {
1243 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1244 return &c->local.cid_set.plaintext;
1245 }
1246
quicly_get_original_dcid(quicly_conn_t * conn)1247 inline const quicly_cid_t *quicly_get_original_dcid(quicly_conn_t *conn)
1248 {
1249 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1250 return &c->original_dcid;
1251 }
1252
quicly_get_remote_cid(quicly_conn_t * conn)1253 inline const quicly_cid_t *quicly_get_remote_cid(quicly_conn_t *conn)
1254 {
1255 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1256 return &c->remote.cid_set.cids[0].cid;
1257 }
1258
quicly_get_remote_transport_parameters(quicly_conn_t * conn)1259 inline const quicly_transport_parameters_t *quicly_get_remote_transport_parameters(quicly_conn_t *conn)
1260 {
1261 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1262 return &c->remote.transport_params;
1263 }
1264
quicly_is_client(quicly_conn_t * conn)1265 inline int quicly_is_client(quicly_conn_t *conn)
1266 {
1267 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1268 return (c->local.bidi.next_stream_id & 1) == 0;
1269 }
1270
quicly_get_local_next_stream_id(quicly_conn_t * conn,int uni)1271 inline quicly_stream_id_t quicly_get_local_next_stream_id(quicly_conn_t *conn, int uni)
1272 {
1273 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1274 return uni ? c->local.uni.next_stream_id : c->local.bidi.next_stream_id;
1275 }
1276
quicly_get_remote_next_stream_id(quicly_conn_t * conn,int uni)1277 inline quicly_stream_id_t quicly_get_remote_next_stream_id(quicly_conn_t *conn, int uni)
1278 {
1279 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1280 return uni ? c->remote.uni.next_stream_id : c->remote.bidi.next_stream_id;
1281 }
1282
quicly_get_sockname(quicly_conn_t * conn)1283 inline struct sockaddr *quicly_get_sockname(quicly_conn_t *conn)
1284 {
1285 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1286 return &c->local.address.sa;
1287 }
1288
quicly_get_peername(quicly_conn_t * conn)1289 inline struct sockaddr *quicly_get_peername(quicly_conn_t *conn)
1290 {
1291 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1292 return &c->remote.address.sa;
1293 }
1294
quicly_get_protocol_version(quicly_conn_t * conn)1295 inline uint32_t quicly_get_protocol_version(quicly_conn_t *conn)
1296 {
1297 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1298 return c->version;
1299 }
1300
quicly_get_data(quicly_conn_t * conn)1301 inline void **quicly_get_data(quicly_conn_t *conn)
1302 {
1303 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1304 return &c->data;
1305 }
1306
quicly_get_tracer(quicly_conn_t * conn)1307 inline quicly_tracer_t *quicly_get_tracer(quicly_conn_t *conn)
1308 {
1309 struct _st_quicly_conn_public_t *c = (struct _st_quicly_conn_public_t *)conn;
1310 return &c->tracer;
1311 }
1312
quicly_stop_requested(quicly_stream_t * stream)1313 inline int quicly_stop_requested(quicly_stream_t *stream)
1314 {
1315 return stream->_send_aux.stop_sending.sender_state != QUICLY_SENDER_STATE_NONE;
1316 }
1317
quicly_stream_get_receive_window(quicly_stream_t * stream)1318 inline uint32_t quicly_stream_get_receive_window(quicly_stream_t *stream)
1319 {
1320 return stream->_recv_aux.window;
1321 }
1322
quicly_stream_set_receive_window(quicly_stream_t * stream,uint32_t window)1323 inline void quicly_stream_set_receive_window(quicly_stream_t *stream, uint32_t window)
1324 {
1325 stream->_recv_aux.window = window;
1326 }
1327
quicly_stream_is_client_initiated(quicly_stream_id_t stream_id)1328 inline int quicly_stream_is_client_initiated(quicly_stream_id_t stream_id)
1329 {
1330 if (stream_id < 0)
1331 return (stream_id & 1) != 0;
1332 return (stream_id & 1) == 0;
1333 }
1334
quicly_stream_is_unidirectional(quicly_stream_id_t stream_id)1335 inline int quicly_stream_is_unidirectional(quicly_stream_id_t stream_id)
1336 {
1337 if (stream_id < 0)
1338 return 0;
1339 return (stream_id & 2) != 0;
1340 }
1341
quicly_stream_has_send_side(int is_client,quicly_stream_id_t stream_id)1342 inline int quicly_stream_has_send_side(int is_client, quicly_stream_id_t stream_id)
1343 {
1344 if (!quicly_stream_is_unidirectional(stream_id))
1345 return 1;
1346 return is_client == quicly_stream_is_client_initiated(stream_id);
1347 }
1348
quicly_stream_has_receive_side(int is_client,quicly_stream_id_t stream_id)1349 inline int quicly_stream_has_receive_side(int is_client, quicly_stream_id_t stream_id)
1350 {
1351 if (!quicly_stream_is_unidirectional(stream_id))
1352 return 1;
1353 return is_client != quicly_stream_is_client_initiated(stream_id);
1354 }
1355
quicly_stream_is_self_initiated(quicly_stream_t * stream)1356 inline int quicly_stream_is_self_initiated(quicly_stream_t *stream)
1357 {
1358 return quicly_stream_is_client_initiated(stream->stream_id) == quicly_is_client(stream->conn);
1359 }
1360
quicly_byte_to_hex(char * dst,uint8_t v)1361 inline void quicly_byte_to_hex(char *dst, uint8_t v)
1362 {
1363 dst[0] = "0123456789abcdef"[v >> 4];
1364 dst[1] = "0123456789abcdef"[v & 0xf];
1365 }
1366
1367 #ifdef __cplusplus
1368 }
1369 #endif
1370
1371 #endif
1372