Skip to content

Commit

Permalink
implement codec for PATH_ABANDON and PATH_STATUS though they are not …
Browse files Browse the repository at this point in the history
…used as they are advisory and still ambiguity in spec
  • Loading branch information
kazuho committed Sep 19, 2023
1 parent cf8a788 commit 4432722
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 7 deletions.
2 changes: 1 addition & 1 deletion include/quicly.h
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ struct st_quicly_conn_streamgroup_state_t {
uint64_t padding, ping, ack, reset_stream, stop_sending, crypto, new_token, stream, max_data, max_stream_data, \
max_streams_bidi, max_streams_uni, data_blocked, stream_data_blocked, streams_blocked, new_connection_id, \
retire_connection_id, path_challenge, path_response, transport_close, application_close, handshake_done, datagram, \
ack_frequency, ack_mp; \
ack_frequency, ack_mp, path_abandon, path_status; \
} num_frames_sent, num_frames_received; \
/** \
* Total number of PTOs observed during the connection. \
Expand Down
94 changes: 88 additions & 6 deletions include/quicly/frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ extern "C" {
#define QUICLY_FRAME_TYPE_ACK_FREQUENCY 0xaf
#define QUICLY_FRAME_TYPE_ACK_MP 0x15228c00
#define QUICLY_FRAME_TYPE_ACK_MP_ECN 0x15228c01
#define QUICLY_FRAME_TYPE_PATH_ABANDON 0x15228c05
#define QUICLY_FRAME_TYPE_PATH_STATUS 0x15228c06

#define QUICLY_FRAME_TYPE_STREAM_BITS 0x7
#define QUICLY_FRAME_TYPE_STREAM_BIT_OFF 0x4
Expand All @@ -82,6 +84,7 @@ extern "C" {
#define QUICLY_ACK_MP_FRAME_CAPACITY (4 + 8 + 8 + 8 + 1)
#define QUICLY_PATH_CHALLENGE_FRAME_CAPACITY (1 + 8)
#define QUICLY_STREAM_FRAME_CAPACITY (1 + 8 + 8 + 1)
#define QUICLY_PATH_STATUS_FRAME_CAPACITY (4 + 8 + 8 + 1)

/**
* maximum number of ACK blocks (inclusive)
Expand All @@ -101,6 +104,8 @@ static size_t quicly_encodev_capacity(uint64_t v);
static unsigned quicly_clz32(uint32_t v);
static unsigned quicly_clz64(uint64_t v);

static ptls_iovec_t quicly__frame_decode_length_value_pair(const uint8_t **src, const uint8_t *end);

typedef struct st_quicly_stream_frame_t {
uint64_t stream_id;
unsigned is_fin : 1;
Expand Down Expand Up @@ -287,6 +292,23 @@ static uint8_t *quicly_encode_ack_frequency_frame(uint8_t *dst, uint64_t sequenc
uint64_t max_ack_delay, int ignore_order);
static int quicly_decode_ack_frequency_frame(const uint8_t **src, const uint8_t *end, quicly_ack_frequency_frame_t *frame);

typedef struct st_quicly_path_abandon_frame_t {
uint64_t dcid;
uint64_t error_code;
ptls_iovec_t reason_phrase;
} quicly_path_abandon_frame_t;

static int quicly_decode_path_abandon_frame(const uint8_t **src, const uint8_t *end, quicly_path_abandon_frame_t *frame);

typedef struct st_quicly_path_status_frame_t {
uint64_t dcid;
uint64_t sequence;
uint8_t available : 1;
} quicly_path_status_frame_t;

static uint8_t *quicly_encode_path_status_frame(uint8_t *dst, uint64_t dcid, uint64_t sequence, int available);
static int quicly_decode_path_status_frame(const uint8_t **src, const uint8_t *end, quicly_path_status_frame_t *frame);

/* inline definitions */

