Skip to content

Commit fbcbc60

Browse files
committed
Merge branch 'master' into qmux-development
2 parents 349be6e + 318d0ba commit fbcbc60

15 files changed

Lines changed: 235 additions & 65 deletions

File tree

CMakeLists.txt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -440,8 +440,9 @@ if (BUILD_LOGLIB)
440440
PRIVATE
441441
${PTLS_INCLUDE_DIRS}
442442
PUBLIC
443-
picoquic
444-
loglib)
443+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/picoquic>
444+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/loglib>
445+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
445446
set_picoquic_compile_settings(picoquic-log)
446447
endif()
447448

@@ -453,6 +454,7 @@ endif()
453454

454455
if (BUILD_HTTP)
455456
add_library(picohttp-core ${PICOHTTP_LIBRARY_FILES})
457+
add_library(picoquic::picohttp-core ALIAS picohttp-core)
456458
target_link_libraries(picohttp-core
457459
PRIVATE
458460
${PTLS_LIBRARIES}
@@ -467,8 +469,9 @@ if (BUILD_HTTP)
467469
${OPENSSL_INCLUDE_DIR}
468470
${MBEDTLS_INCLUDE_DIRS}
469471
PUBLIC
470-
picoquic
471-
picohttp)
472+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/picoquic>
473+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/picohttp>
474+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
472475
set_picoquic_compile_settings(picohttp-core)
473476
endif()
474477

@@ -631,7 +634,9 @@ endif()
631634

