Skip to content

Commit

Permalink
Merge pull request #770 from private-octopus/fifo-not-lifo
Browse files Browse the repository at this point in the history
Fifo not lifo
  • Loading branch information
huitema committed Jan 17, 2020
2 parents 9784916 + 4fda2a4 commit a66a5d0
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 92 deletions.
Binary file added UpgradeLog.htm
Binary file not shown.
128 changes: 83 additions & 45 deletions picohttp/demoserver.c
Expand Up @@ -23,28 +23,92 @@
#include <string.h>
#include <stdio.h>
#include <picotls.h>
#include "picosplay.h"
#include "picoquic_internal.h"
#include "tls_api.h"
#include "h3zero.h"
#include "democlient.h"
#include "demoserver.h"
#include "siduck.h"

/* Stream context splay management */

static int64_t picohttp_stream_node_compare(void *l, void *r)
{
/* Stream values are from 0 to 2^62-1, which means we are not worried with rollover */
return ((picohttp_server_stream_ctx_t*)l)->stream_id - ((picohttp_server_stream_ctx_t*)r)->stream_id;
}

static picosplay_node_t * picohttp_stream_node_create(void * value)
{
return &((picohttp_server_stream_ctx_t *)value)->http_stream_node;
}


static void * picohttp_stream_node_value(picosplay_node_t * node)
{
return (void*)((char*)node - offsetof(struct st_picohttp_server_stream_ctx_t, http_stream_node));
}

static void picohttp_clear_stream_ctx(picohttp_server_stream_ctx_t* stream_ctx)
{
if (stream_ctx->F != NULL) {
stream_ctx->F = picoquic_file_close(stream_ctx->F);
}

if (stream_ctx->path_callback != NULL) {
(void)stream_ctx->path_callback(NULL, NULL, 0, picohttp_callback_reset, stream_ctx);
}

if (stream_ctx->is_h3) {
h3zero_delete_data_stream_state(&stream_ctx->ps.stream_state);
}
else {
if (stream_ctx->ps.hq.path != NULL) {
free(stream_ctx->ps.hq.path);
}
}
}

static void picohttp_stream_node_delete(void * tree, picosplay_node_t * node)
{
picohttp_server_stream_ctx_t * stream_ctx = picohttp_stream_node_value(node);

picohttp_clear_stream_ctx(stream_ctx);

free(stream_ctx);
}

void picohttp_delete_stream(picosplay_tree_t * http_stream_tree, picohttp_server_stream_ctx_t* stream)
{
picosplay_delete(http_stream_tree, &stream->http_stream_node);
}

static picohttp_server_stream_ctx_t* picohttp_find_stream(picosplay_tree_t * stream_tree, uint64_t stream_id)
{
picohttp_server_stream_ctx_t * ret = NULL;
picohttp_server_stream_ctx_t target;
target.stream_id = stream_id;
picosplay_node_t * node = picosplay_find(stream_tree, (void*)&target);

if (node != NULL) {
ret = (picohttp_server_stream_ctx_t *)picohttp_stream_node_value(node);
}

return ret;
}

static picohttp_server_stream_ctx_t * picohttp_find_or_create_stream(
picoquic_cnx_t* cnx,
uint64_t stream_id,
picosplay_tree_t * stream_tree,
picohttp_server_stream_ctx_t ** p_first_stream,
int should_create,
int is_h3)
{
picohttp_server_stream_ctx_t * stream_ctx = NULL;
picohttp_server_stream_ctx_t * stream_ctx = picohttp_find_stream(stream_tree, stream_id);

/* if stream is already present, check its state. New bytes? */
stream_ctx = *p_first_stream;
while (stream_ctx != NULL && stream_ctx->stream_id != stream_id) {
stream_ctx = stream_ctx->next_stream;
}

if (stream_ctx == NULL && should_create) {
stream_ctx = (picohttp_server_stream_ctx_t*)
Expand All @@ -55,38 +119,15 @@ static picohttp_server_stream_ctx_t * picohttp_find_or_create_stream(
}
else {
memset(stream_ctx, 0, sizeof(picohttp_server_stream_ctx_t));
stream_ctx->next_stream = *p_first_stream;
*p_first_stream = stream_ctx;
stream_ctx->stream_id = stream_id;
stream_ctx->is_h3 = is_h3;
picosplay_insert(stream_tree, stream_ctx);
}
}

return stream_ctx;
}

