Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/picoquic/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
hfstco committed Aug 4, 2024
2 parents c057203 + 031b880 commit 2b14247
Show file tree
Hide file tree
Showing 20 changed files with 550 additions and 272 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ else()
endif()

project(picoquic
VERSION 1.1.21.6
VERSION 1.1.21.8
DESCRIPTION "picoquic library"
LANGUAGES C CXX)

Expand Down
6 changes: 6 additions & 0 deletions UnitTest1/unittest1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2471,6 +2471,12 @@ namespace UnitTest1
Assert::AreEqual(ret, 0);
}

TEST_METHOD(multipath_ab1) {
int ret = multipath_ab1_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(multipath_sat_plus) {
int ret = multipath_sat_plus_test();

Expand Down
81 changes: 12 additions & 69 deletions picoquic/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,80 +95,14 @@ static option_table_line_t option_table[] = {
{ picoquic_option_No_GSO, '0', "no_gso", 0, "", "Do not use UDP GSO or equivalent" },
{ picoquic_option_BDP_frame, 'j', "bdp", 1, "number", "use bdp extension frame(1) or don\'t (0). Default=0" },
{ picoquic_option_CWIN_MAX, 'W', "cwin_max", 1, "bytes", "Max value for CWIN. Default=UINT64_MAX"},
#ifndef PICOQUIC_WITHOUT_SSLKEYLOG
{ picoquic_option_SSLKEYLOG, '8', "sslkeylog", 0, "", "Enable SSLKEYLOG" },
#endif
{ picoquic_option_HELP, 'h', "help", 0, "", "This help message" }
};

static size_t option_table_size = sizeof(option_table) / sizeof(option_table_line_t);

#if 0
/* Not in use and not tests. Reevaluate if we use files of parameters */
static int skip_spaces(const char* line, int offset)
{
int c;

while ((c = line[offset]) != 0) {
if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
offset++;
}
else {
break;
}
}
return offset;
}

static int skip_name(const char* line, int offset)
{
int c;

while ((c = line[offset]) != 0) {
if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == ':' || c == '#') {
break;
}
else {
offset++;
}
}
return offset;
}

static int parse_line_params(const char* line, int offset, option_param_t* params, int params_max, int* nb_params)
{
int nb_found = 0;

offset = skip_spaces(line, offset);
if (line[offset] == ':') {
while (nb_found < params_max) {
int offset_start;
offset_start = skip_spaces(line, offset);
offset = skip_name(line, offset);
if (offset == offset_start) {
/* Nothing there. */
break;
}
else {
params[nb_found].param = line + offset_start;
params[nb_found].length = offset - offset_start;
nb_found++;
}
}
}
*nb_params = nb_found;
return offset;
}

static int compare_option_name(const char * line, int offset, size_t length, char const* option_name)
{
int ret = -1;

if (length == strlen(option_name)) {
ret = strncmp(option_name, line + offset, length);
}

return ret;
}
#endif