632635
if (TARGET picohttp-core)
633636
install(TARGETS picohttp-core
634-
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
637+
EXPORT picoquic-targets
638+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
639+
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
635640
install(FILES
636641
${PICOHTTP_HEADERS}
637642
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
@@ -644,7 +649,9 @@ endif()
644649

645650
if (TARGET picoquic-log)
646651
install(TARGETS picoquic-log
647-
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
652+
EXPORT picoquic-targets
653+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
654+
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
648655

649656
install(FILES
650657
${PICOQUIC_LOGLIB_HEADERS}

UnitTest1/unittest1.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3573,6 +3573,12 @@ namespace UnitTest1
35733573
Assert::AreEqual(ret, 0);
35743574
}
35753575

3576+
TEST_METHOD(picowt_baton_wildcard) {
3577+
int ret = picowt_baton_wildcard_test();
3578+
3579+
Assert::AreEqual(ret, 0);
3580+
}
3581+
35763582
TEST_METHOD(picowt_baton_krome) {
35773583
int ret = picowt_baton_krome_test();
35783584

ci/embedding-test/install_test/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ project(install_test LANGUAGES C)
33

44
# Validate that an installed picoquic exports INTERFACE_INCLUDE_DIRECTORIES so
55
# that consumers can #include <picoquic.h> without manually specifying the path.
6+
# Also validates that picohttp-core is exported as picoquic::picohttp-core.
67
find_package(picoquic REQUIRED)
78

89
add_executable(install_test main.c)
910
target_link_libraries(install_test PRIVATE picoquic::picoquic-core)
11+
12+
if(TARGET picoquic::picohttp-core)
13+
add_executable(install_test_http main_http.c)
14+
target_link_libraries(install_test_http PRIVATE picoquic::picohttp-core)
15+
endif()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <h3zero.h>
2+
#include <stdio.h>
3+
4+
int main(void)
5+
{
6+
printf("picohttp-core available\n");
7+
return 0;
8+
}

ci/embedding-test/run.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ cmake -S "$SCRIPT_DIR/install_test" -B "$BUILD_DIR/install_test" \
4242
-DCMAKE_BUILD_TYPE=Release
4343
cmake --build "$BUILD_DIR/install_test"
4444
"$BUILD_DIR/install_test/install_test"
45+
if [ -f "$BUILD_DIR/install_test/install_test_http" ]; then
46+
"$BUILD_DIR/install_test/install_test_http"
47+
fi
4548

4649
# --- FetchContent re-export test ---
4750
# Validates that a library embedding picoquic via FetchContent correctly

picohttp/h3zero.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
* The server will start the connection by sending a setting frame, which will
3232
* specify a zero-length dynamic dictionary for QPACK.
3333
*/
34+
#include <stdio.h>
3435
#include <string.h>
3536
#include <stdlib.h>
3637
#include <stdint.h>
@@ -478,6 +479,16 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
478479
decoded_length, &parts->path, &parts->path_length);
479480
}
480481
break;
482+
case http_pseudo_header_authority:
483+
if (parts->authority != NULL) {
484+
/* Duplicate authority! */
485+
bytes = 0;
486+
}
487+
else {
488+
bytes = h3zero_parse_qpack_header_value_string(bytes, decoded,
489+
decoded_length, &parts->authority, &parts->authority_length);
490+
}
491+
break;
481492
case http_header_range:
482493
if (parts->range != NULL) {
483494
/* Duplicate content type! */
@@ -517,7 +528,16 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
517528
}
518529
else {
519530
bytes = h3zero_parse_qpack_header_value_string(bytes, decoded,
520-
decoded_length, &parts->wt_protocol, &parts->wt_available_protocols_length);
531+
decoded_length, &parts->wt_protocol, &parts->wt_protocol_length);
532+
/* WT-Protocol is a Structured Header String — strip surrounding quotes */
533+
if (parts->wt_protocol != NULL && parts->wt_protocol_length >= 2 &&
534+
parts->wt_protocol[0] == '"' &&
535+
parts->wt_protocol[parts->wt_protocol_length - 1] == '"') {
536+
uint8_t* p = (uint8_t*)parts->wt_protocol;
537+
parts->wt_protocol_length -= 2;
538+
memmove(p, p + 1, parts->wt_protocol_length);
539+
p[parts->wt_protocol_length] = 0;
540+
}
521541
}
522542
break;
523543

@@ -537,11 +557,12 @@ uint8_t * h3zero_parse_qpack_header_value(uint8_t * bytes, uint8_t * bytes_max,
537557
int h3zero_get_interesting_header_type(uint8_t * name, size_t name_length, int is_huffman)
538558
{
539559
char const * interesting_header_name[] = {
540-
":method", ":path", ":status", "content-type", ":protocol", "origin", "range",
560+
":method", ":path", ":authority", ":status", "content-type", ":protocol", "origin", "range",
541561
H3ZERO_WT_AVAILABLE_PROTOCOLS, H3ZERO_WT_PROTOCOL,
542562
NULL};
543563
const http_header_enum_t interesting_header[] = {
544564
http_pseudo_header_method, http_pseudo_header_path,
565+
http_pseudo_header_authority,
545566
http_pseudo_header_status, http_header_content_type,
546567
http_pseudo_header_protocol, http_header_origin,
547568
http_header_range, http_header_wt_available_protocols, http_header_wt_protocol
@@ -998,9 +1019,12 @@ uint8_t * h3zero_create_response_header_frame_ex(uint8_t * bytes, uint8_t * byte
9981019
}
9991020

10001021
if (wt_protocol != NULL) {
1022+
/* WT-Protocol is a Structured Header String and must be quoted per spec */
1023+
char quoted[258];
1024+
int quoted_len = snprintf(quoted, sizeof(quoted), "\"%s\"", wt_protocol);
10011025
bytes = h3zero_qpack_literal_plus_name_encode(bytes, bytes_max,
10021026
(uint8_t*)H3ZERO_WT_PROTOCOL, strlen(H3ZERO_WT_PROTOCOL),
1003-
(uint8_t*)wt_protocol, strlen(wt_protocol));
1027+
(uint8_t*)quoted, (size_t)quoted_len);
10041028
}
10051029

10061030
return bytes;
@@ -1113,6 +1137,11 @@ void h3zero_release_header_parts(h3zero_header_parts_t* header)
11131137
*((uint8_t**)&header->path) = NULL;
11141138
header->path_length = 0;
11151139
}
1140+
if (header->authority != NULL) {
1141+
free((uint8_t*)header->authority);
1142+
*((uint8_t**)&header->authority) = NULL;
1143+
header->authority_length = 0;
1144+
}
11161145
if (header->range != NULL) {
11171146
free((uint8_t*)header->range);
11181147
*((uint8_t**)&header->range) = NULL;

picohttp/h3zero.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
#ifndef H3ZERO_H
2222
#define H3ZERO_H
2323

24+
#include <stddef.h>
25+
#include <stdint.h>
26+
2427
#ifdef __cplusplus
2528
extern "C" {
2629
#endif
@@ -190,6 +193,8 @@ typedef struct st_h3zero_header_parts_t {
190193
h3zero_method_enum method;
191194
uint8_t const * path;
192195
size_t path_length;
196+
uint8_t const * authority;
197+
size_t authority_length;
193198
uint8_t const * range;
194199
size_t range_length;
195200
int status;

picohttp/h3zero_common.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -983,18 +983,23 @@ Picoquic POST Response\
983983
int h3zero_server_parse_path(const uint8_t* path, size_t path_length, uint64_t* echo_size,
984984
char** file_path, char const* web_folder, int* file_error);
985985

986-
int h3zero_find_path_item(const uint8_t * path, size_t path_length, const picohttp_server_path_item_t * path_table, size_t path_table_nb)
986+
int h3zero_find_path_item(const uint8_t* path, size_t path_length, const picohttp_server_path_item_t* path_table, size_t path_table_nb)
987987
{
988-
size_t i = 0;
989-
990-
while (i < path_table_nb) {
991-
if (path_length >= path_table[i].path_length && memcmp(path, path_table[i].path, path_table[i].path_length) == 0){
992-
if (path_length == path_table[i].path_length || path[path_table[i].path_length] == (uint8_t)'?')
993-
return (int)i;
994-
}
995-
i++;
996-
}
997-
return -1;
988+
int wildcard_index = -1;
989+
size_t i = 0;
990+
991+
while (i < path_table_nb) {
992+
if (wildcard_index < 0 && path_table[i].path_length == 1 && path_table[i].path[0] == '*') {
993+
/* Record wildcard as fallback; keep scanning for a specific match.
994+
* Convention: place '*' last in the table for readability. */
995+
wildcard_index = (int)i;
996+
} else if (path_length >= path_table[i].path_length && memcmp(path, path_table[i].path, path_table[i].path_length) == 0) {
997+
if (path_length == path_table[i].path_length || path[path_table[i].path_length] == (uint8_t)'?')
998+
return (int)i;
999+
}
1000+
i++;
1001+
}
1002+
return wildcard_index;
9981003
}
9991004

10001005
/* TODO find a better place. */

picohttp/pico_webtransport.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ extern "C" {
116116
*/
117117
int picowt_select_wt_protocol(h3zero_stream_ctx_t* stream_ctx, char const* supported);
118118

119+
/* Get the authority from a WebTransport request.
120+
* Returns a pointer to the null-terminated authority string, or NULL if not present.
121+
* The pointer is valid for the lifetime of the stream context.
122+
*/
123+
const char* picowt_get_authority(h3zero_stream_ctx_t* stream_ctx);
124+
119125
#ifdef __cplusplus
120126
}
121127
#endif

picohttp/webtransport.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ int picowt_select_wt_protocol(h3zero_stream_ctx_t* stream_ctx, char const* suppo
332332
return ret;
333333
}
334334

335+
const char* picowt_get_authority(h3zero_stream_ctx_t* stream_ctx)
336+
{
337+
return (const char*)stream_ctx->ps.stream_state.header.authority;
338+
}
339+
335340
/*
336341
* Connect
337342
*/

0 commit comments

Comments
 (0)