inline uint16_t quicly_decode16(const uint8_t **src)
Expand Down Expand Up @@ -347,6 +369,22 @@ inline uint8_t *quicly_encode64(uint8_t *p, uint64_t v)
return p;
}

inline ptls_iovec_t quicly__frame_decode_length_value_pair(const uint8_t **src, const uint8_t *end)
{
ptls_iovec_t vec;
uint64_t len;

if ((len = quicly_decodev(src, end)) == UINT64_MAX)
goto Fail;
if ((uint64_t)(end - *src) < len)
goto Fail;
vec = ptls_iovec_init(*src, len);
*src += len;
return vec;
Fail:
return ptls_iovec_init(NULL, 0);
}

inline size_t quicly_encodev_capacity(uint64_t v)
{
if (v > 63) {
Expand Down Expand Up @@ -497,19 +535,15 @@ inline int quicly_decode_application_close_frame(const uint8_t **src, const uint

inline int quicly_decode_transport_close_frame(const uint8_t **src, const uint8_t *end, quicly_transport_close_frame_t *frame)
{
uint64_t error_code, reason_len;
uint64_t error_code;

if ((error_code = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
frame->error_code = (uint16_t)error_code;
if ((frame->frame_type = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
if ((reason_len = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
if ((uint64_t)(end - *src) < reason_len)
if ((frame->reason_phrase = quicly__frame_decode_length_value_pair(src, end)).base == NULL)
goto Error;
frame->reason_phrase = ptls_iovec_init(*src, reason_len);
*src += reason_len;
return 0;
Error:
return QUICLY_TRANSPORT_ERROR_FRAME_ENCODING;
Expand Down Expand Up @@ -830,6 +864,54 @@ inline int quicly_decode_ack_frequency_frame(const uint8_t **src, const uint8_t
return QUICLY_TRANSPORT_ERROR_FRAME_ENCODING;
}

inline int quicly_decode_path_abandon_frame(const uint8_t **src, const uint8_t *end, quicly_path_abandon_frame_t *frame)
{
if ((frame->dcid = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
if ((frame->error_code = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
if ((frame->reason_phrase = quicly__frame_decode_length_value_pair(src, end)).base == NULL)
goto Error;
return 0;
Error:
return QUICLY_TRANSPORT_ERROR_FRAME_ENCODING;
}

inline uint8_t *quicly_encode_path_status_frame(uint8_t *dst, uint64_t dcid, uint64_t sequence, int available)
{
PTLS_BUILD_ASSERT(QUICLY_FRAME_TYPE_PATH_STATUS < 0x40000000 && "othewise adjust frame capacity");
dst = quicly_encodev(dst, QUICLY_FRAME_TYPE_PATH_STATUS);
dst = quicly_encodev(dst, dcid);
dst = quicly_encodev(dst, sequence);
*dst++ = available ? 2 : 1;
return dst;
}

inline int quicly_decode_path_status_frame(const uint8_t **src, const uint8_t *end, quicly_path_status_frame_t *frame)
{
uint64_t status;

if ((frame->dcid = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
if ((frame->sequence = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
if ((status = quicly_decodev(src, end)) == UINT64_MAX)
goto Error;
switch (status) {
case 1:
frame->available = 0;
break;
case 2:
frame->available = 1;
break;
default:
goto Error;
}
return 0;
Error:
return QUICLY_TRANSPORT_ERROR_FRAME_ENCODING;
}

#ifdef __cplusplus
}
#endif
Expand Down
49 changes: 49 additions & 0 deletions lib/quicly.c
Original file line number Diff line number Diff line change
Expand Up @@ -6618,6 +6618,53 @@ static int handle_ack_frequency_frame(quicly_conn_t *conn, struct st_quicly_hand
return 0;
}

static int handle_path_abandon_frame(quicly_conn_t *conn, struct st_quicly_handle_payload_state_t *state)
{
quicly_path_abandon_frame_t frame;
int ret;

if (!quicly_is_multipath(conn))
return QUICLY_TRANSPORT_ERROR_FRAME_ENCODING;

if ((ret = quicly_decode_path_abandon_frame(&state->src, state->end, &frame)) != 0)
return ret;

QUICLY_PROBE(PATH_ABANDON_RECEIVE, conn, conn->stash.now, frame.dcid, frame.error_code,
QUICLY_PROBE_ESCAPE_UNSAFE_STRING(frame.reason_phrase.base, frame.reason_phrase.len));
QUICLY_LOG_CONN(path_abandon_receive, conn, {
PTLS_LOG_ELEMENT_UNSIGNED(dcid, frame.dcid);
PTLS_LOG_ELEMENT_UNSIGNED(error_code, frame.error_code);
PTLS_LOG_ELEMENT_UNSAFESTR(reason_phrase, (const char *)frame.reason_phrase.base, frame.reason_phrase.len);
});

/* TODO handle the frame */

return 0;
}

static int handle_path_status_frame(quicly_conn_t *conn, struct st_quicly_handle_payload_state_t *state)
{
quicly_path_status_frame_t frame;
int ret;

if (!quicly_is_multipath(conn))
return QUICLY_TRANSPORT_ERROR_FRAME_ENCODING;

if ((ret = quicly_decode_path_status_frame(&state->src, state->end, &frame)) != 0)
return ret;

QUICLY_PROBE(PATH_STATUS_RECEIVE, conn, conn->stash.now, frame.dcid, frame.sequence, frame.available ? 2 : 1);
QUICLY_LOG_CONN(path_status_receive, conn, {
PTLS_LOG_ELEMENT_UNSIGNED(dcid, frame.dcid);
PTLS_LOG_ELEMENT_UNSIGNED(sequence, frame.sequence);
PTLS_LOG_ELEMENT_UNSIGNED(available, frame.available ? 2 : 1);
});

/* TODO handle the frame */

return 0;
}

static int handle_payload(quicly_conn_t *conn, size_t epoch, size_t path_index, struct st_quicly_pn_space_t *pn_space,
const uint8_t *_src, size_t _len, uint64_t *offending_frame_type, int *is_ack_only, int *is_probe_only)
{
Expand Down Expand Up @@ -6702,6 +6749,8 @@ static int handle_payload(quicly_conn_t *conn, size_t epoch, size_t path_index,
FRAME( DATAGRAM_WITHLEN , datagram , 0 , 1, 0, 1 , 1 , 0 ),
FRAME( ACK_FREQUENCY , ack_frequency , 0 , 0 , 0 , 1 , 1 , 0 ),
FRAME( ACK_MP , ack_mp , 0 , 0 , 0 , 1 , 0 , 0 ),
FRAME( PATH_ABANDON , path_abandon , 0 , 0 , 0 , 1 , 1 , 0 ),
FRAME( PATH_STATUS , path_status , 0 , 0 , 0 , 1 , 1 , 0 ),
/* +------------------+---------------+-------------------+---------------+---------+ */
#undef FRAME
{UINT64_MAX},
Expand Down
6 changes: 6 additions & 0 deletions quicly-probes.d
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ provider quicly {
const void *src, size_t src_len);
probe stream_on_receive_reset(struct st_quicly_conn_t *conn, int64_t at, struct st_quicly_stream_t *stream, int err);

probe path_abandon_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t dcid, uint64_t error_code,
const char *reason_phrase);

probe path_status_send(struct st_quicly_conn_t *conn, int64_t at, uint64_t dcid, uint64_t sequence, uint64_t status);
probe path_status_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t dcid, uint64_t sequence, uint64_t status);

probe debug_message(struct st_quicly_conn_t *conn, const char *function, int line, const char *message);

probe conn_stats(struct st_quicly_conn_t *conn, int64_t at, struct st_quicly_stats_t *stats, size_t size);
Expand Down

0 comments on commit 4432722

Please sign in to comment.