static uint32_t config_parse_target_version(char const* v_arg)
{
/* Expect the version to be encoded in base 16 */
Expand Down Expand Up @@ -345,6 +279,11 @@ static int config_set_option(option_table_line_t* option_desc, option_param_t* p
case picoquic_option_DisablePortBlocking:
config->disable_port_blocking = 1;
break;
#ifndef PICOQUIC_WITHOUT_SSLKEYLOG
case picoquic_option_SSLKEYLOG:
config->enable_sslkeylog = 1;
break;
#endif
case picoquic_option_SOLUTION_DIR:
ret = config_set_string_param(&config->solution_dir, params, nb_params, 0);
break;
Expand Down Expand Up @@ -815,6 +754,10 @@ picoquic_quic_t* picoquic_create_and_configure(picoquic_quic_config_t* config,

picoquic_disable_port_blocking(quic, config->disable_port_blocking);

#ifndef PICOQUIC_WITHOUT_SSLKEYLOG
picoquic_enable_sslkeylog(quic, config->enable_sslkeylog);
#endif

if (config->initial_random >= 0 && config->initial_random <= 2) {
picoquic_set_random_initial(quic, config->initial_random);
}
Expand Down
150 changes: 116 additions & 34 deletions picoquic/frames.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,8 @@ int picoquic_queue_retire_connection_id_frame(picoquic_cnx_t * cnx, uint64_t uni
&more_data, &is_pure_ack, cnx->is_multipath_enabled, unique_path_id, sequence);

if ((consumed = bytes_next - frame_buffer) > 0) {
ret = picoquic_queue_misc_frame(cnx, frame_buffer, consumed, is_pure_ack);
ret = picoquic_queue_misc_frame(cnx, frame_buffer, consumed, is_pure_ack,
picoquic_packet_context_application);
}

return ret;
Expand Down Expand Up @@ -798,7 +799,8 @@ int picoquic_queue_new_token_frame(picoquic_cnx_t * cnx, uint8_t * token, size_t
uint8_t* bytes = picoquic_format_new_token_frame(frame_buffer, frame_buffer + sizeof(frame_buffer), &more_data, &is_pure_ack, token, token_length);

if (bytes > frame_buffer) {
ret = picoquic_queue_misc_frame(cnx, frame_buffer, bytes - frame_buffer, 1);
ret = picoquic_queue_misc_frame(cnx, frame_buffer, bytes - frame_buffer, 1,
picoquic_packet_context_application);
}

return ret;
Expand Down Expand Up @@ -4441,31 +4443,68 @@ int picoquic_check_max_streams_frame_needs_repeat(picoquic_cnx_t* cnx, const uin
/* Common code for datagrams and misc frames
*/

uint8_t * picoquic_format_first_misc_or_dg_frame(uint8_t* bytes, uint8_t * bytes_max, int * more_data, int * is_pure_ack,
uint8_t * picoquic_format_first_misc_or_dg_frame(uint8_t* bytes, uint8_t * bytes_max,
int * more_data, int * is_pure_ack, picoquic_misc_frame_header_t* misc_frame,
picoquic_misc_frame_header_t** first, picoquic_misc_frame_header_t** last)
{
picoquic_misc_frame_header_t* misc_frame = *first;

if (bytes + misc_frame->length > bytes_max) {
*more_data = 1;
} else {
uint8_t* frame = ((uint8_t*)misc_frame) + sizeof(picoquic_misc_frame_header_t);
memcpy(bytes, frame, misc_frame->length);
bytes += misc_frame->length;
*is_pure_ack &= misc_frame->is_pure_ack;
picoquic_delete_misc_or_dg(first, last, *first);
picoquic_delete_misc_or_dg(first, last, misc_frame);
}

return bytes;
}

/* Check whether miscellaneous frames are ready in packet context
*/
picoquic_misc_frame_header_t* picoquic_find_first_misc_frame(picoquic_cnx_t* cnx, picoquic_packet_context_enum pc)
{
picoquic_misc_frame_header_t* misc_frame = cnx->first_misc_frame;

while (misc_frame != NULL && misc_frame->pc != pc) {
misc_frame = misc_frame->next_misc_frame;
}
return misc_frame;
}

/*
* Sending of miscellaneous frames
*/

uint8_t* picoquic_format_first_misc_frame(picoquic_cnx_t* cnx, uint8_t* bytes, uint8_t* bytes_max, int* more_data, int* is_pure_ack)
{
return picoquic_format_first_misc_or_dg_frame(bytes, bytes_max, more_data, is_pure_ack, &cnx->first_misc_frame, &cnx->last_misc_frame);
return picoquic_format_first_misc_or_dg_frame(bytes, bytes_max, more_data, is_pure_ack, cnx->first_misc_frame, &cnx->first_misc_frame, &cnx->last_misc_frame);
}

/*
* Sending of miscellaneous frames in context
*/

uint8_t* picoquic_format_misc_frames_in_context(picoquic_cnx_t* cnx, uint8_t* bytes, uint8_t* bytes_max,
int* more_data, int* is_pure_ack, picoquic_packet_context_enum pc)
{
picoquic_misc_frame_header_t* misc_frame;
/* If present, send misc frame */
while ((misc_frame = picoquic_find_first_misc_frame(cnx, pc)) != NULL) {
uint8_t* bytes_misc = bytes;
int frame_is_pure_ack = misc_frame->is_pure_ack;

bytes = picoquic_format_first_misc_or_dg_frame(bytes, bytes_max, more_data, is_pure_ack,
misc_frame, &cnx->first_misc_frame, &cnx->last_misc_frame);
if (bytes <= bytes_misc) {
break;
}
else {
*is_pure_ack &= frame_is_pure_ack;
}
}

return bytes;
}

/*
Expand Down Expand Up @@ -4727,7 +4766,7 @@ int picoquic_queue_handshake_done_frame(picoquic_cnx_t* cnx)
uint8_t frame_buffer = picoquic_frame_type_handshake_done;

return picoquic_queue_misc_or_dg_frame(cnx, &cnx->first_datagram, &cnx->last_datagram,
&frame_buffer, 1, 0);
&frame_buffer, 1, 0, picoquic_packet_context_application);
}

/* Handling of datagram frames.
Expand Down Expand Up @@ -4853,7 +4892,7 @@ int picoquic_queue_datagram_frame(picoquic_cnx_t * cnx, size_t length, const uin

if ((consumed = bytes_next - frame_buffer) > 0) {
ret = picoquic_queue_misc_or_dg_frame(cnx, &cnx->first_datagram, &cnx->last_datagram,
frame_buffer, consumed, 0);
frame_buffer, consumed, 0, picoquic_packet_context_application);
}
else {
ret = PICOQUIC_ERROR_FRAME_BUFFER_TOO_SMALL;
Expand All @@ -4870,7 +4909,7 @@ uint8_t * picoquic_format_first_datagram_frame(picoquic_cnx_t* cnx, uint8_t* byt
}
else {
bytes = picoquic_format_first_misc_or_dg_frame(bytes, bytes_max, more_data, is_pure_ack,
&cnx->first_datagram, &cnx->last_datagram);
cnx->first_datagram, &cnx->first_datagram, &cnx->last_datagram);
}

return bytes;
Expand Down Expand Up @@ -5254,9 +5293,9 @@ const uint8_t* picoquic_parse_path_abandon_frame(const uint8_t* bytes, const uin
}

const uint8_t* picoquic_decode_path_abandon_frame(const uint8_t* bytes, const uint8_t* bytes_max,
picoquic_cnx_t* cnx,uint64_t current_time)
picoquic_cnx_t* cnx, uint64_t current_time)
{
uint64_t path_id;
uint64_t unique_path_id;
uint64_t reason = 0;

/* This code assumes that the frame type is already skipped */
Expand All @@ -5266,36 +5305,60 @@ const uint8_t* picoquic_decode_path_abandon_frame(const uint8_t* bytes, const ui
picoquic_connection_error_ex(cnx, PICOQUIC_TRANSPORT_FRAME_FORMAT_ERROR,
picoquic_frame_type_path_abandon, "multipath not negotiated");
}
else if ((bytes = picoquic_parse_path_abandon_frame(bytes, bytes_max, &path_id, &reason)) != NULL) {
else if ((bytes = picoquic_parse_path_abandon_frame(bytes, bytes_max, &unique_path_id, &reason)) == NULL) {
/* Bad frame encoding */
picoquic_connection_error_ex(cnx, PICOQUIC_TRANSPORT_FRAME_FORMAT_ERROR,
picoquic_frame_type_path_abandon, "bad abandon frame");
}
else if (unique_path_id > cnx->max_path_id_local) {
/* Invalid path ID */
picoquic_connection_error_ex(cnx, PICOQUIC_TRANSPORT_PROTOCOL_VIOLATION,
picoquic_frame_type_path_abandon, "Path ID over limit");
bytes = NULL;
}
else {
/* process the abandon frame */
int path_number = (cnx->is_multipath_enabled)?
picoquic_find_path_by_unique_id(cnx, path_id):
picoquic_find_path_by_cnxid_id(cnx, 1, path_id);
if (path_number < 0) {
/* Invalid path ID. Just ignore this frame. Add line in log for debug */
picoquic_log_app_message(cnx, "Ignore abandon path with invalid ID: %" PRIu64,
path_id);
}
else if (cnx->path[path_number]->path_is_demoted) {
if (!cnx->path[path_number]->path_abandon_received) {
cnx->path[path_number]->path_abandon_received = 1;
int path_index = picoquic_find_path_by_unique_id(cnx, unique_path_id);
if (path_index >= 0) {
if (!cnx->path[path_index]->path_is_demoted) {
/* The peer is asking to abandon an existing path */
cnx->path[path_index]->path_abandon_received = 1;
picoquic_demote_path(cnx, path_index, current_time, 0, NULL);
}
else if (!cnx->path[path_index]->path_abandon_received) {
cnx->path[path_index]->path_abandon_received = 1;
}
else {
/* Already abandoned... */
picoquic_log_app_message(cnx, "Ignore redundant abandon path with ID: %" PRIu64,
path_id);
unique_path_id);
}
}
else {
cnx->path[path_number]->path_abandon_received = 1;
picoquic_demote_path(cnx, path_number, current_time, 0, NULL);
/* The path is either not created yet or already deleted. This is not an
* error because the path ID is valid. We may need to delete the
* stash of CID, send an Abandon frame, etc. */
picoquic_local_cnxid_list_t* local_cnxid_list =
picoquic_find_or_create_local_cnxid_list(cnx, unique_path_id, 0);
if (local_cnxid_list == NULL) {
/* Already deleted. Add line in log for debug */
picoquic_log_app_message(cnx, "Ignore abandon path with deleted ID: %" PRIu64,
unique_path_id);
}
else {
if (!local_cnxid_list->is_demoted) {
/* Do the demotion work of a local cnxid. */
if (picoquic_demote_local_cnxid_list(cnx, unique_path_id,
0, "Abandoned by peer", current_time) != 0) {
/* Sorry, this is a local error */
bytes = NULL;
}
}
/* The path id was demoted. We can clear the list of local ID */
picoquic_delete_local_cnxid_list(cnx, local_cnxid_list);
}
}
}
else {
/* Bad frame encoding */
picoquic_connection_error_ex(cnx, PICOQUIC_TRANSPORT_FRAME_FORMAT_ERROR,
picoquic_frame_type_path_abandon, "bad abandon frame");
}
return bytes;
}

Expand All @@ -5315,6 +5378,23 @@ uint8_t* picoquic_format_path_abandon_frame(uint8_t* bytes, uint8_t* bytes_max,
return bytes;
}

int picoquic_queue_path_abandon_frame(picoquic_cnx_t* cnx,
uint64_t unique_path_id, uint64_t reason, char const* phrase)
{
int ret = 0;
uint8_t buffer[512];
uint8_t* end_bytes;
int more_data = 0;
end_bytes = picoquic_format_path_abandon_frame(buffer, buffer + sizeof(buffer), &more_data,
unique_path_id, reason, phrase);
if (end_bytes == NULL ||
picoquic_queue_misc_frame(cnx, buffer, end_bytes - buffer, 0,
picoquic_packet_context_application) != 0) {
/* Could not format or could not queue. Internal error. */
ret = -1;
}
return ret;
}

/* Multipath PATH SNADBY and AVAILABLE frames
*/
Expand Down Expand Up @@ -5350,7 +5430,8 @@ int picoquic_queue_path_available_or_standby_frame(
uint8_t* bytes_next = picoquic_format_path_available_or_standby_frame(
frame_buffer, frame_buffer + sizeof(frame_buffer), frame_type, path_id, sequence);
size_t consumed = bytes_next - frame_buffer;
ret = picoquic_queue_misc_frame(cnx, frame_buffer, consumed, is_pure_ack);
ret = picoquic_queue_misc_frame(cnx, frame_buffer, consumed, is_pure_ack,
picoquic_packet_context_application);
if (ret == 0) {
path_x->status_sequence_sent_last = sequence;
}
Expand Down Expand Up @@ -5470,7 +5551,8 @@ int picoquic_queue_max_path_id_frame(
uint8_t* bytes_next = picoquic_format_max_path_id_frame(
frame_buffer, frame_buffer + sizeof(frame_buffer), cnx->max_path_id_local);
size_t consumed = bytes_next - frame_buffer;
ret = picoquic_queue_misc_frame(cnx, frame_buffer, consumed, is_pure_ack);
ret = picoquic_queue_misc_frame(cnx, frame_buffer, consumed, is_pure_ack,
picoquic_packet_context_application);
return ret;
}

Expand Down
Loading

0 comments on commit 2b14247

Please sign in to comment.