static void picohttp_delete_stream(picohttp_server_stream_ctx_t* stream_ctx)
{
if (stream_ctx->F != NULL) {
stream_ctx->F = picoquic_file_close(stream_ctx->F);
}

if (stream_ctx->path_callback != NULL) {
(void)stream_ctx->path_callback(NULL, NULL, 0, picohttp_callback_reset, stream_ctx);
}

if (stream_ctx->is_h3) {
h3zero_delete_data_stream_state(&stream_ctx->ps.stream_state);
}
else {
if (stream_ctx->ps.hq.path != NULL) {
free(stream_ctx->ps.hq.path);
}
}

free(stream_ctx);
}

/*
* Create and delete server side connection context
*/
Expand All @@ -97,6 +138,9 @@ static h3zero_server_callback_ctx_t* h3zero_server_callback_create_context(picoh

if (ctx != NULL) {
memset(ctx, 0, sizeof(h3zero_server_callback_ctx_t));

picosplay_init_tree(&ctx->h3_stream_tree, picohttp_stream_node_compare, picohttp_stream_node_create, picohttp_stream_node_delete, picohttp_stream_node_value);

ctx->first_stream = NULL;
ctx->buffer = (uint8_t*)malloc(PICOHTTP_RESPONSE_MAX);
if (ctx->buffer == NULL) {
Expand All @@ -118,12 +162,7 @@ static h3zero_server_callback_ctx_t* h3zero_server_callback_create_context(picoh

static void h3zero_server_callback_delete_context(h3zero_server_callback_ctx_t* ctx)
{
picohttp_server_stream_ctx_t* stream_ctx;

while ((stream_ctx = ctx->first_stream) != NULL) {
ctx->first_stream = stream_ctx->next_stream;
picohttp_delete_stream(stream_ctx);
}
picosplay_empty_tree(&ctx->h3_stream_tree);

if (ctx->buffer != NULL) {
free(ctx->buffer);
Expand Down Expand Up @@ -440,7 +479,7 @@ static int h3zero_server_callback_data(
else {
/* Find or create stream context */
if (stream_ctx == NULL) {
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->first_stream, 1, 1);
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->h3_stream_tree, &ctx->first_stream, 1, 1);
}

if (stream_ctx == NULL) {
Expand Down Expand Up @@ -516,7 +555,7 @@ int h3zero_server_callback_prepare_to_send(picoquic_cnx_t* cnx,
int ret = -1;

if (stream_ctx == NULL) {
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->first_stream, 0, 1);
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->h3_stream_tree, &ctx->first_stream, 0, 1);
}

if (stream_ctx == NULL) {
Expand Down Expand Up @@ -611,7 +650,7 @@ int h3zero_server_callback(picoquic_cnx_t* cnx,
case picoquic_callback_stop_sending: /* Client asks server to reset stream #x */
/* TODO: special case for uni streams. */
if (stream_ctx == NULL) {
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->first_stream, 0, 1);
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->h3_stream_tree, &ctx->first_stream, 0, 1);
}
if (stream_ctx != NULL) {
/* reset post callback. */
Expand All @@ -632,7 +671,7 @@ int h3zero_server_callback(picoquic_cnx_t* cnx,
case picoquic_callback_stream_gap:
/* Gap indication, when unreliable streams are supported */
if (stream_ctx == NULL) {
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->first_stream, 0, 1);
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->h3_stream_tree, &ctx->first_stream, 0, 1);
}
if (stream_ctx != NULL) {
if (stream_ctx->path_callback != NULL) {
Expand Down Expand Up @@ -691,6 +730,9 @@ static picoquic_h09_server_callback_ctx_t* first_server_callback_create_context(

if (ctx != NULL) {
memset(ctx, 0, sizeof(picoquic_h09_server_callback_ctx_t));

picosplay_init_tree(&ctx->h09_stream_tree, picohttp_stream_node_compare, picohttp_stream_node_create, picohttp_stream_node_delete, picohttp_stream_node_value);

ctx->first_stream = NULL;
if (param != NULL) {
ctx->path_table = param->path_table;
Expand All @@ -704,12 +746,8 @@ static picoquic_h09_server_callback_ctx_t* first_server_callback_create_context(

static void picoquic_h09_server_callback_delete_context(picoquic_h09_server_callback_ctx_t* ctx)
{
picohttp_server_stream_ctx_t* stream_ctx;

while ((stream_ctx = ctx->first_stream) != NULL) {
ctx->first_stream = stream_ctx->next_stream;
picohttp_delete_stream(stream_ctx);
}
picosplay_empty_tree(&ctx->h09_stream_tree);

free(ctx);
}
Expand Down Expand Up @@ -1132,7 +1170,7 @@ int picoquic_h09_server_callback(picoquic_cnx_t* cnx,
}

if (stream_ctx == NULL) {
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->first_stream, 1, 0);
stream_ctx = picohttp_find_or_create_stream(cnx, stream_id, &ctx->h09_stream_tree, &ctx->first_stream, 1, 0);
}

switch (fin_or_event) {
Expand Down
3 changes: 3 additions & 0 deletions picohttp/demoserver.h
Expand Up @@ -89,6 +89,7 @@ typedef enum {
typedef struct st_picohttp_server_stream_ctx_t {
/* TODO-POST: identification of URL to process POST or GET? */
/* TODO-POST: provide content-type */
picosplay_node_t http_stream_node;
struct st_picohttp_server_stream_ctx_t* next_stream;
int is_h3;
union {
Expand Down Expand Up @@ -116,6 +117,7 @@ typedef struct st_picohttp_server_stream_ctx_t {
/* Define the H3Zero server callback */

typedef struct st_h3zero_server_callback_ctx_t {
picosplay_tree_t h3_stream_tree;
picohttp_server_stream_ctx_t* first_stream;
size_t buffer_max;
uint8_t* buffer;
Expand All @@ -133,6 +135,7 @@ int h3zero_server_callback(picoquic_cnx_t* cnx,
*/

typedef struct st_picoquic_h09_server_callback_ctx_t {
picosplay_tree_t h09_stream_tree;
picohttp_server_stream_ctx_t* first_stream;
picohttp_server_path_item_t * path_table;
size_t path_table_nb;
Expand Down
15 changes: 3 additions & 12 deletions picoquic/frames.c
Expand Up @@ -1160,18 +1160,9 @@ picoquic_stream_head_t* picoquic_find_ready_stream(picoquic_cnx_t* cnx)
if (stream == end_of_second_pass) {
end_of_second_pass = next_stream;
}
if (stream == cnx->first_output_stream) {
cnx->first_output_stream = next_stream;
}
else if (previous_stream != NULL) {
previous_stream->next_output_stream = next_stream;
}
else {
DBG_PRINTF("Corrupted list of output streams found when removing stream %d", (int)stream->stream_id);
break;
}
stream->next_output_stream = NULL;
stream->is_output_stream = 0;

picoquic_remove_output_stream(cnx, stream, previous_stream);

picoquic_delete_stream_if_closed(cnx, stream);
stream = next_stream;
}
Expand Down
19 changes: 6 additions & 13 deletions picoquic/packet.c
Expand Up @@ -727,19 +727,12 @@ int picoquic_prepare_version_negotiation(
/* Set the version number to zero */
picoformat_32(bytes + byte_index, 0);
byte_index += 4;
if (ph->is_old_invariant) {
/* Encode the ID lengths */
bytes[byte_index++] = picoquic_create_packet_header_cnxid_lengths(ph->srce_cnx_id.id_len, ph->dest_cnx_id.id_len);
/* Copy the incoming connection ID */
byte_index += picoquic_format_connection_id(bytes + byte_index, PICOQUIC_MAX_PACKET_SIZE - byte_index, ph->srce_cnx_id);
byte_index += picoquic_format_connection_id(bytes + byte_index, PICOQUIC_MAX_PACKET_SIZE - byte_index, ph->dest_cnx_id);
}
else {
bytes[byte_index++] = ph->srce_cnx_id.id_len;
byte_index += picoquic_format_connection_id(bytes + byte_index, PICOQUIC_MAX_PACKET_SIZE - byte_index, ph->srce_cnx_id);
bytes[byte_index++] = ph->dest_cnx_id.id_len;
byte_index += picoquic_format_connection_id(bytes + byte_index, PICOQUIC_MAX_PACKET_SIZE - byte_index, ph->dest_cnx_id);
}

bytes[byte_index++] = ph->srce_cnx_id.id_len;
byte_index += picoquic_format_connection_id(bytes + byte_index, PICOQUIC_MAX_PACKET_SIZE - byte_index, ph->srce_cnx_id);
bytes[byte_index++] = ph->dest_cnx_id.id_len;
byte_index += picoquic_format_connection_id(bytes + byte_index, PICOQUIC_MAX_PACKET_SIZE - byte_index, ph->dest_cnx_id);

/* Set the payload to the list of versions */
for (size_t i = 0; i < picoquic_nb_supported_versions; i++) {
picoformat_32(bytes + byte_index, picoquic_supported_versions[i].version);
Expand Down
1 change: 0 additions & 1 deletion picoquic/picoquic.h
Expand Up @@ -217,7 +217,6 @@ typedef struct st_picoquic_packet_header_t {
unsigned int spin : 1;
unsigned int has_spin_bit : 1;
unsigned int has_reserved_bit_set : 1;
unsigned int is_old_invariant : 1;
unsigned int has_loss_bits : 1;
unsigned int loss_bit_Q : 1;
unsigned int loss_bit_L : 1;
Expand Down
4 changes: 4 additions & 0 deletions picoquic/picoquic_internal.h
Expand Up @@ -395,6 +395,7 @@ typedef struct st_picoquic_stream_data_node_t {
typedef struct st_picoquic_stream_head_t {
picosplay_node_t stream_node;
struct st_picoquic_stream_head_t * next_output_stream;
struct st_picoquic_stream_head_t * previous_output_stream;
uint64_t stream_id;
uint64_t consumed_offset;
uint64_t fin_offset;
Expand Down Expand Up @@ -816,6 +817,7 @@ typedef struct st_picoquic_cnx_t {
/* Management of streams */
picosplay_tree_t stream_tree;
picoquic_stream_head_t * first_output_stream;
picoquic_stream_head_t * last_output_stream;
picoquic_stream_head_t * last_visited_stream;
uint64_t high_priority_stream_id;
uint64_t next_stream_id[4];
Expand Down Expand Up @@ -1074,6 +1076,8 @@ int picoquic_delete_stream_if_closed(picoquic_cnx_t* cnx, picoquic_stream_head_t
void picoquic_update_stream_initial_remote(picoquic_cnx_t* cnx);

picoquic_stream_head_t * picoquic_stream_from_node(picosplay_node_t * node);
void picoquic_insert_output_stream(picoquic_cnx_t* cnx, picoquic_stream_head_t * stream);
void picoquic_remove_output_stream(picoquic_cnx_t* cnx, picoquic_stream_head_t * stream, picoquic_stream_head_t * previous_stream);
picoquic_stream_head_t * picoquic_first_stream(picoquic_cnx_t * cnx);
picoquic_stream_head_t * picoquic_last_stream(picoquic_cnx_t * cnx);
picoquic_stream_head_t * picoquic_next_stream(picoquic_stream_head_t * stream);
Expand Down

0 comments on commit a66a5d0

Please sign in to comment.