litespeed-quic/src/liblsquic/lsquic_parse.h

439 lines
18 KiB
C
Raw Normal View History

/* Copyright (c) 2017 - 2021 LiteSpeed Technologies Inc. See LICENSE. */
2017-09-22 21:00:03 +00:00
#ifndef LSQUIC_PARSE_H
#define LSQUIC_PARSE_H 1
#include <stdint.h>
#include "lsquic_packet_common.h"
#include "lsquic_packet_gquic.h"
#include "lsquic_shared_support.h"
2017-09-22 21:00:03 +00:00
struct lsquic_conn;
2017-09-22 21:00:03 +00:00
struct lsquic_packet_in;
2018-08-15 19:06:31 +00:00
struct lsquic_packet_out;
struct packin_parse_state;
2017-09-22 21:00:03 +00:00
struct stream_frame;
struct lsquic_cid;
2018-08-15 19:06:31 +00:00
enum packet_out_flags;
enum lsquic_version;
enum stream_dir;
2017-09-22 21:00:03 +00:00
struct ack_info
2017-09-22 21:00:03 +00:00
{
enum packnum_space pns;
enum {
AI_ECN = 1 << 0, /* ecn_counts[1,2,3] contain ECN counts */
AI_TRUNCATED = 1 << 1, /* There were more ranges to parse, but we
* ran out of elements in `ranges'.
*/
} flags;
2017-09-22 21:00:03 +00:00
unsigned n_ranges; /* This is at least 1 */
/* Largest acked is ack_info.ranges[0].high */
lsquic_time_t lack_delta;
uint64_t ecn_counts[4];
Latest changes - [API Change] lsquic_engine_connect() returns pointer to the connection object. - [API Change] Add lsquic_conn_get_engine() to get engine object from connection object. - [API Change] Add lsquic_conn_status() to query connection status. - [API Change] Add add lsquic_conn_set_ctx(). - [API Change] Add new timestamp format, e.g. 2017-03-21 13:43:46.671345 - [OPTIMIZATION] Process handshake STREAM frames as soon as packet arrives. - [OPTIMIZATION] Do not compile expensive send controller sanity check by default. - [OPTIMIZATION] Add fast path to gquic_be_gen_reg_pkt_header. - [OPTIMIZATION] Only make squeeze function call if necessary. - [OPTIMIZATION] Speed up Q039 ACK frame parsing. - [OPTIMIZATION] Fit most used elements of packet_out into first 64 bytes. - [OPTIMIZATION] Keep track of scheduled bytes instead of calculating. - [OPTIMIZATION] Prefetch next unacked packet when processing ACK. - [OPTIMIZATION] Leverage fact that ACK ranges and unacked list are. ordered. - [OPTIMIZATION] Reduce function pointer use for STREAM frame generation - Fix: reset incoming streams that arrive after we send GOAWAY. - Fix: delay client on_new_conn() call until connection is fully set up. - Fixes to buffered packets logic: splitting, STREAM frame elision. - Fix: do not dispatch on_write callback if no packets are available. - Fix WINDOW_UPDATE send and resend logic. - Fix STREAM frame extension code. - Fix: Drop unflushed data when stream is reset. - Switch to tracking CWND using bytes rather than packets. - Fix TCP friendly adjustment in cubic. - Fix: do not generate invalid STOP_WAITING frames during high packet loss. - Pacer fixes.
2018-02-26 21:01:16 +00:00
struct lsquic_packno_range ranges[256];
Latest changes - [OPTIMIZATION] Merge series of ACKs if possible Parsed single-range ACK frames (that is the majority of frames) are saved in the connection and their processing is deferred until the connection is ticked. If several ACKs come in a series between adjacent ticks, we check whether the latest ACK is a strict superset of the saved ACK. If it is, the older ACK is not processed. If ACK frames can be merged, they are merged and only one of them is either processed or saved. - [OPTIMIZATION] Speed up ACK verification by simplifying send history. Never generate a gap in the sent packet number sequence. This reduces the send history to a single number instead of potentially a series of packet ranges and thereby speeds up ACK verification. By default, detecting a gap in the send history is not fatal: only a single warning is generated per connection. The connection can continue to operate even if the ACK verification code is not able to detect some inconsistencies. - [OPTIMIZATION] Rearrange the lsquic_send_ctl struct The first part of struct lsquic_send_ctl now consists of members that are used in lsquic_send_ctl_got_ack() (in the absense of packet loss, which is the normal case). To speed up reads and writes, we no longer try to save space by using 8- and 16-bit integers. Use regular integer width for everything. - [OPTIMIZATION] Cache size of sent packet. - [OPTIMIZATION] Keep track of the largest ACKed in packet_out Instead of parsing our own ACK frames when packet has been acked, use the value saved in the packet_out structure when the ACK frame was generated. - [OPTIMIZATION] Take RTT sampling conditional out of ACK loop - [OPTIMIZATION] ACK processing: only call clock_gettime() if needed - [OPTIMIZATION] Several code-level optimizations to ACK processing. - Fix: http_client: fix -I flag; switch assert() to abort()
2018-03-09 19:17:39 +00:00
};
2017-09-22 21:00:03 +00:00
#define largest_acked(acki) (+(acki)->ranges[0].high)
#define smallest_acked(acki) (+(acki)->ranges[(acki)->n_ranges - 1].low)
/* Chrome may send an empty ACK frame when it closes a connection.
* We do not know why it occurs -- perhaps a bug in Chrome.
*/
/* This macro cannot be used in IETF QUIC as zero is a valid packet number.
* Hopefully the Chrome bug will have been fixed by then.
*/
#define empty_ack_frame(acki) (largest_acked(acki) == 0)
2017-09-22 21:00:03 +00:00
/* gaf_: generate ACK frame */
struct lsquic_packno_range;
typedef const struct lsquic_packno_range *
(*gaf_rechist_first_f) (void *rechist);
typedef const struct lsquic_packno_range *
(*gaf_rechist_next_f) (void *rechist);
typedef lsquic_time_t
(*gaf_rechist_largest_recv_f) (void *rechist);
/* gsf_: generate stream frame */
typedef size_t (*gsf_read_f) (void *stream, void *buf, size_t len, int *fin);
/* This structure contains functions that parse and generate packets and
* frames in version-specific manner. To begin with, there is difference
* between GQUIC's little-endian (Q038 and lower) and big-endian formats
* (Q039 and higher). Q046 and higher uses different format for packet headers.
2017-09-22 21:00:03 +00:00
*/
struct parse_funcs
{
/* Return buf length */
int
2018-08-15 19:06:31 +00:00
(*pf_gen_reg_pkt_header) (const struct lsquic_conn *,
const struct lsquic_packet_out *, unsigned char *, size_t,
/* In Q050 and IETF QUIC, these are set: */
unsigned *packno_off, unsigned *packno_len);
2017-09-22 21:00:03 +00:00
void
(*pf_parse_packet_in_finish) (struct lsquic_packet_in *packet_in,
struct packin_parse_state *);
enum quic_frame_type
(*pf_parse_frame_type) (const unsigned char *, size_t);
/* Return used buffer length or a negative value if there was not enough
* room to write the stream frame. In the latter case, the negative of
* the negative return value is the number of bytes required. The
* exception is -1, which is a generic error code, as we always need
* more than 1 byte to write a STREAM frame.
*/
/* pf_gen_stream_frame and pf_gen_crypto_frame must be adjacent so that
* they can be cast to an array.
*/
2017-09-22 21:00:03 +00:00
int
(*pf_gen_stream_frame) (unsigned char *buf, size_t bufsz,
lsquic_stream_id_t stream_id, uint64_t offset,
Latest changes - [API Change] lsquic_engine_connect() returns pointer to the connection object. - [API Change] Add lsquic_conn_get_engine() to get engine object from connection object. - [API Change] Add lsquic_conn_status() to query connection status. - [API Change] Add add lsquic_conn_set_ctx(). - [API Change] Add new timestamp format, e.g. 2017-03-21 13:43:46.671345 - [OPTIMIZATION] Process handshake STREAM frames as soon as packet arrives. - [OPTIMIZATION] Do not compile expensive send controller sanity check by default. - [OPTIMIZATION] Add fast path to gquic_be_gen_reg_pkt_header. - [OPTIMIZATION] Only make squeeze function call if necessary. - [OPTIMIZATION] Speed up Q039 ACK frame parsing. - [OPTIMIZATION] Fit most used elements of packet_out into first 64 bytes. - [OPTIMIZATION] Keep track of scheduled bytes instead of calculating. - [OPTIMIZATION] Prefetch next unacked packet when processing ACK. - [OPTIMIZATION] Leverage fact that ACK ranges and unacked list are. ordered. - [OPTIMIZATION] Reduce function pointer use for STREAM frame generation - Fix: reset incoming streams that arrive after we send GOAWAY. - Fix: delay client on_new_conn() call until connection is fully set up. - Fixes to buffered packets logic: splitting, STREAM frame elision. - Fix: do not dispatch on_write callback if no packets are available. - Fix WINDOW_UPDATE send and resend logic. - Fix STREAM frame extension code. - Fix: Drop unflushed data when stream is reset. - Switch to tracking CWND using bytes rather than packets. - Fix TCP friendly adjustment in cubic. - Fix: do not generate invalid STOP_WAITING frames during high packet loss. - Pacer fixes.
2018-02-26 21:01:16 +00:00
int fin, size_t size, gsf_read_f, void *stream);
/* The two "UNUSED" parameters are here so that it matches
* pf_gen_stream_frame.
*/
int
(*pf_gen_crypto_frame) (unsigned char *buf, size_t bufsz,
lsquic_stream_id_t UNUSED_1, uint64_t offset,
int UNUSED_2, size_t size, gsf_read_f, void *stream);
/* pf_parse_stream_frame and pf_parse_crypto_frame must be adjacent so that
* they can be cast to an array.
*/
2017-09-22 21:00:03 +00:00
int
(*pf_parse_stream_frame) (const unsigned char *buf, size_t rem_packet_sz,
struct stream_frame *);
int
(*pf_parse_crypto_frame) (const unsigned char *buf, size_t rem_packet_sz,
struct stream_frame *);
/* Return true if STREAM frame extends to the end of the packet and thus
* does not contain a Length field (no update).
*/
int
(*pf_dec_stream_frame_size) (unsigned char *buf, size_t new_size);
int
2017-09-22 21:00:03 +00:00
(*pf_parse_ack_frame) (const unsigned char *buf, size_t buf_len,
struct ack_info *ack_info, uint8_t exp);
2017-09-22 21:00:03 +00:00
int
(*pf_gen_ack_frame) (unsigned char *outbuf, size_t outbuf_sz,
gaf_rechist_first_f, gaf_rechist_next_f,
gaf_rechist_largest_recv_f, void *rechist, lsquic_time_t now,
int *has_missing, lsquic_packno_t *largest_received,
const uint64_t *ecn_counts);
2017-09-22 21:00:03 +00:00
int
(*pf_gen_stop_waiting_frame) (unsigned char *buf, size_t buf_len,
lsquic_packno_t cur_packno, enum packno_bits,
2017-09-22 21:00:03 +00:00
lsquic_packno_t least_unacked_packno);
int
(*pf_parse_stop_waiting_frame) (const unsigned char *buf, size_t buf_len,
lsquic_packno_t cur_packno, enum packno_bits,
2017-09-22 21:00:03 +00:00
lsquic_packno_t *least_unacked);
int
(*pf_skip_stop_waiting_frame) (size_t buf_len, enum packno_bits);
2017-09-22 21:00:03 +00:00
int
(*pf_gen_window_update_frame) (unsigned char *buf, int buf_len,
lsquic_stream_id_t stream_id, uint64_t offset);
2017-09-22 21:00:03 +00:00
int
(*pf_parse_window_update_frame) (const unsigned char *buf, size_t buf_len,
lsquic_stream_id_t *stream_id, uint64_t *offset);
/* The third argument for pf_gen_blocked_frame() and pf_parse_blocked_frame()
* is Stream ID for GQUIC and offset for IETF QUIC. Since both of these are
* uint64_t, we'll use the same function pointer. Just have to be a little
* careful here.
*/
2017-09-22 21:00:03 +00:00
int
(*pf_gen_blocked_frame) (unsigned char *buf, size_t buf_len,
lsquic_stream_id_t stream_id);
2017-09-22 21:00:03 +00:00
int
(*pf_parse_blocked_frame) (const unsigned char *buf, size_t buf_len,
/* TODO: rename third argument when dropping GQUIC */
lsquic_stream_id_t *stream_id);
unsigned
(*pf_blocked_frame_size) (uint64_t);
unsigned
(*pf_rst_frame_size) (lsquic_stream_id_t stream_id, uint64_t final_size,
uint64_t error_code);
2017-09-22 21:00:03 +00:00
int
(*pf_gen_rst_frame) (unsigned char *buf, size_t buf_len,
lsquic_stream_id_t stream_id, uint64_t offset, uint64_t error_code);
2017-09-22 21:00:03 +00:00
int
(*pf_parse_rst_frame) (const unsigned char *buf, size_t buf_len,
lsquic_stream_id_t *stream_id, uint64_t *offset, uint64_t *error_code);
int
(*pf_parse_stop_sending_frame) (const unsigned char *buf, size_t buf_len,
lsquic_stream_id_t *stream_id, uint64_t *error_code);
unsigned
(*pf_stop_sending_frame_size) (lsquic_stream_id_t, uint64_t);
int
(*pf_gen_stop_sending_frame) (unsigned char *buf, size_t buf_len,
lsquic_stream_id_t, uint64_t error_code);
size_t
(*pf_connect_close_frame_size) (int app_error, unsigned error_code,
unsigned frame_type, size_t reason_len);
2017-09-22 21:00:03 +00:00
int
(*pf_gen_connect_close_frame) (unsigned char *buf, size_t buf_len,
int app_error, unsigned error_code, const char *reason, int reason_len);
2017-09-22 21:00:03 +00:00
int
(*pf_parse_connect_close_frame) (const unsigned char *buf, size_t buf_len,
int *app_error, uint64_t *error_code, uint16_t *reason_length,
2017-09-22 21:00:03 +00:00
uint8_t *reason_offset);
int
(*pf_gen_goaway_frame) (unsigned char *buf, size_t buf_len,
uint32_t error_code, lsquic_stream_id_t last_good_stream_id,
2017-09-22 21:00:03 +00:00
const char *reason, size_t reason_len);
int
(*pf_parse_goaway_frame) (const unsigned char *buf, size_t buf_len,
uint32_t *error_code, lsquic_stream_id_t *last_good_stream_id,
2017-09-22 21:00:03 +00:00
uint16_t *reason_length, const char **reason);
int
(*pf_gen_ping_frame) (unsigned char *buf, int buf_len);
int
(*pf_parse_path_chal_frame) (const unsigned char *buf, size_t,
uint64_t *chal);
int
(*pf_parse_path_resp_frame) (const unsigned char *buf, size_t,
uint64_t *resp);
2017-09-22 21:00:03 +00:00
/* These float reading and writing functions assume `mem' has at least
* 2 bytes.
*/
void
(*pf_write_float_time16) (lsquic_time_t time_us, void *mem);
uint64_t
(*pf_read_float_time16) (const void *mem);
ssize_t
(*pf_generate_simple_prst) (const lsquic_cid_t *cid,
unsigned char *, size_t);
2017-09-22 21:00:03 +00:00
size_t
(*pf_calc_stream_frame_header_sz) (lsquic_stream_id_t stream_id,
uint64_t offset, unsigned data_sz);
size_t
(*pf_calc_crypto_frame_header_sz) (uint64_t offset, unsigned data_sz);
Latest changes - [API Change] Sendfile-like functionality is gone. The stream no longer opens files and deals with file descriptors. (Among other things, this makes the code more portable.) Three writing functions are provided: lsquic_stream_write lsquic_stream_writev lsquic_stream_writef (NEW) lsquic_stream_writef() is given an abstract reader that has function pointers for size() and read() functions which the user can implement. This is the most flexible way. lsquic_stream_write() and lsquic_stream_writev() are now both implemented as wrappers around lsquic_stream_writef(). - [OPTIMIZATION] When writing to stream, be it within or without the on_write() callback, place data directly into packet buffer, bypassing auxiliary data structures. This reduces amount of memory required, for the amount of data that can be written is limited by the congestion window. To support writes outside the on_write() callback, we keep N outgoing packet buffers per connection which can be written to by any stream. One half of these are reserved for the highest priority stream(s), the other half for all other streams. This way, low-priority streams cannot write instead of high-priority streams and, on the other hand, low-priority streams get a chance to send their packets out. The algorithm is as follows: - When user writes to stream outside of the callback: - If this is the highest priority stream, place it onto the reserved N/2 queue or fail. (The actual size of this queue is dynamic -- MAX(N/2, CWND) -- rather than N/2, allowing high-priority streams to write as much as can be sent.) - If the stream is not the highest priority, try to place the data onto the reserved N/2 queue or fail. - When tick occurs *and* more packets can be scheduled: - Transfer packets from the high N/2 queue to the scheduled queue. - If more scheduling is allowed: - Call on_write callbacks for highest-priority streams, placing resulting packets directly onto the scheduled queue. - If more scheduling is allowed: - Transfer packets from the low N/2 queue to the scheduled queue. - If more scheduling is allowed: - Call on_write callbacks for non-highest-priority streams, placing resulting packets directly onto the scheduled queue The number N is currently 20, but it could be varied based on resource usage. - If stream is created due to incoming headers, make headers readable from on_new. - Outgoing packets are no longer marked non-writeable to prevent placing more than one STREAM frame from the same stream into a single packet. This property is maintained via code flow and an explicit check. Packets for stream data are allocated using a special function. - STREAM frame elision is cheaper, as we only perform it if a reset stream has outgoing packets referencing it. - lsquic_packet_out_t is smaller, as stream_rec elements are now inside a union.
2017-10-31 13:35:58 +00:00
void
(*pf_turn_on_fin) (unsigned char *);
2018-08-15 19:06:31 +00:00
size_t
(*pf_packout_size) (const struct lsquic_conn *,
const struct lsquic_packet_out *);
/* This returns the high estimate of the header size. Note that it
* cannot account for the size of the token in the IETF QUIC Initial
* packets as it does not know it.
*/
2018-08-15 19:06:31 +00:00
size_t
(*pf_packout_max_header_size) (const struct lsquic_conn *,
enum packet_out_flags, size_t dcid_len, enum header_type);
enum packno_bits
(*pf_calc_packno_bits) (lsquic_packno_t packno,
lsquic_packno_t least_unacked, uint64_t n_in_flight);
unsigned
(*pf_packno_bits2len) (enum packno_bits);
int
(*pf_parse_max_data) (const unsigned char *, size_t, uint64_t *);
int
(*pf_gen_max_data_frame) (unsigned char *, size_t, uint64_t);
unsigned
(*pf_max_data_frame_size) (uint64_t);
/*
* Returns number of bytes parsed on success or negative value on error:
* -1 Out of input buffer
* -2 Invalid CID length value
*/
int
(*pf_parse_new_conn_id) (const unsigned char *, size_t, uint64_t *,
uint64_t *, lsquic_cid_t *, const unsigned char **);
unsigned
(*pf_stream_blocked_frame_size) (lsquic_stream_id_t, uint64_t);
int
(*pf_gen_stream_blocked_frame) (unsigned char *buf, size_t,
lsquic_stream_id_t, uint64_t);
int
(*pf_parse_stream_blocked_frame) (const unsigned char *buf, size_t,
lsquic_stream_id_t *, uint64_t *);
unsigned
(*pf_max_stream_data_frame_size) (lsquic_stream_id_t, uint64_t);
int
(*pf_gen_max_stream_data_frame) (unsigned char *buf, size_t,
lsquic_stream_id_t, uint64_t);
int
(*pf_parse_max_stream_data_frame) (const unsigned char *buf, size_t,
lsquic_stream_id_t *, uint64_t *);
int
(*pf_parse_new_token_frame) (const unsigned char *buf, size_t,
const unsigned char **token, size_t *token_size);
size_t
(*pf_new_connection_id_frame_size) (unsigned seqno, unsigned cid_len);
int
(*pf_gen_new_connection_id_frame) (unsigned char *buf, size_t,
unsigned seqno, const struct lsquic_cid *,
const unsigned char *token, size_t);
size_t
(*pf_retire_cid_frame_size) (uint64_t);
int
(*pf_gen_retire_cid_frame) (unsigned char *buf, size_t, uint64_t);
int
(*pf_parse_retire_cid_frame) (const unsigned char *buf, size_t, uint64_t *);
size_t
(*pf_new_token_frame_size) (size_t);
int
(*pf_gen_new_token_frame) (unsigned char *buf, size_t,
const unsigned char *token, size_t);
int
(*pf_gen_streams_blocked_frame) (unsigned char *buf, size_t buf_len,
enum stream_dir, uint64_t);
int
(*pf_parse_streams_blocked_frame) (const unsigned char *buf, size_t buf_len,
enum stream_dir *, uint64_t *);
unsigned
(*pf_streams_blocked_frame_size) (uint64_t);
int
(*pf_gen_max_streams_frame) (unsigned char *buf, size_t buf_len,
enum stream_dir, uint64_t);
int
(*pf_parse_max_streams_frame) (const unsigned char *buf, size_t buf_len,
enum stream_dir *, uint64_t *);
unsigned
(*pf_max_streams_frame_size) (uint64_t);
unsigned
(*pf_path_chal_frame_size) (void);
int
(*pf_gen_path_chal_frame) (unsigned char *, size_t, uint64_t chal);
unsigned
(*pf_path_resp_frame_size) (void);
int
(*pf_gen_path_resp_frame) (unsigned char *, size_t, uint64_t resp);
int
(*pf_gen_handshake_done_frame) (unsigned char *buf, size_t buf_len);
int
(*pf_parse_handshake_done_frame) (const unsigned char *buf, size_t buf_len);
unsigned
(*pf_handshake_done_frame_size) (void);
int
(*pf_gen_ack_frequency_frame) (unsigned char *buf, size_t buf_len,
uint64_t seqno, uint64_t pack_tol, uint64_t upd_mad, int ignore);
int
(*pf_parse_ack_frequency_frame) (const unsigned char *buf, size_t buf_len,
uint64_t *seqno, uint64_t *pack_tol, uint64_t *upd_mad, int *ignore);
unsigned
(*pf_ack_frequency_frame_size) (uint64_t seqno, uint64_t pack_tol,
uint64_t upd_mad /* Don't need to pass `ignore' */);
int
(*pf_gen_timestamp_frame) (unsigned char *buf, size_t buf_len, uint64_t);
int
(*pf_parse_timestamp_frame) (const unsigned char *buf, size_t, uint64_t *);
int
(*pf_parse_datagram_frame) (const unsigned char *buf, size_t, const void **,
size_t *);
int
(*pf_gen_datagram_frame) (unsigned char *, size_t bufsz, size_t min_sz,
size_t max_sz, ssize_t (*)(struct lsquic_conn *, void *, size_t),
struct lsquic_conn *);
unsigned
(*pf_datagram_frame_size) (size_t);
2017-09-22 21:00:03 +00:00
};
LSQUIC_EXTERN const struct parse_funcs lsquic_parse_funcs_gquic_Q043;
LSQUIC_EXTERN const struct parse_funcs lsquic_parse_funcs_gquic_Q046;
LSQUIC_EXTERN const struct parse_funcs lsquic_parse_funcs_gquic_Q050;
LSQUIC_EXTERN const struct parse_funcs lsquic_parse_funcs_ietf_v1;
2017-09-22 21:00:03 +00:00
#define select_pf_by_ver(ver) ( \
(1 << (ver)) & (1 << LSQVER_043) ? \
&lsquic_parse_funcs_gquic_Q043 : \
(1 << (ver)) & (1 << LSQVER_046) ? \
&lsquic_parse_funcs_gquic_Q046 : \
2021-06-02 04:39:15 +00:00
(1 << (ver)) & (1 << LSQVER_050) ? \
&lsquic_parse_funcs_gquic_Q050 : \
&lsquic_parse_funcs_ietf_v1)
2017-09-22 21:00:03 +00:00
/* This function is gQUIC-version independent */
2017-09-22 21:00:03 +00:00
int
2018-08-15 19:06:31 +00:00
lsquic_gquic_parse_packet_in_begin (struct lsquic_packet_in *, size_t length,
int is_server, unsigned cid_len, struct packin_parse_state *);
2017-09-22 21:00:03 +00:00
2018-08-15 19:06:31 +00:00
int
lsquic_Q046_parse_packet_in_short_begin (struct lsquic_packet_in *, size_t length,
int is_server, unsigned, struct packin_parse_state *);
2018-08-15 19:06:31 +00:00
int
lsquic_Q046_parse_packet_in_long_begin (struct lsquic_packet_in *, size_t length,
int is_server, unsigned, struct packin_parse_state *);
2018-08-15 19:06:31 +00:00
int
lsquic_Q050_parse_packet_in_long_begin (struct lsquic_packet_in *, size_t length,
int is_server, unsigned, struct packin_parse_state *);
enum quic_frame_type
lsquic_parse_frame_type_gquic_Q035_thru_Q046 (const unsigned char *, size_t);
2017-09-22 21:00:03 +00:00
extern const enum quic_frame_type lsquic_iquic_byte2type[0x40];
2017-09-22 21:00:03 +00:00
size_t
lsquic_calc_stream_frame_header_sz_gquic (lsquic_stream_id_t stream_id,
uint64_t offset, unsigned);
2017-09-22 21:00:03 +00:00
2018-08-15 19:06:31 +00:00
size_t
lsquic_gquic_packout_size (const struct lsquic_conn *,
const struct lsquic_packet_out *);
size_t
lsquic_gquic_packout_header_size (const struct lsquic_conn *conn,
enum packet_out_flags flags, size_t unused, enum header_type);
size_t
lsquic_gquic_po_header_sz (enum packet_out_flags flags);
size_t
lsquic_gquic_packout_size (const struct lsquic_conn *,
const struct lsquic_packet_out *);
2018-08-15 19:06:31 +00:00
size_t
lsquic_gquic_po_header_sz (enum packet_out_flags flags);
2017-09-22 21:00:03 +00:00
/* This maps two bits as follows:
* 00 -> 1
* 01 -> 2
* 10 -> 4
* 11 -> 6
*
* Assumes that only two low bits are set.
*/
#define twobit_to_1246(bits) ((bits) * 2 + !(bits))
/* This maps two bits as follows:
* 00 -> 1
* 01 -> 2
* 10 -> 4
* 11 -> 8
*
* Assumes that only two low bits are set.
*/
#define twobit_to_1248(bits) (1 << (bits))
#define ECN_COUNTS_STR " ECT(0): 01234567879012345678790;" \
" ECT(1): 01234567879012345678790;" \
" CE: 01234567879012345678790"
#define RANGES_TRUNCATED_STR " ranges truncated! "
#define MAX_ACKI_STR_SZ (256 * (3 /* [-] */ + 20 /* ~0ULL */ * 2) \
+ sizeof(ECN_COUNTS_STR) + sizeof(RANGES_TRUNCATED_STR))
void
lsquic_acki2str (const struct ack_info *acki, char *, size_t);
2017-09-22 21:00:03 +00:00
Latest changes - [API Change] Sendfile-like functionality is gone. The stream no longer opens files and deals with file descriptors. (Among other things, this makes the code more portable.) Three writing functions are provided: lsquic_stream_write lsquic_stream_writev lsquic_stream_writef (NEW) lsquic_stream_writef() is given an abstract reader that has function pointers for size() and read() functions which the user can implement. This is the most flexible way. lsquic_stream_write() and lsquic_stream_writev() are now both implemented as wrappers around lsquic_stream_writef(). - [OPTIMIZATION] When writing to stream, be it within or without the on_write() callback, place data directly into packet buffer, bypassing auxiliary data structures. This reduces amount of memory required, for the amount of data that can be written is limited by the congestion window. To support writes outside the on_write() callback, we keep N outgoing packet buffers per connection which can be written to by any stream. One half of these are reserved for the highest priority stream(s), the other half for all other streams. This way, low-priority streams cannot write instead of high-priority streams and, on the other hand, low-priority streams get a chance to send their packets out. The algorithm is as follows: - When user writes to stream outside of the callback: - If this is the highest priority stream, place it onto the reserved N/2 queue or fail. (The actual size of this queue is dynamic -- MAX(N/2, CWND) -- rather than N/2, allowing high-priority streams to write as much as can be sent.) - If the stream is not the highest priority, try to place the data onto the reserved N/2 queue or fail. - When tick occurs *and* more packets can be scheduled: - Transfer packets from the high N/2 queue to the scheduled queue. - If more scheduling is allowed: - Call on_write callbacks for highest-priority streams, placing resulting packets directly onto the scheduled queue. - If more scheduling is allowed: - Transfer packets from the low N/2 queue to the scheduled queue. - If more scheduling is allowed: - Call on_write callbacks for non-highest-priority streams, placing resulting packets directly onto the scheduled queue The number N is currently 20, but it could be varied based on resource usage. - If stream is created due to incoming headers, make headers readable from on_new. - Outgoing packets are no longer marked non-writeable to prevent placing more than one STREAM frame from the same stream into a single packet. This property is maintained via code flow and an explicit check. Packets for stream data are allocated using a special function. - STREAM frame elision is cheaper, as we only perform it if a reset stream has outgoing packets referencing it. - lsquic_packet_out_t is smaller, as stream_rec elements are now inside a union.
2017-10-31 13:35:58 +00:00
void
lsquic_turn_on_fin_Q035_thru_Q046 (unsigned char *);
Latest changes - [API Change] Sendfile-like functionality is gone. The stream no longer opens files and deals with file descriptors. (Among other things, this makes the code more portable.) Three writing functions are provided: lsquic_stream_write lsquic_stream_writev lsquic_stream_writef (NEW) lsquic_stream_writef() is given an abstract reader that has function pointers for size() and read() functions which the user can implement. This is the most flexible way. lsquic_stream_write() and lsquic_stream_writev() are now both implemented as wrappers around lsquic_stream_writef(). - [OPTIMIZATION] When writing to stream, be it within or without the on_write() callback, place data directly into packet buffer, bypassing auxiliary data structures. This reduces amount of memory required, for the amount of data that can be written is limited by the congestion window. To support writes outside the on_write() callback, we keep N outgoing packet buffers per connection which can be written to by any stream. One half of these are reserved for the highest priority stream(s), the other half for all other streams. This way, low-priority streams cannot write instead of high-priority streams and, on the other hand, low-priority streams get a chance to send their packets out. The algorithm is as follows: - When user writes to stream outside of the callback: - If this is the highest priority stream, place it onto the reserved N/2 queue or fail. (The actual size of this queue is dynamic -- MAX(N/2, CWND) -- rather than N/2, allowing high-priority streams to write as much as can be sent.) - If the stream is not the highest priority, try to place the data onto the reserved N/2 queue or fail. - When tick occurs *and* more packets can be scheduled: - Transfer packets from the high N/2 queue to the scheduled queue. - If more scheduling is allowed: - Call on_write callbacks for highest-priority streams, placing resulting packets directly onto the scheduled queue. - If more scheduling is allowed: - Transfer packets from the low N/2 queue to the scheduled queue. - If more scheduling is allowed: - Call on_write callbacks for non-highest-priority streams, placing resulting packets directly onto the scheduled queue The number N is currently 20, but it could be varied based on resource usage. - If stream is created due to incoming headers, make headers readable from on_new. - Outgoing packets are no longer marked non-writeable to prevent placing more than one STREAM frame from the same stream into a single packet. This property is maintained via code flow and an explicit check. Packets for stream data are allocated using a special function. - STREAM frame elision is cheaper, as we only perform it if a reset stream has outgoing packets referencing it. - lsquic_packet_out_t is smaller, as stream_rec elements are now inside a union.
2017-10-31 13:35:58 +00:00
enum packno_bits
lsquic_gquic_calc_packno_bits (lsquic_packno_t packno,
lsquic_packno_t least_unacked, uint64_t n_in_flight);
unsigned
lsquic_gquic_packno_bits2len (enum packno_bits);
int
lsquic_merge_acks (struct ack_info *dst, const struct ack_info *src);
2017-09-22 21:00:03 +00:00
#endif