Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of range header #1703

Merged
merged 8 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions picohttp/democlient.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ int h09_demo_client_prepare_stream_open_command(

static int picoquic_demo_client_open_stream(picoquic_cnx_t* cnx,
picoquic_demo_callback_ctx_t* ctx,
uint64_t stream_id, char const* doc_name, char const* fname, uint64_t post_size, uint64_t nb_repeat)
uint64_t stream_id, char const* doc_name, char const* fname, char const* range, uint64_t post_size, uint64_t nb_repeat)
{
int ret = 0;
uint8_t buffer[1024];
Expand Down Expand Up @@ -315,8 +315,10 @@ static int picoquic_demo_client_open_stream(picoquic_cnx_t* cnx,

switch (ctx->alpn) {
case picoquic_alpn_http_3:
ret = h3zero_client_create_stream_request(
buffer, sizeof(buffer), path, path_len, post_size, cnx->sni, &request_length);
ret = h3zero_client_create_stream_request_ex(
buffer, sizeof(buffer), path, path_len,
range, (range == NULL)?0:strlen(range), post_size,
cnx->sni, &request_length);
break;
case picoquic_alpn_http_0_9:
default:
Expand Down Expand Up @@ -397,6 +399,7 @@ int picoquic_demo_client_start_streams(picoquic_cnx_t* cnx,
ret = picoquic_demo_client_open_stream(cnx, ctx, ctx->demo_stream[i].stream_id,
ctx->demo_stream[i].doc_name,
ctx->demo_stream[i].f_name,
ctx->demo_stream[i].range,
(size_t)ctx->demo_stream[i].post_size,
repeat_nb);
repeat_nb++;
Expand Down Expand Up @@ -871,10 +874,40 @@ char const * demo_client_parse_post_size(char const * text, uint64_t * post_size
return text;
}

char const * demo_client_parse_range(char const * text, char ** range)
{
if (text[0] != '#') {
*range = NULL;
}
else {
char const* range_start = ++text;
size_t l_range = 0;

while (*text != ':' && *text != ';' && *text != 0) {
text++;
}
l_range = text - range_start;
*range = malloc(l_range + 1);
if (*range == NULL) {
text = NULL;
} else {
memcpy(*range, range_start, l_range);
(*range)[l_range] = 0;

if (*text == ':') {
text++;
}
}
}

return text;
}

char const * demo_client_parse_stream_desc(char const * text, uint64_t default_stream, uint64_t default_previous,
picoquic_demo_stream_desc_t * desc)
{
memset(desc, 0, sizeof(picoquic_demo_stream_desc_t));

text = demo_client_parse_stream_repeat(text, &desc->repeat_count);

if (text != NULL) {
Expand All @@ -895,6 +928,10 @@ char const * demo_client_parse_stream_desc(char const * text, uint64_t default_s
text = demo_client_parse_post_size(demo_client_parse_stream_spaces(text), &desc->post_size);
}

if (text != NULL) {
text = demo_client_parse_range(demo_client_parse_stream_spaces(text), (char **)&desc->range);
}

/* Skip the final ';' */
if (text != NULL && *text == ';') {
text++;
Expand All @@ -914,6 +951,10 @@ void demo_client_delete_scenario_desc(size_t nb_streams, picoquic_demo_stream_de
free((char*)desc[i].doc_name);
*(char**)(&desc[i].doc_name) = NULL;
}
if (desc[i].range != NULL) {
free((char*)desc[i].range);
*(char**)(&desc[i].range) = NULL;
}
}
free(desc);
}
Expand Down
1 change: 1 addition & 0 deletions picohttp/democlient.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ typedef struct st_picoquic_demo_stream_desc_t {
char const* doc_name;
char const* f_name;
uint64_t post_size;
char const* range;
} picoquic_demo_stream_desc_t;

#define PICOQUIC_DEMO_STREAM_LIST_MAX 16
Expand Down
41 changes: 33 additions & 8 deletions picohttp/h3zero.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,16 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
decoded_length, &parts->path, &parts->path_length);
}
break;
case http_header_range:
if (parts->range != NULL) {
/* Duplicate content type! */
bytes = 0;
}
else {
bytes = h3zero_parse_qpack_header_value_string(bytes, decoded,
decoded_length, &parts->range, &parts->range_length);
}
break;
case http_pseudo_header_protocol:
if (parts->protocol != NULL) {
/* Duplicate content type! */
Expand All @@ -493,11 +503,12 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
int h3zero_get_interesting_header_type(uint8_t * name, size_t name_length, int is_huffman)
{
char const * interesting_header_name[] = {
":method", ":path", ":status", "content-type", ":protocol", "origin", NULL};
":method", ":path", ":status", "content-type", ":protocol", "origin", "range", NULL};
const http_header_enum_t interesting_header[] = {
http_pseudo_header_method, http_pseudo_header_path,
http_pseudo_header_status, http_header_content_type,
http_pseudo_header_protocol, http_header_origin
http_pseudo_header_protocol, http_header_origin,
http_header_range
};
http_header_enum_t val = http_header_unknown;
uint8_t deHuff[256];
Expand Down Expand Up @@ -837,7 +848,7 @@ uint8_t* h3zero_create_connect_header_frame(uint8_t* bytes, uint8_t* bytes_max,
}

uint8_t * h3zero_create_post_header_frame_ex(uint8_t * bytes, uint8_t * bytes_max,
uint8_t const * path, size_t path_length, char const * host,
uint8_t const * path, size_t path_length, uint8_t const * range, size_t range_length, char const* host,
h3zero_content_type_enum content_type, char const* ua_string)
{
if (bytes == NULL || bytes + 2 > bytes_max) {
Expand All @@ -852,10 +863,14 @@ uint8_t * h3zero_create_post_header_frame_ex(uint8_t * bytes, uint8_t * bytes_ma
bytes = h3zero_qpack_code_encode(bytes, bytes_max, 0xC0, 0x3F, H3ZERO_QPACK_SCHEME_HTTPS);
/* Path: doc_name. Use literal plus reference format */
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_CODE_PATH, path, path_length);
/*Authority: host. Use literal plus reference format */
/* Authority: host. Use literal plus reference format */
if (host != NULL) {
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_AUTHORITY, (uint8_t const *)host, strlen(host));
}
/* Optional: range. Use literal plus reference format */
if (range_length > 0) {
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_RANGE, (uint8_t const *)range, range_length);
}
/* User Agent */
if (ua_string != NULL) {
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_USER_AGENT, (uint8_t const*)ua_string, strlen(ua_string));
Expand All @@ -869,12 +884,13 @@ uint8_t * h3zero_create_post_header_frame_ex(uint8_t * bytes, uint8_t * bytes_ma
uint8_t* h3zero_create_post_header_frame(uint8_t* bytes, uint8_t* bytes_max,
uint8_t const* path, size_t path_length, char const* host, h3zero_content_type_enum content_type)
{
return h3zero_create_post_header_frame_ex(bytes, bytes_max, path, path_length, host,
return h3zero_create_post_header_frame_ex(bytes, bytes_max, path, path_length, NULL, 0, host,
content_type, H3ZERO_USER_AGENT_STRING);
}

uint8_t * h3zero_create_request_header_frame_ex(uint8_t * bytes, uint8_t * bytes_max,
uint8_t const * path, size_t path_length, char const * host, char const* ua_string)
uint8_t const * path, size_t path_length, uint8_t const * range, size_t range_length,
char const * host, char const* ua_string)
{
if (bytes == NULL || bytes + 2 > bytes_max) {
return NULL;
Expand All @@ -888,10 +904,14 @@ uint8_t * h3zero_create_request_header_frame_ex(uint8_t * bytes, uint8_t * bytes
bytes = h3zero_qpack_code_encode(bytes, bytes_max, 0xC0, 0x3F, H3ZERO_QPACK_SCHEME_HTTPS);
/* Path: doc_name. Use literal plus reference format */
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_CODE_PATH, path, path_length);
/*Authority: host. Use literal plus reference format */
/* Authority: host. Use literal plus reference format */
if (host != NULL) {
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_AUTHORITY, (uint8_t const *)host, strlen(host));
}
/* Optional: range. Use literal plus reference format */
if (range_length > 0) {
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_RANGE, (uint8_t const *)range, range_length);
}
/* User Agent */
if (ua_string != NULL) {
bytes = h3zero_qpack_literal_plus_ref_encode(bytes, bytes_max, H3ZERO_QPACK_USER_AGENT, (uint8_t const*)ua_string, strlen(ua_string));
Expand All @@ -903,7 +923,7 @@ uint8_t* h3zero_create_request_header_frame(uint8_t* bytes, uint8_t* bytes_max,
uint8_t const* path, size_t path_length, char const* host)
{
return h3zero_create_request_header_frame_ex(bytes, bytes_max, path, path_length,
host, H3ZERO_USER_AGENT_STRING);
NULL, 0, host, H3ZERO_USER_AGENT_STRING);
}

uint8_t * h3zero_create_response_header_frame_ex(uint8_t * bytes, uint8_t * bytes_max,
Expand Down Expand Up @@ -1039,6 +1059,11 @@ void h3zero_release_header_parts(h3zero_header_parts_t* header)
*((uint8_t**)&header->path) = NULL;
header->path_length = 0;
}
if (header->range != NULL) {
free((uint8_t*)header->range);
*((uint8_t**)&header->range) = NULL;
header->range_length = 0;
}
if (header->protocol != NULL) {
free((uint8_t*)header->protocol);
*((uint8_t**)&header->protocol) = NULL;
Expand Down
12 changes: 10 additions & 2 deletions picohttp/h3zero.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ typedef enum {
#define H3ZERO_QPACK_AUTHORITY 0
#define H3ZERO_QPACK_SCHEME_HTTPS 23
#define H3ZERO_QPACK_TEXT_PLAIN 53
#define H3ZERO_QPACK_RANGE 55
#define H3ZERO_QPACK_USER_AGENT 95
#define H3ZERO_QPACK_ORIGIN 90
#define H3ZERO_QPACK_SERVER 92
Expand Down Expand Up @@ -183,6 +184,8 @@ typedef struct st_h3zero_header_parts_t {
h3zero_method_enum method;
uint8_t const * path;
size_t path_length;
uint8_t const * range;
size_t range_length;
int status;
h3zero_content_type_enum content_type;
uint8_t const * protocol;
Expand Down Expand Up @@ -225,15 +228,20 @@ uint8_t * h3zero_parse_qpack_header_frame(uint8_t * bytes, uint8_t * bytes_max,
uint8_t * h3zero_create_request_header_frame(uint8_t * bytes, uint8_t * bytes_max,
uint8_t const * path, size_t path_length, char const * host);
uint8_t* h3zero_create_request_header_frame_ex(uint8_t* bytes, uint8_t* bytes_max,
uint8_t const* path, size_t path_length, char const* host, char const* ua_string);
uint8_t const* path, size_t path_length, uint8_t const* range, size_t range_length,
char const* host, char const* ua_string);
uint8_t * h3zero_create_post_header_frame(uint8_t * bytes, uint8_t * bytes_max,
uint8_t const * path, size_t path_length, char const * host,
h3zero_content_type_enum content_type);
uint8_t* h3zero_create_request_header_frame_ex(uint8_t* bytes, uint8_t* bytes_max,
uint8_t const* path, size_t path_length, uint8_t const* range, size_t range_length,
char const* host, char const* ua_string);
uint8_t* h3zero_create_connect_header_frame(uint8_t* bytes, uint8_t* bytes_max,
uint8_t const* path, size_t path_length, char const* protocol, char const* origin,
char const* ua_string);
uint8_t* h3zero_create_post_header_frame_ex(uint8_t* bytes, uint8_t* bytes_max,
uint8_t const* path, size_t path_length, char const* host, h3zero_content_type_enum content_type, char const* ua_string);
uint8_t const* path, size_t path_length, uint8_t const* range, size_t range_length,
char const* host, h3zero_content_type_enum content_type, char const* ua_string);
uint8_t * h3zero_create_response_header_frame(uint8_t * bytes, uint8_t * bytes_max,
h3zero_content_type_enum doc_type);
uint8_t* h3zero_create_error_frame(uint8_t* bytes, uint8_t* bytes_max, char const* error_code, char const* server_string);
Expand Down
13 changes: 9 additions & 4 deletions picohttp/h3zero_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
* but the client implementation is barebone.
*/

int h3zero_client_create_stream_request(
uint8_t * buffer, size_t max_bytes, uint8_t const * path, size_t path_len, uint64_t post_size, const char * host, size_t * consumed)
int h3zero_client_create_stream_request_ex(
uint8_t * buffer, size_t max_bytes, uint8_t const * path, size_t path_len, const char * range, size_t range_len, uint64_t post_size, const char * host, size_t * consumed)
{
int ret = 0;
uint8_t * o_bytes = buffer;
Expand All @@ -51,8 +51,8 @@ int h3zero_client_create_stream_request(
*o_bytes++ = h3zero_frame_header;
o_bytes += 2; /* reserve two bytes for frame length */
if (post_size == 0) {
o_bytes = h3zero_create_request_header_frame(o_bytes, o_bytes_max,
(const uint8_t *)path, path_len, host);
o_bytes = h3zero_create_request_header_frame_ex(o_bytes, o_bytes_max,
(const uint8_t *)path, path_len, (const uint8_t *)range, range_len, host, H3ZERO_USER_AGENT_STRING);
}
else {
o_bytes = h3zero_create_post_header_frame(o_bytes, o_bytes_max,
Expand Down Expand Up @@ -99,5 +99,10 @@ int h3zero_client_create_stream_request(
return ret;
}

int h3zero_client_create_stream_request(
uint8_t* buffer, size_t max_bytes, uint8_t const* path, size_t path_len, uint64_t post_size, const char* host, size_t* consumed)
{
return h3zero_client_create_stream_request_ex(buffer, max_bytes, path, path_len, NULL, 0, post_size, host, consumed);
}


2 changes: 2 additions & 0 deletions picohttp/h3zero_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ extern "C" {

/* CLIENT DEFINITIONS
*/
int h3zero_client_create_stream_request_ex(
uint8_t* buffer, size_t max_bytes, uint8_t const* path, size_t path_len, const char* range, size_t range_len, uint64_t post_size, const char* host, size_t* consumed);
int h3zero_client_create_stream_request(
uint8_t * buffer, size_t max_bytes, uint8_t const * path, size_t path_len, uint64_t post_size, const char * host, size_t * consumed);

Expand Down
Loading
Loading