merged to upstream
This commit is contained in:
commit
6b5bc6d41c
22
CHANGELOG
22
CHANGELOG
|
@ -1,3 +1,25 @@
|
|||
2020-06-03
|
||||
- 2.16.0
|
||||
- [API] Use lsxpack_header v206.
|
||||
- [FEATURE] Windows supported.
|
||||
- [BUGFIX] Fix uninitialized variable use in client (regression in
|
||||
2.15.0).
|
||||
- Use ls-hpack 2.2.0.
|
||||
- Use ls-qpack 2.2.0.
|
||||
- Sample programs: fix the way maximum number of packets is
|
||||
calculated.
|
||||
- Remove some dead code.
|
||||
|
||||
2020-05-27
|
||||
- 2.15.0
|
||||
- [FEATURE] QUIC and HTTP/3 Internet Draft 28 support.
|
||||
- [BUGFIX] Ignore Retry packets after other packets are decrypted
|
||||
successfully.
|
||||
- [BUGFIX] Transport parameter decoding: CID no longer has 4-byte
|
||||
length minimum.
|
||||
- http_client: fix and optimize lsxpack_header allocator.
|
||||
- Drop support for Internet Draft 25.
|
||||
|
||||
2020-05-19
|
||||
- 2.14.8
|
||||
- Support Android.
|
||||
|
|
|
@ -85,7 +85,22 @@ ENDIF()
|
|||
|
||||
#MSVC
|
||||
ELSE()
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4100") # unreferenced formal parameter
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4115") # unnamed type definition in parentheses
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4116") # named type definition in parentheses
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4146") # unary minus operator applied to unsigned type, result still unsigned
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4132") # const initialization
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4200") # zero-sized array
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4204") # non-constant aggregate initializer
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4244") # integer conversion
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4245") # conversion from 'int' to 'unsigned int', signed/unsigned mismatch
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4267") # integer conversion
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4214") # nonstandard extension used: bit field types other than int
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4295") # array is too small to include a terminating null character
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4334") # result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4456") # hide previous local declaration
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4459") # hide global declaration
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} /wd4706") # assignment within conditional expression
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -W4 -WX -Zi -DWIN32_LEAN_AND_MEAN -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS -I${CMAKE_CURRENT_SOURCE_DIR}/wincompat")
|
||||
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Od")
|
||||
|
@ -103,6 +118,11 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MY_CMAKE_FLAGS} $ENV{EXTRA_CFLAGS}")
|
|||
|
||||
MESSAGE(STATUS "Compiler flags: ${CMAKE_C_FLAGS}")
|
||||
|
||||
find_package(Perl)
|
||||
IF(NOT PERL_FOUND)
|
||||
MESSAGE(FATAL_ERROR "Perl not found -- need it to generate source code")
|
||||
ENDIF()
|
||||
|
||||
IF (NOT DEFINED BORINGSSL_INCLUDE AND DEFINED BORINGSSL_DIR)
|
||||
FIND_PATH(BORINGSSL_INCLUDE NAMES openssl/ssl.h
|
||||
PATHS ${BORINGSSL_DIR}/include
|
||||
|
@ -124,7 +144,7 @@ IF (NOT DEFINED BORINGSSL_LIB AND DEFINED BORINGSSL_DIR)
|
|||
FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME}
|
||||
NAMES ${LIB_NAME}
|
||||
PATHS ${BORINGSSL_DIR}/${LIB_NAME}
|
||||
PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
|
||||
PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
|
||||
NO_DEFAULT_PATH)
|
||||
ELSE()
|
||||
FIND_LIBRARY(BORINGSSL_LIB_${LIB_NAME}
|
||||
|
@ -195,7 +215,7 @@ ELSE()
|
|||
MESSAGE(STATUS "zlib not found")
|
||||
ENDIF()
|
||||
|
||||
IF (LSQUIC_BIN)
|
||||
IF (LSQUIC_BIN OR LSQUIC_TESTS)
|
||||
FIND_PATH(EVENT_INCLUDE_DIR NAMES event2/event.h)
|
||||
IF (EVENT_INCLUDE_DIR)
|
||||
INCLUDE_DIRECTORIES(${EVENT_INCLUDE_DIR})
|
||||
|
@ -215,15 +235,38 @@ IF(EVENT_LIB)
|
|||
ELSE()
|
||||
MESSAGE(STATUS "libevent not found")
|
||||
ENDIF()
|
||||
|
||||
add_executable(http_server bin/http_server.c bin/prog.c bin/test_common.c bin/test_cert.c)
|
||||
add_executable(md5_server bin/md5_server.c bin/prog.c bin/test_common.c bin/test_cert.c)
|
||||
add_executable(md5_client bin/md5_client.c bin/prog.c bin/test_common.c bin/test_cert.c)
|
||||
add_executable(echo_server bin/echo_server.c bin/prog.c bin/test_common.c bin/test_cert.c)
|
||||
add_executable(echo_client bin/echo_client.c bin/prog.c bin/test_common.c bin/test_cert.c)
|
||||
|
||||
|
||||
SET(LIBS lsquic ${EVENT_LIB} ${BORINGSSL_LIB_ssl} ${BORINGSSL_LIB_crypto} ${ZLIB_LIB} ${LIBS})
|
||||
IF(MSVC)
|
||||
FIND_LIBRARY(PCRE_LIB pcre)
|
||||
IF(PCRE_LIB)
|
||||
MESSAGE(STATUS "Found pcre: ${PCRE_LIB}")
|
||||
LIST(APPEND LIBS ${PCRE_LIB})
|
||||
ELSE()
|
||||
MESSAGE(STATUS "pcre not found: http_server won't work")
|
||||
ENDIF()
|
||||
FIND_LIBRARY(PCREPOSIX_LIB pcreposix)
|
||||
IF(PCREPOSIX_LIB)
|
||||
MESSAGE(STATUS "Found pcreposix: ${PCREPOSIX_LIB}")
|
||||
LIST(APPEND LIBS ${PCREPOSIX_LIB})
|
||||
ELSE()
|
||||
MESSAGE(STATUS "pcreposix not found: http_server won't work")
|
||||
ENDIF()
|
||||
LIST(APPEND LIBS ws2_32)
|
||||
ENDIF()
|
||||
ENDIF() # LSQUIC_BIN OR LSQUIC_TESTS
|
||||
|
||||
IF(LSQUIC_BIN)
|
||||
IF(MSVC)
|
||||
SET(GETOPT_C wincompat/getopt.c)
|
||||
ENDIF()
|
||||
add_executable(http_server bin/http_server.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
|
||||
IF(NOT MSVC) # TODO: port MD5 server and client to Windows
|
||||
add_executable(md5_server bin/md5_server.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
|
||||
add_executable(md5_client bin/md5_client.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
|
||||
ENDIF()
|
||||
add_executable(echo_server bin/echo_server.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
|
||||
add_executable(echo_client bin/echo_client.c bin/prog.c bin/test_common.c bin/test_cert.c ${GETOPT_C})
|
||||
|
||||
|
||||
IF (NOT MSVC)
|
||||
|
||||
|
@ -242,6 +285,7 @@ add_executable(http_client
|
|||
bin/http_client.c
|
||||
bin/prog.c
|
||||
bin/test_common.c
|
||||
bin/test_cert.c
|
||||
wincompat/getopt.c
|
||||
wincompat/getopt1.c
|
||||
)
|
||||
|
@ -251,8 +295,10 @@ ENDIF()
|
|||
|
||||
TARGET_LINK_LIBRARIES(http_client ${LIBS})
|
||||
TARGET_LINK_LIBRARIES(http_server ${LIBS})
|
||||
IF(NOT MSVC)
|
||||
TARGET_LINK_LIBRARIES(md5_server ${LIBS})
|
||||
TARGET_LINK_LIBRARIES(md5_client ${LIBS})
|
||||
ENDIF()
|
||||
TARGET_LINK_LIBRARIES(echo_server ${LIBS})
|
||||
TARGET_LINK_LIBRARIES(echo_client ${LIBS})
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[![Build Status](https://travis-ci.org/litespeedtech/lsquic.svg?branch=master)](https://travis-ci.org/litespeedtech/lsquic)
|
||||
[![Build Status](https://api.cirrus-ci.com/github/litespeedtech/lsquic.svg)](https://cirrus-ci.com/github/litespeedtech/lsquic)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/kei9649t9leoqicr?svg=true)](https://ci.appveyor.com/project/litespeedtech/lsquic)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/ij4n3vy343pkgm1j?svg=true)](https://ci.appveyor.com/project/litespeedtech/lsquic)
|
||||
|
||||
LiteSpeed QUIC (LSQUIC) Library README
|
||||
=============================================
|
||||
|
@ -15,7 +15,7 @@ and OpenLiteSpeed. We think it is free of major problems. Nevertheless, do
|
|||
not hesitate to report bugs back to us. Even better, send us fixes and
|
||||
improvements!
|
||||
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-25, and ID-27.
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, and ID-28.
|
||||
Support for newer versions will be added soon after they are released.
|
||||
|
||||
Documentation
|
||||
|
@ -137,7 +137,7 @@ The library has been tested on the following platforms:
|
|||
- x86_64
|
||||
- Android
|
||||
- ARM
|
||||
- Windows (this needs updating for the server part, now broken)
|
||||
- Windows
|
||||
- x86_64
|
||||
|
||||
Have fun,
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
version: 1.{branch}.{build}
|
||||
|
||||
image: Visual Studio 2017
|
||||
|
||||
cache: c:\tools\vcpkg\installed
|
||||
|
||||
init:
|
||||
|
||||
- cmd: ''
|
||||
|
||||
install:
|
||||
|
||||
- cmd: >-
|
||||
|
||||
vcpkg install zlib:x64-windows-static
|
||||
|
||||
vcpkg install libevent:x64-windows-static
|
||||
|
||||
vcpkg install pcre:x64-windows-static
|
||||
|
||||
vcpkg integrate install
|
||||
|
||||
build_script:
|
||||
|
||||
- cmd: >-
|
||||
|
||||
vcpkg list
|
||||
|
||||
git clone https://boringssl.googlesource.com/boringssl
|
||||
|
||||
cd boringssl
|
||||
|
||||
git checkout bfe527fa35735e8e045cbfb42b012e13ca68f9cf
|
||||
|
||||
cmake -DCMAKE_GENERATOR_PLATFORM=x64 --config Debug -DBUILD_SHARED_LIBS=OFF -DOPENSSL_NO_ASM=1 .
|
||||
|
||||
|
||||
|
||||
msbuild /m ALL_BUILD.vcxproj
|
||||
|
||||
|
||||
|
||||
cd ..
|
||||
|
||||
|
||||
|
||||
git submodule init
|
||||
|
||||
|
||||
|
||||
git submodule update
|
||||
|
||||
|
||||
|
||||
cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DBUILD_SHARED_LIBS=OFF -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake -DBORINGSSL_DIR=%cd%\boringssl .
|
||||
|
||||
|
||||
|
||||
msbuild /m ALL_BUILD.vcxproj
|
||||
|
||||
test_script:
|
||||
|
||||
- cmd: msbuild /m RUN_TESTS.vcxproj
|
|
@ -21,6 +21,16 @@ CHECK_SYMBOL_EXISTS(
|
|||
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
|
||||
IF (MSVC AND PCRE_LIB)
|
||||
FIND_PATH(EVENT_INCLUDE_DIR NAMES pcreposix.h)
|
||||
IF (EVENT_INCLUDE_DIR)
|
||||
MESSAGE(STATUS "found pcreposix.h")
|
||||
SET(HAVE_REGEX 1)
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "event2/event.h was not found")
|
||||
ENDIF()
|
||||
ELSE()
|
||||
CHECK_INCLUDE_FILES(regex.h HAVE_REGEX)
|
||||
ENDIF()
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/test_config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/test_config.h)
|
||||
|
|
|
@ -9,11 +9,21 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#define Read read
|
||||
#else
|
||||
#include "vc_compat.h"
|
||||
#include "getopt.h"
|
||||
#include <io.h>
|
||||
#define Read _read
|
||||
#define STDIN_FILENO 0
|
||||
#endif
|
||||
|
||||
#include <event2/event.h>
|
||||
|
||||
|
@ -69,12 +79,12 @@ struct lsquic_stream_ctx {
|
|||
|
||||
|
||||
static void
|
||||
read_stdin (int fd, short what, void *ctx)
|
||||
read_stdin (evutil_socket_t fd, short what, void *ctx)
|
||||
{
|
||||
ssize_t nr;
|
||||
lsquic_stream_ctx_t *st_h = ctx;
|
||||
|
||||
nr = read(fd, st_h->buf + st_h->buf_off++, 1);
|
||||
nr = Read(fd, st_h->buf + st_h->buf_off++, 1);
|
||||
LSQ_DEBUG("read %zd bytes from stdin", nr);
|
||||
if (0 == nr)
|
||||
{
|
||||
|
@ -217,6 +227,7 @@ main (int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
int flags = fcntl(STDIN_FILENO, F_GETFL);
|
||||
flags |= O_NONBLOCK;
|
||||
if (0 != fcntl(STDIN_FILENO, F_SETFL, flags))
|
||||
|
@ -224,6 +235,12 @@ main (int argc, char **argv)
|
|||
perror("fcntl");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
{
|
||||
u_long on = 1;
|
||||
ioctlsocket(STDIN_FILENO, FIONBIO, &on);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (0 != prog_prep(&prog))
|
||||
{
|
||||
|
|
|
@ -4,14 +4,19 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <time.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include "vc_compat.h"
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "test_common.h"
|
||||
|
|
|
@ -220,6 +220,7 @@ struct lsquic_conn_ctx {
|
|||
struct hset_elem
|
||||
{
|
||||
STAILQ_ENTRY(hset_elem) next;
|
||||
size_t nalloc;
|
||||
struct lsxpack_header xhdr;
|
||||
};
|
||||
|
||||
|
@ -530,18 +531,20 @@ static void
|
|||
send_headers (lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
const char *hostname = st_h->client_ctx->hostname;
|
||||
struct header_buf hbuf;
|
||||
if (!hostname)
|
||||
hostname = st_h->client_ctx->prog->prog_hostname;
|
||||
hbuf.off = 0;
|
||||
struct lsxpack_header headers_arr[7];
|
||||
#define V(v) (v), strlen(v)
|
||||
lsxpack_header_set_ptr(&headers_arr[0], V(":method"), V(st_h->client_ctx->method));
|
||||
lsxpack_header_set_ptr(&headers_arr[1], V(":scheme"), V("https"));
|
||||
lsxpack_header_set_ptr(&headers_arr[2], V(":path"), V(st_h->path));
|
||||
lsxpack_header_set_ptr(&headers_arr[3], V(":authority"), V(hostname));
|
||||
lsxpack_header_set_ptr(&headers_arr[4], V("user-agent"), V(st_h->client_ctx->prog->prog_settings.es_ua));
|
||||
header_set_ptr(&headers_arr[0], &hbuf, V(":method"), V(st_h->client_ctx->method));
|
||||
header_set_ptr(&headers_arr[1], &hbuf, V(":scheme"), V("https"));
|
||||
header_set_ptr(&headers_arr[2], &hbuf, V(":path"), V(st_h->path));
|
||||
header_set_ptr(&headers_arr[3], &hbuf, V(":authority"), V(hostname));
|
||||
header_set_ptr(&headers_arr[4], &hbuf, V("user-agent"), V(st_h->client_ctx->prog->prog_settings.es_ua));
|
||||
/* The following headers only gets sent if there is request payload: */
|
||||
lsxpack_header_set_ptr(&headers_arr[5], V("content-type"), V("application/octet-stream"));
|
||||
lsxpack_header_set_ptr(&headers_arr[6], V("content-length"), V( st_h->client_ctx->payload_size));
|
||||
header_set_ptr(&headers_arr[5], &hbuf, V("content-type"), V("application/octet-stream"));
|
||||
header_set_ptr(&headers_arr[6], &hbuf, V("content-length"), V( st_h->client_ctx->payload_size));
|
||||
lsquic_http_headers_t headers = {
|
||||
.count = sizeof(headers_arr) / sizeof(headers_arr[0]),
|
||||
.headers = headers_arr,
|
||||
|
@ -999,16 +1002,19 @@ hset_prepare_decode (void *hset_p, struct lsxpack_header *xhdr,
|
|||
}
|
||||
STAILQ_INSERT_TAIL(hset, el, next);
|
||||
lsxpack_header_prepare_decode(&el->xhdr, buf, 0, req_space);
|
||||
el->nalloc = req_space;
|
||||
}
|
||||
else
|
||||
{
|
||||
el = (struct hset_elem *) ((char *) xhdr
|
||||
- offsetof(struct hset_elem, xhdr));
|
||||
if (req_space <= xhdr->val_len)
|
||||
if (req_space <= el->nalloc)
|
||||
{
|
||||
LSQ_ERROR("requested space is smaller than already allocated");
|
||||
return NULL;
|
||||
}
|
||||
if (req_space < el->nalloc * 2)
|
||||
req_space = el->nalloc * 2;
|
||||
buf = realloc(el->xhdr.buf, req_space);
|
||||
if (!buf)
|
||||
{
|
||||
|
@ -1017,6 +1023,7 @@ hset_prepare_decode (void *hset_p, struct lsxpack_header *xhdr,
|
|||
}
|
||||
el->xhdr.buf = buf;
|
||||
el->xhdr.val_len = req_space;
|
||||
el->nalloc = req_space;
|
||||
}
|
||||
|
||||
return &el->xhdr;
|
||||
|
@ -1067,11 +1074,11 @@ hset_dump (const struct hset *hset, FILE *out)
|
|||
const struct hset_elem *el;
|
||||
|
||||
STAILQ_FOREACH(el, hset, next)
|
||||
if (el->xhdr.flags & (LSXPACK_HPACK_IDX|LSXPACK_QPACK_IDX))
|
||||
if (el->xhdr.flags & (LSXPACK_HPACK_VAL_MATCHED|LSXPACK_QPACK_IDX))
|
||||
fprintf(out, "%.*s (%s static table idx %u): %.*s\n",
|
||||
(int) el->xhdr.name_len, lsxpack_header_get_name(&el->xhdr),
|
||||
el->xhdr.flags & LSXPACK_HPACK_IDX ? "hpack" : "qpack",
|
||||
el->xhdr.flags & LSXPACK_HPACK_IDX ? el->xhdr.hpack_index
|
||||
el->xhdr.flags & LSXPACK_HPACK_VAL_MATCHED ? "hpack" : "qpack",
|
||||
el->xhdr.flags & LSXPACK_HPACK_VAL_MATCHED ? el->xhdr.hpack_index
|
||||
: el->xhdr.qpack_index,
|
||||
(int) el->xhdr.val_len, lsxpack_header_get_value(&el->xhdr));
|
||||
else
|
||||
|
@ -1152,7 +1159,6 @@ qif_client_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
|
|||
struct lsxpack_header *header;
|
||||
static int reqno;
|
||||
size_t nalloc;
|
||||
int i;
|
||||
char *end, *tab, *line;
|
||||
char line_buf[0x1000];
|
||||
|
||||
|
@ -1210,20 +1216,11 @@ qif_client_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
|
|||
exit(1);
|
||||
}
|
||||
header = &ctx->headers.headers[ctx->headers.count++];
|
||||
lsxpack_header_set_ptr(header, (void *) ctx->qif_sz, tab - line,
|
||||
(void *) (ctx->qif_sz + (tab - line + 1)), end - tab - 1);
|
||||
|
||||
lsxpack_header_set_offset2(header, ctx->qif_str + ctx->qif_sz, 0,
|
||||
tab - line, tab - line + 1, end - tab - 1);
|
||||
ctx->qif_sz += end + 1 - line;
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->headers.count; ++i)
|
||||
{
|
||||
ctx->headers.headers[i].buf = ctx->qif_str
|
||||
+ (uintptr_t) ctx->headers.headers[i].buf;
|
||||
ctx->headers.headers[i].name_ptr = ctx->qif_str
|
||||
+ (uintptr_t) ctx->headers.headers[i].name_ptr;
|
||||
}
|
||||
|
||||
lsquic_stream_wantwrite(stream, 1);
|
||||
|
||||
if (!line)
|
||||
|
@ -1421,10 +1418,6 @@ main (int argc, char **argv)
|
|||
client_ctx.hcc_reset_after_nbytes = 0;
|
||||
client_ctx.hcc_retire_cid_after_nbytes = 0;
|
||||
client_ctx.prog = &prog;
|
||||
#ifdef WIN32
|
||||
WSADATA wsd;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsd);
|
||||
#endif
|
||||
|
||||
prog_init(&prog, LSENG_HTTP, &sports, &http_client_if, &client_ctx);
|
||||
|
||||
|
|
|
@ -10,15 +10,20 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <regex.h>
|
||||
#include <netinet/in.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include "vc_compat.h"
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include <event2/event.h>
|
||||
|
||||
#include <openssl/md5.h>
|
||||
|
@ -29,12 +34,243 @@
|
|||
#include "test_common.h"
|
||||
#include "prog.h"
|
||||
|
||||
#if HAVE_REGEX
|
||||
#ifndef WIN32
|
||||
#include <regex.h>
|
||||
#else
|
||||
#include <pcreposix.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../src/liblsquic/lsquic_logger.h"
|
||||
#include "../src/liblsquic/lsquic_int_types.h"
|
||||
#include "../src/liblsquic/lsquic_util.h"
|
||||
|
||||
static const char on_being_idle[];
|
||||
static const size_t IDLE_SIZE;
|
||||
#if HAVE_REGEX
|
||||
static const char on_being_idle[] =
|
||||
"ON BEING IDLE.\n"
|
||||
"\n"
|
||||
"Now, this is a subject on which I flatter myself I really am _au fait_.\n"
|
||||
"The gentleman who, when I was young, bathed me at wisdom's font for nine\n"
|
||||
"guineas a term--no extras--used to say he never knew a boy who could\n"
|
||||
"do less work in more time; and I remember my poor grandmother once\n"
|
||||
"incidentally observing, in the course of an instruction upon the use\n"
|
||||
"of the Prayer-book, that it was highly improbable that I should ever do\n"
|
||||
"much that I ought not to do, but that she felt convinced beyond a doubt\n"
|
||||
"that I should leave undone pretty well everything that I ought to do.\n"
|
||||
"\n"
|
||||
"I am afraid I have somewhat belied half the dear old lady's prophecy.\n"
|
||||
"Heaven help me! I have done a good many things that I ought not to have\n"
|
||||
"done, in spite of my laziness. But I have fully confirmed the accuracy\n"
|
||||
"of her judgment so far as neglecting much that I ought not to have\n"
|
||||
"neglected is concerned. Idling always has been my strong point. I take\n"
|
||||
"no credit to myself in the matter--it is a gift. Few possess it. There\n"
|
||||
"are plenty of lazy people and plenty of slow-coaches, but a genuine\n"
|
||||
"idler is a rarity. He is not a man who slouches about with his hands in\n"
|
||||
"his pockets. On the contrary, his most startling characteristic is that\n"
|
||||
"he is always intensely busy.\n"
|
||||
"\n"
|
||||
"It is impossible to enjoy idling thoroughly unless one has plenty of\n"
|
||||
"work to do. There is no fun in doing nothing when you have nothing to\n"
|
||||
"do. Wasting time is merely an occupation then, and a most exhausting\n"
|
||||
"one. Idleness, like kisses, to be sweet must be stolen.\n"
|
||||
"\n"
|
||||
"Many years ago, when I was a young man, I was taken very ill--I never\n"
|
||||
"could see myself that much was the matter with me, except that I had\n"
|
||||
"a beastly cold. But I suppose it was something very serious, for the\n"
|
||||
"doctor said that I ought to have come to him a month before, and that\n"
|
||||
"if it (whatever it was) had gone on for another week he would not have\n"
|
||||
"answered for the consequences. It is an extraordinary thing, but I\n"
|
||||
"never knew a doctor called into any case yet but what it transpired\n"
|
||||
"that another day's delay would have rendered cure hopeless. Our medical\n"
|
||||
"guide, philosopher, and friend is like the hero in a melodrama--he\n"
|
||||
"always comes upon the scene just, and only just, in the nick of time. It\n"
|
||||
"is Providence, that is what it is.\n"
|
||||
"\n"
|
||||
"Well, as I was saying, I was very ill and was ordered to Buxton for a\n"
|
||||
"month, with strict injunctions to do nothing whatever all the while\n"
|
||||
"that I was there. \"Rest is what you require,\" said the doctor, \"perfect\n"
|
||||
"rest.\"\n"
|
||||
"\n"
|
||||
"It seemed a delightful prospect. \"This man evidently understands my\n"
|
||||
"complaint,\" said I, and I pictured to myself a glorious time--a four\n"
|
||||
"weeks' _dolce far niente_ with a dash of illness in it. Not too much\n"
|
||||
"illness, but just illness enough--just sufficient to give it the flavor\n"
|
||||
"of suffering and make it poetical. I should get up late, sip chocolate,\n"
|
||||
"and have my breakfast in slippers and a dressing-gown. I should lie out\n"
|
||||
"in the garden in a hammock and read sentimental novels with a melancholy\n"
|
||||
"ending, until the books should fall from my listless hand, and I should\n"
|
||||
"recline there, dreamily gazing into the deep blue of the firmament,\n"
|
||||
"watching the fleecy clouds floating like white-sailed ships across\n"
|
||||
"its depths, and listening to the joyous song of the birds and the low\n"
|
||||
"rustling of the trees. Or, on becoming too weak to go out of doors,\n"
|
||||
"I should sit propped up with pillows at the open window of the\n"
|
||||
"ground-floor front, and look wasted and interesting, so that all the\n"
|
||||
"pretty girls would sigh as they passed by.\n"
|
||||
"\n"
|
||||
"And twice a day I should go down in a Bath chair to the Colonnade to\n"
|
||||
"drink the waters. Oh, those waters! I knew nothing about them then,\n"
|
||||
"and was rather taken with the idea. \"Drinking the waters\" sounded\n"
|
||||
"fashionable and Queen Anne-fied, and I thought I should like them. But,\n"
|
||||
"ugh! after the first three or four mornings! Sam Weller's description of\n"
|
||||
"them as \"having a taste of warm flat-irons\" conveys only a faint idea of\n"
|
||||
"their hideous nauseousness. If anything could make a sick man get well\n"
|
||||
"quickly, it would be the knowledge that he must drink a glassful of them\n"
|
||||
"every day until he was recovered. I drank them neat for six consecutive\n"
|
||||
"days, and they nearly killed me; but after then I adopted the plan of\n"
|
||||
"taking a stiff glass of brandy-and-water immediately on the top of them,\n"
|
||||
"and found much relief thereby. I have been informed since, by various\n"
|
||||
"eminent medical gentlemen, that the alcohol must have entirely\n"
|
||||
"counteracted the effects of the chalybeate properties contained in the\n"
|
||||
"water. I am glad I was lucky enough to hit upon the right thing.\n"
|
||||
"\n"
|
||||
"But \"drinking the waters\" was only a small portion of the torture I\n"
|
||||
"experienced during that memorable month--a month which was, without\n"
|
||||
"exception, the most miserable I have ever spent. During the best part of\n"
|
||||
"it I religiously followed the doctor's mandate and did nothing whatever,\n"
|
||||
"except moon about the house and garden and go out for two hours a day in\n"
|
||||
"a Bath chair. That did break the monotony to a certain extent. There is\n"
|
||||
"more excitement about Bath-chairing--especially if you are not used to\n"
|
||||
"the exhilarating exercise--than might appear to the casual observer. A\n"
|
||||
"sense of danger, such as a mere outsider might not understand, is ever\n"
|
||||
"present to the mind of the occupant. He feels convinced every minute\n"
|
||||
"that the whole concern is going over, a conviction which becomes\n"
|
||||
"especially lively whenever a ditch or a stretch of newly macadamized\n"
|
||||
"road comes in sight. Every vehicle that passes he expects is going to\n"
|
||||
"run into him; and he never finds himself ascending or descending a\n"
|
||||
"hill without immediately beginning to speculate upon his chances,\n"
|
||||
"supposing--as seems extremely probable--that the weak-kneed controller\n"
|
||||
"of his destiny should let go.\n"
|
||||
"\n"
|
||||
"But even this diversion failed to enliven after awhile, and the _ennui_\n"
|
||||
"became perfectly unbearable. I felt my mind giving way under it. It is\n"
|
||||
"not a strong mind, and I thought it would be unwise to tax it too far.\n"
|
||||
"So somewhere about the twentieth morning I got up early, had a good\n"
|
||||
"breakfast, and walked straight off to Hayfield, at the foot of the\n"
|
||||
"Kinder Scout--a pleasant, busy little town, reached through a lovely\n"
|
||||
"valley, and with two sweetly pretty women in it. At least they were\n"
|
||||
"sweetly pretty then; one passed me on the bridge and, I think, smiled;\n"
|
||||
"and the other was standing at an open door, making an unremunerative\n"
|
||||
"investment of kisses upon a red-faced baby. But it is years ago, and I\n"
|
||||
"dare say they have both grown stout and snappish since that time.\n"
|
||||
"Coming back, I saw an old man breaking stones, and it roused such strong\n"
|
||||
"longing in me to use my arms that I offered him a drink to let me take\n"
|
||||
"his place. He was a kindly old man and he humored me. I went for those\n"
|
||||
"stones with the accumulated energy of three weeks, and did more work in\n"
|
||||
"half an hour than he had done all day. But it did not make him jealous.\n"
|
||||
"\n"
|
||||
"Having taken the plunge, I went further and further into dissipation,\n"
|
||||
"going out for a long walk every morning and listening to the band in\n"
|
||||
"the pavilion every evening. But the days still passed slowly\n"
|
||||
"notwithstanding, and I was heartily glad when the last one came and I\n"
|
||||
"was being whirled away from gouty, consumptive Buxton to London with its\n"
|
||||
"stern work and life. I looked out of the carriage as we rushed through\n"
|
||||
"Hendon in the evening. The lurid glare overhanging the mighty city\n"
|
||||
"seemed to warm my heart, and when, later on, my cab rattled out of St.\n"
|
||||
"Pancras' station, the old familiar roar that came swelling up around me\n"
|
||||
"sounded the sweetest music I had heard for many a long day.\n"
|
||||
"\n"
|
||||
"I certainly did not enjoy that month's idling. I like idling when I\n"
|
||||
"ought not to be idling; not when it is the only thing I have to do. That\n"
|
||||
"is my pig-headed nature. The time when I like best to stand with my\n"
|
||||
"back to the fire, calculating how much I owe, is when my desk is heaped\n"
|
||||
"highest with letters that must be answered by the next post. When I like\n"
|
||||
"to dawdle longest over my dinner is when I have a heavy evening's work\n"
|
||||
"before me. And if, for some urgent reason, I ought to be up particularly\n"
|
||||
"early in the morning, it is then, more than at any other time, that I\n"
|
||||
"love to lie an extra half-hour in bed.\n"
|
||||
"\n"
|
||||
"Ah! how delicious it is to turn over and go to sleep again: \"just for\n"
|
||||
"five minutes.\" Is there any human being, I wonder, besides the hero of\n"
|
||||
"a Sunday-school \"tale for boys,\" who ever gets up willingly? There\n"
|
||||
"are some men to whom getting up at the proper time is an utter\n"
|
||||
"impossibility. If eight o'clock happens to be the time that they should\n"
|
||||
"turn out, then they lie till half-past. If circumstances change and\n"
|
||||
"half-past eight becomes early enough for them, then it is nine before\n"
|
||||
"they can rise. They are like the statesman of whom it was said that he\n"
|
||||
"was always punctually half an hour late. They try all manner of schemes.\n"
|
||||
"They buy alarm-clocks (artful contrivances that go off at the wrong time\n"
|
||||
"and alarm the wrong people). They tell Sarah Jane to knock at the door\n"
|
||||
"and call them, and Sarah Jane does knock at the door and does call them,\n"
|
||||
"and they grunt back \"awri\" and then go comfortably to sleep again. I\n"
|
||||
"knew one man who would actually get out and have a cold bath; and even\n"
|
||||
"that was of no use, for afterward he would jump into bed again to warm\n"
|
||||
"himself.\n"
|
||||
"\n"
|
||||
"I think myself that I could keep out of bed all right if I once got\n"
|
||||
"out. It is the wrenching away of the head from the pillow that I find so\n"
|
||||
"hard, and no amount of over-night determination makes it easier. I say\n"
|
||||
"to myself, after having wasted the whole evening, \"Well, I won't do\n"
|
||||
"any more work to-night; I'll get up early to-morrow morning;\" and I am\n"
|
||||
"thoroughly resolved to do so--then. In the morning, however, I feel less\n"
|
||||
"enthusiastic about the idea, and reflect that it would have been much\n"
|
||||
"better if I had stopped up last night. And then there is the trouble of\n"
|
||||
"dressing, and the more one thinks about that the more one wants to put\n"
|
||||
"it off.\n"
|
||||
"\n"
|
||||
"It is a strange thing this bed, this mimic grave, where we stretch our\n"
|
||||
"tired limbs and sink away so quietly into the silence and rest. \"O bed,\n"
|
||||
"O bed, delicious bed, that heaven on earth to the weary head,\" as sang\n"
|
||||
"poor Hood, you are a kind old nurse to us fretful boys and girls. Clever\n"
|
||||
"and foolish, naughty and good, you take us all in your motherly lap and\n"
|
||||
"hush our wayward crying. The strong man full of care--the sick man\n"
|
||||
"full of pain--the little maiden sobbing for her faithless lover--like\n"
|
||||
"children we lay our aching heads on your white bosom, and you gently\n"
|
||||
"soothe us off to by-by.\n"
|
||||
"\n"
|
||||
"Our trouble is sore indeed when you turn away and will not comfort us.\n"
|
||||
"How long the dawn seems coming when we cannot sleep! Oh! those hideous\n"
|
||||
"nights when we toss and turn in fever and pain, when we lie, like living\n"
|
||||
"men among the dead, staring out into the dark hours that drift so slowly\n"
|
||||
"between us and the light. And oh! those still more hideous nights when\n"
|
||||
"we sit by another in pain, when the low fire startles us every now and\n"
|
||||
"then with a falling cinder, and the tick of the clock seems a hammer\n"
|
||||
"beating out the life that we are watching.\n"
|
||||
"\n"
|
||||
"But enough of beds and bedrooms. I have kept to them too long, even for\n"
|
||||
"an idle fellow. Let us come out and have a smoke. That wastes time just\n"
|
||||
"as well and does not look so bad. Tobacco has been a blessing to us\n"
|
||||
"idlers. What the civil-service clerk before Sir Walter's time found\n"
|
||||
"to occupy their minds with it is hard to imagine. I attribute the\n"
|
||||
"quarrelsome nature of the Middle Ages young men entirely to the want of\n"
|
||||
"the soothing weed. They had no work to do and could not smoke, and\n"
|
||||
"the consequence was they were forever fighting and rowing. If, by any\n"
|
||||
"extraordinary chance, there was no war going, then they got up a deadly\n"
|
||||
"family feud with the next-door neighbor, and if, in spite of this, they\n"
|
||||
"still had a few spare moments on their hands, they occupied them with\n"
|
||||
"discussions as to whose sweetheart was the best looking, the arguments\n"
|
||||
"employed on both sides being battle-axes, clubs, etc. Questions of taste\n"
|
||||
"were soon decided in those days. When a twelfth-century youth fell in\n"
|
||||
"love he did not take three paces backward, gaze into her eyes, and tell\n"
|
||||
"her she was too beautiful to live. He said he would step outside and see\n"
|
||||
"about it. And if, when he got out, he met a man and broke his head--the\n"
|
||||
"other man's head, I mean--then that proved that his--the first\n"
|
||||
"fellow's--girl was a pretty girl. But if the other fellow broke _his_\n"
|
||||
"head--not his own, you know, but the other fellow's--the other fellow\n"
|
||||
"to the second fellow, that is, because of course the other fellow would\n"
|
||||
"only be the other fellow to him, not the first fellow who--well, if he\n"
|
||||
"broke his head, then _his_ girl--not the other fellow's, but the fellow\n"
|
||||
"who _was_ the--Look here, if A broke B's head, then A's girl was a\n"
|
||||
"pretty girl; but if B broke A's head, then A's girl wasn't a pretty\n"
|
||||
"girl, but B's girl was. That was their method of conducting art\n"
|
||||
"criticism.\n"
|
||||
"\n"
|
||||
"Nowadays we light a pipe and let the girls fight it out among\n"
|
||||
"themselves.\n"
|
||||
"\n"
|
||||
"They do it very well. They are getting to do all our work. They are\n"
|
||||
"doctors, and barristers, and artists. They manage theaters, and promote\n"
|
||||
"swindles, and edit newspapers. I am looking forward to the time when we\n"
|
||||
"men shall have nothing to do but lie in bed till twelve, read two novels\n"
|
||||
"a day, have nice little five-o'clock teas all to ourselves, and tax\n"
|
||||
"our brains with nothing more trying than discussions upon the latest\n"
|
||||
"patterns in trousers and arguments as to what Mr. Jones' coat was\n"
|
||||
"made of and whether it fitted him. It is a glorious prospect--for idle\n"
|
||||
"fellows.\n"
|
||||
"\n\n\n"
|
||||
;
|
||||
static const size_t IDLE_SIZE = sizeof(on_being_idle) - 1;
|
||||
#endif
|
||||
|
||||
/* This is the "LSWS" mode: first write is performed immediately, outside
|
||||
* of the on_write() callback. This makes it possible to play with buffered
|
||||
|
@ -43,11 +279,13 @@ static const size_t IDLE_SIZE;
|
|||
static int s_immediate_write;
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define V(v) (v), strlen(v)
|
||||
|
||||
struct lsquic_conn_ctx;
|
||||
|
||||
static void interop_server_hset_destroy (void *);
|
||||
|
||||
|
||||
struct server_ctx {
|
||||
struct lsquic_conn_ctx *conn_h;
|
||||
lsquic_engine_t *engine;
|
||||
|
@ -278,12 +516,14 @@ static int
|
|||
send_headers (struct lsquic_stream *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
const char *content_type;
|
||||
struct header_buf hbuf;
|
||||
|
||||
content_type = select_content_type(st_h);
|
||||
struct lsxpack_header headers_arr[2];
|
||||
|
||||
lsxpack_header_set_ptr(&headers_arr[0], ":status", 7, "200", 3);
|
||||
lsxpack_header_set_ptr(&headers_arr[1], "content-type", 12,
|
||||
hbuf.off = 0;
|
||||
header_set_ptr(&headers_arr[0], &hbuf, ":status", 7, "200", 3);
|
||||
header_set_ptr(&headers_arr[1], &hbuf, "content-type", 12,
|
||||
content_type, strlen(content_type));
|
||||
lsquic_http_headers_t headers = {
|
||||
.count = sizeof(headers_arr) / sizeof(headers_arr[0]),
|
||||
|
@ -301,7 +541,7 @@ send_headers (struct lsquic_stream *stream, lsquic_stream_ctx_t *st_h)
|
|||
|
||||
|
||||
static void
|
||||
resume_response (int fd, short what, void *arg)
|
||||
resume_response (evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
struct lsquic_stream_ctx *const st_h = arg;
|
||||
|
||||
|
@ -551,6 +791,7 @@ push_promise (lsquic_stream_ctx_t *st_h, lsquic_stream_t *stream)
|
|||
regex_t re;
|
||||
regmatch_t matches[2];
|
||||
struct hset_fm *hfm;
|
||||
struct header_buf hbuf;
|
||||
|
||||
s = regcomp(&re, "\r\nHost: *([[:alnum:].][[:alnum:].]*)\r\n",
|
||||
REG_EXTENDED|REG_ICASE);
|
||||
|
@ -577,16 +818,17 @@ push_promise (lsquic_stream_ctx_t *st_h, lsquic_stream_t *stream)
|
|||
}
|
||||
|
||||
#define V(v) (v), strlen(v)
|
||||
hbuf.off = 0;
|
||||
struct lsxpack_header headers_arr[6];
|
||||
lsxpack_header_set_ptr(&headers_arr[0], V(":method"), V("GET"));
|
||||
lsxpack_header_set_ptr(&headers_arr[1], V(":path"),
|
||||
header_set_ptr(&headers_arr[0], &hbuf, V(":method"), V("GET"));
|
||||
header_set_ptr(&headers_arr[1], &hbuf, V(":path"),
|
||||
V(st_h->server_ctx->push_path));
|
||||
lsxpack_header_set_ptr(&headers_arr[2], V(":authority"),
|
||||
header_set_ptr(&headers_arr[2], &hbuf, V(":authority"),
|
||||
st_h->req_buf + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
|
||||
lsxpack_header_set_ptr(&headers_arr[3], V(":scheme"), V("https"));
|
||||
lsxpack_header_set_ptr(&headers_arr[4], V("x-some-header"),
|
||||
header_set_ptr(&headers_arr[3], &hbuf, V(":scheme"), V("https"));
|
||||
header_set_ptr(&headers_arr[4], &hbuf, V("x-some-header"),
|
||||
V("x-some-value"));
|
||||
lsxpack_header_set_ptr(&headers_arr[5], V("x-kenny-status"),
|
||||
header_set_ptr(&headers_arr[5], &hbuf, V("x-kenny-status"),
|
||||
V("Oh my God! They killed Kenny!!! You bastards!"));
|
||||
lsquic_http_headers_t headers = {
|
||||
.count = sizeof(headers_arr) / sizeof(headers_arr[0]),
|
||||
|
@ -605,7 +847,6 @@ push_promise (lsquic_stream_ctx_t *st_h, lsquic_stream_t *stream)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
|
@ -641,7 +882,6 @@ static void
|
|||
http_server_on_read_regular (struct lsquic_stream *stream,
|
||||
lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
#if HAVE_OPEN_MEMSTREAM
|
||||
unsigned char buf[0x400];
|
||||
ssize_t nread;
|
||||
int s;
|
||||
|
@ -674,20 +914,22 @@ http_server_on_read_regular (struct lsquic_stream *stream,
|
|||
LSQ_ERROR("error reading: %s", strerror(errno));
|
||||
lsquic_stream_close(stream);
|
||||
}
|
||||
#else
|
||||
LSQ_ERROR("%s: open_memstream not supported\n", __func__);
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
http_server_on_read (struct lsquic_stream *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
#if HAVE_OPEN_MEMSTREAM
|
||||
if (lsquic_stream_is_pushed(stream))
|
||||
http_server_on_read_pushed(stream, st_h);
|
||||
else
|
||||
http_server_on_read_regular(stream, st_h);
|
||||
#else
|
||||
LSQ_ERROR("%s: open_memstream not supported\n", __func__);
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -716,6 +958,7 @@ const struct lsquic_stream_if http_server_if = {
|
|||
};
|
||||
|
||||
|
||||
#if HAVE_REGEX
|
||||
struct req_map
|
||||
{
|
||||
enum method method;
|
||||
|
@ -848,12 +1091,12 @@ read_md5 (void *ctx, const unsigned char *buf, size_t sz, int fin)
|
|||
static void
|
||||
http_server_interop_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
#define ERROR_RESP(code, args...) do { \
|
||||
LSQ_WARN(args); \
|
||||
#define ERROR_RESP(code, ...) do { \
|
||||
LSQ_WARN(__VA_ARGS__); \
|
||||
st_h->interop_handler = IOH_ERROR; \
|
||||
st_h->resp_status = #code; \
|
||||
st_h->interop_u.err.resp.sz = snprintf(st_h->interop_u.err.buf, \
|
||||
sizeof(st_h->interop_u.err.buf), args); \
|
||||
sizeof(st_h->interop_u.err.buf), __VA_ARGS__); \
|
||||
if (st_h->interop_u.err.resp.sz >= sizeof(st_h->interop_u.err.buf)) \
|
||||
st_h->interop_u.err.resp.sz = sizeof(st_h->interop_u.err.buf) - 1; \
|
||||
st_h->interop_u.err.resp.buf = st_h->interop_u.err.buf; \
|
||||
|
@ -1047,14 +1290,16 @@ send_headers2 (struct lsquic_stream *stream, struct lsquic_stream_ctx *st_h,
|
|||
size_t content_len)
|
||||
{
|
||||
char clbuf[0x20];
|
||||
struct header_buf hbuf;
|
||||
|
||||
snprintf(clbuf, sizeof(clbuf), "%zd", content_len);
|
||||
|
||||
hbuf.off = 0;
|
||||
struct lsxpack_header headers_arr[4];
|
||||
lsxpack_header_set_ptr(&headers_arr[0], V(":status"), V(st_h->resp_status));
|
||||
lsxpack_header_set_ptr(&headers_arr[1], V("server"), V(LITESPEED_ID));
|
||||
lsxpack_header_set_ptr(&headers_arr[2], V("content-type"), V("text/html"));
|
||||
lsxpack_header_set_ptr(&headers_arr[3], V("content-length"), V(clbuf));
|
||||
header_set_ptr(&headers_arr[0], &hbuf, V(":status"), V(st_h->resp_status));
|
||||
header_set_ptr(&headers_arr[1], &hbuf, V("server"), V(LITESPEED_ID));
|
||||
header_set_ptr(&headers_arr[2], &hbuf, V("content-type"), V("text/html"));
|
||||
header_set_ptr(&headers_arr[3], &hbuf, V("content-length"), V(clbuf));
|
||||
lsquic_http_headers_t headers = {
|
||||
.count = sizeof(headers_arr) / sizeof(headers_arr[0]),
|
||||
.headers = headers_arr,
|
||||
|
@ -1070,7 +1315,7 @@ idle_read (void *lsqr_ctx, void *buf, size_t count)
|
|||
{
|
||||
struct gen_file_ctx *const gfc = lsqr_ctx;
|
||||
unsigned char *p = buf;
|
||||
unsigned char *const end = buf + count;
|
||||
unsigned char *const end = p + count;
|
||||
size_t towrite;
|
||||
|
||||
while (p < end && gfc->remain > 0)
|
||||
|
@ -1133,6 +1378,7 @@ idle_on_write (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
|||
struct lsquic_http_headers headers;
|
||||
struct req *req;
|
||||
ssize_t nw;
|
||||
struct header_buf hbuf;
|
||||
|
||||
if (st_h->flags & SH_HEADERS_SENT)
|
||||
{
|
||||
|
@ -1158,10 +1404,11 @@ idle_on_write (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
|||
{
|
||||
STAILQ_REMOVE_HEAD(&gfc->push_paths, next);
|
||||
LSQ_DEBUG("pushing promise for %s", push_path->path);
|
||||
lsxpack_header_set_ptr(&header_arr[0], V(":method"), V("GET"));
|
||||
lsxpack_header_set_ptr(&header_arr[1], V(":path"), V(push_path->path));
|
||||
lsxpack_header_set_ptr(&header_arr[2], V(":authority"), V(st_h->req->authority_str));
|
||||
lsxpack_header_set_ptr(&header_arr[3], V(":scheme"), V("https"));
|
||||
hbuf.off = 0;
|
||||
header_set_ptr(&header_arr[0], &hbuf, V(":method"), V("GET"));
|
||||
header_set_ptr(&header_arr[1], &hbuf, V(":path"), V(push_path->path));
|
||||
header_set_ptr(&header_arr[2], &hbuf, V(":authority"), V(st_h->req->authority_str));
|
||||
header_set_ptr(&header_arr[3], &hbuf, V(":scheme"), V("https"));
|
||||
headers.headers = header_arr;
|
||||
headers.count = sizeof(header_arr) / sizeof(header_arr[0]);
|
||||
req = new_req(GET, push_path->path, st_h->req->authority_str);
|
||||
|
@ -1243,6 +1490,7 @@ const struct lsquic_stream_if interop_http_server_if = {
|
|||
.on_write = http_server_interop_on_write,
|
||||
.on_close = http_server_on_close,
|
||||
};
|
||||
#endif /* HAVE_REGEX */
|
||||
|
||||
|
||||
static void
|
||||
|
@ -1308,6 +1556,23 @@ interop_server_hset_prepare_decode (void *hset_p, struct lsxpack_header *xhdr,
|
|||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
char *
|
||||
strndup (const char *s, size_t n)
|
||||
{
|
||||
char *copy;
|
||||
|
||||
copy = malloc(n + 1);
|
||||
if (!copy)
|
||||
return NULL;
|
||||
|
||||
memcpy(copy, s, n);
|
||||
copy[n] = '\0';
|
||||
return copy;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
interop_server_hset_add_header (void *hset_p, struct lsxpack_header *xhdr)
|
||||
{
|
||||
|
@ -1403,6 +1668,11 @@ main (int argc, char **argv)
|
|||
struct server_ctx server_ctx;
|
||||
struct prog prog;
|
||||
|
||||
#if !(HAVE_OPEN_MEMSTREAM || HAVE_REGEX)
|
||||
fprintf(stderr, "cannot run server without regex or open_memstream\n");
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
memset(&server_ctx, 0, sizeof(server_ctx));
|
||||
TAILQ_INIT(&server_ctx.sports);
|
||||
server_ctx.prog = &prog;
|
||||
|
@ -1425,11 +1695,13 @@ main (int argc, char **argv)
|
|||
perror("stat");
|
||||
exit(2);
|
||||
}
|
||||
#ifndef WIN32
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
{
|
||||
fprintf(stderr, "`%s' is not a directory\n", optarg);
|
||||
exit(2);
|
||||
}
|
||||
#endif
|
||||
server_ctx.document_root = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
|
@ -1450,11 +1722,16 @@ main (int argc, char **argv)
|
|||
|
||||
if (!server_ctx.document_root)
|
||||
{
|
||||
#if HAVE_REGEX
|
||||
LSQ_NOTICE("Document root is not set: start in Interop Mode");
|
||||
init_map_regexes();
|
||||
prog.prog_api.ea_stream_if = &interop_http_server_if;
|
||||
prog.prog_api.ea_hsi_if = &header_bypass_api;
|
||||
prog.prog_api.ea_hsi_ctx = NULL;
|
||||
#else
|
||||
LSQ_ERROR("Document root is not set: use -r option");
|
||||
exit(EXIT_FAILURE);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (0 != prog_prep(&prog))
|
||||
|
@ -1468,233 +1745,10 @@ main (int argc, char **argv)
|
|||
s = prog_run(&prog);
|
||||
prog_cleanup(&prog);
|
||||
|
||||
#if HAVE_REGEX
|
||||
if (!server_ctx.document_root)
|
||||
free_map_regexes();
|
||||
#endif
|
||||
|
||||
exit(0 == s ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
static const char on_being_idle[] =
|
||||
"ON BEING IDLE.\n"
|
||||
"\n"
|
||||
"Now, this is a subject on which I flatter myself I really am _au fait_.\n"
|
||||
"The gentleman who, when I was young, bathed me at wisdom's font for nine\n"
|
||||
"guineas a term--no extras--used to say he never knew a boy who could\n"
|
||||
"do less work in more time; and I remember my poor grandmother once\n"
|
||||
"incidentally observing, in the course of an instruction upon the use\n"
|
||||
"of the Prayer-book, that it was highly improbable that I should ever do\n"
|
||||
"much that I ought not to do, but that she felt convinced beyond a doubt\n"
|
||||
"that I should leave undone pretty well everything that I ought to do.\n"
|
||||
"\n"
|
||||
"I am afraid I have somewhat belied half the dear old lady's prophecy.\n"
|
||||
"Heaven help me! I have done a good many things that I ought not to have\n"
|
||||
"done, in spite of my laziness. But I have fully confirmed the accuracy\n"
|
||||
"of her judgment so far as neglecting much that I ought not to have\n"
|
||||
"neglected is concerned. Idling always has been my strong point. I take\n"
|
||||
"no credit to myself in the matter--it is a gift. Few possess it. There\n"
|
||||
"are plenty of lazy people and plenty of slow-coaches, but a genuine\n"
|
||||
"idler is a rarity. He is not a man who slouches about with his hands in\n"
|
||||
"his pockets. On the contrary, his most startling characteristic is that\n"
|
||||
"he is always intensely busy.\n"
|
||||
"\n"
|
||||
"It is impossible to enjoy idling thoroughly unless one has plenty of\n"
|
||||
"work to do. There is no fun in doing nothing when you have nothing to\n"
|
||||
"do. Wasting time is merely an occupation then, and a most exhausting\n"
|
||||
"one. Idleness, like kisses, to be sweet must be stolen.\n"
|
||||
"\n"
|
||||
"Many years ago, when I was a young man, I was taken very ill--I never\n"
|
||||
"could see myself that much was the matter with me, except that I had\n"
|
||||
"a beastly cold. But I suppose it was something very serious, for the\n"
|
||||
"doctor said that I ought to have come to him a month before, and that\n"
|
||||
"if it (whatever it was) had gone on for another week he would not have\n"
|
||||
"answered for the consequences. It is an extraordinary thing, but I\n"
|
||||
"never knew a doctor called into any case yet but what it transpired\n"
|
||||
"that another day's delay would have rendered cure hopeless. Our medical\n"
|
||||
"guide, philosopher, and friend is like the hero in a melodrama--he\n"
|
||||
"always comes upon the scene just, and only just, in the nick of time. It\n"
|
||||
"is Providence, that is what it is.\n"
|
||||
"\n"
|
||||
"Well, as I was saying, I was very ill and was ordered to Buxton for a\n"
|
||||
"month, with strict injunctions to do nothing whatever all the while\n"
|
||||
"that I was there. \"Rest is what you require,\" said the doctor, \"perfect\n"
|
||||
"rest.\"\n"
|
||||
"\n"
|
||||
"It seemed a delightful prospect. \"This man evidently understands my\n"
|
||||
"complaint,\" said I, and I pictured to myself a glorious time--a four\n"
|
||||
"weeks' _dolce far niente_ with a dash of illness in it. Not too much\n"
|
||||
"illness, but just illness enough--just sufficient to give it the flavor\n"
|
||||
"of suffering and make it poetical. I should get up late, sip chocolate,\n"
|
||||
"and have my breakfast in slippers and a dressing-gown. I should lie out\n"
|
||||
"in the garden in a hammock and read sentimental novels with a melancholy\n"
|
||||
"ending, until the books should fall from my listless hand, and I should\n"
|
||||
"recline there, dreamily gazing into the deep blue of the firmament,\n"
|
||||
"watching the fleecy clouds floating like white-sailed ships across\n"
|
||||
"its depths, and listening to the joyous song of the birds and the low\n"
|
||||
"rustling of the trees. Or, on becoming too weak to go out of doors,\n"
|
||||
"I should sit propped up with pillows at the open window of the\n"
|
||||
"ground-floor front, and look wasted and interesting, so that all the\n"
|
||||
"pretty girls would sigh as they passed by.\n"
|
||||
"\n"
|
||||
"And twice a day I should go down in a Bath chair to the Colonnade to\n"
|
||||
"drink the waters. Oh, those waters! I knew nothing about them then,\n"
|
||||
"and was rather taken with the idea. \"Drinking the waters\" sounded\n"
|
||||
"fashionable and Queen Anne-fied, and I thought I should like them. But,\n"
|
||||
"ugh! after the first three or four mornings! Sam Weller's description of\n"
|
||||
"them as \"having a taste of warm flat-irons\" conveys only a faint idea of\n"
|
||||
"their hideous nauseousness. If anything could make a sick man get well\n"
|
||||
"quickly, it would be the knowledge that he must drink a glassful of them\n"
|
||||
"every day until he was recovered. I drank them neat for six consecutive\n"
|
||||
"days, and they nearly killed me; but after then I adopted the plan of\n"
|
||||
"taking a stiff glass of brandy-and-water immediately on the top of them,\n"
|
||||
"and found much relief thereby. I have been informed since, by various\n"
|
||||
"eminent medical gentlemen, that the alcohol must have entirely\n"
|
||||
"counteracted the effects of the chalybeate properties contained in the\n"
|
||||
"water. I am glad I was lucky enough to hit upon the right thing.\n"
|
||||
"\n"
|
||||
"But \"drinking the waters\" was only a small portion of the torture I\n"
|
||||
"experienced during that memorable month--a month which was, without\n"
|
||||
"exception, the most miserable I have ever spent. During the best part of\n"
|
||||
"it I religiously followed the doctor's mandate and did nothing whatever,\n"
|
||||
"except moon about the house and garden and go out for two hours a day in\n"
|
||||
"a Bath chair. That did break the monotony to a certain extent. There is\n"
|
||||
"more excitement about Bath-chairing--especially if you are not used to\n"
|
||||
"the exhilarating exercise--than might appear to the casual observer. A\n"
|
||||
"sense of danger, such as a mere outsider might not understand, is ever\n"
|
||||
"present to the mind of the occupant. He feels convinced every minute\n"
|
||||
"that the whole concern is going over, a conviction which becomes\n"
|
||||
"especially lively whenever a ditch or a stretch of newly macadamized\n"
|
||||
"road comes in sight. Every vehicle that passes he expects is going to\n"
|
||||
"run into him; and he never finds himself ascending or descending a\n"
|
||||
"hill without immediately beginning to speculate upon his chances,\n"
|
||||
"supposing--as seems extremely probable--that the weak-kneed controller\n"
|
||||
"of his destiny should let go.\n"
|
||||
"\n"
|
||||
"But even this diversion failed to enliven after awhile, and the _ennui_\n"
|
||||
"became perfectly unbearable. I felt my mind giving way under it. It is\n"
|
||||
"not a strong mind, and I thought it would be unwise to tax it too far.\n"
|
||||
"So somewhere about the twentieth morning I got up early, had a good\n"
|
||||
"breakfast, and walked straight off to Hayfield, at the foot of the\n"
|
||||
"Kinder Scout--a pleasant, busy little town, reached through a lovely\n"
|
||||
"valley, and with two sweetly pretty women in it. At least they were\n"
|
||||
"sweetly pretty then; one passed me on the bridge and, I think, smiled;\n"
|
||||
"and the other was standing at an open door, making an unremunerative\n"
|
||||
"investment of kisses upon a red-faced baby. But it is years ago, and I\n"
|
||||
"dare say they have both grown stout and snappish since that time.\n"
|
||||
"Coming back, I saw an old man breaking stones, and it roused such strong\n"
|
||||
"longing in me to use my arms that I offered him a drink to let me take\n"
|
||||
"his place. He was a kindly old man and he humored me. I went for those\n"
|
||||
"stones with the accumulated energy of three weeks, and did more work in\n"
|
||||
"half an hour than he had done all day. But it did not make him jealous.\n"
|
||||
"\n"
|
||||
"Having taken the plunge, I went further and further into dissipation,\n"
|
||||
"going out for a long walk every morning and listening to the band in\n"
|
||||
"the pavilion every evening. But the days still passed slowly\n"
|
||||
"notwithstanding, and I was heartily glad when the last one came and I\n"
|
||||
"was being whirled away from gouty, consumptive Buxton to London with its\n"
|
||||
"stern work and life. I looked out of the carriage as we rushed through\n"
|
||||
"Hendon in the evening. The lurid glare overhanging the mighty city\n"
|
||||
"seemed to warm my heart, and when, later on, my cab rattled out of St.\n"
|
||||
"Pancras' station, the old familiar roar that came swelling up around me\n"
|
||||
"sounded the sweetest music I had heard for many a long day.\n"
|
||||
"\n"
|
||||
"I certainly did not enjoy that month's idling. I like idling when I\n"
|
||||
"ought not to be idling; not when it is the only thing I have to do. That\n"
|
||||
"is my pig-headed nature. The time when I like best to stand with my\n"
|
||||
"back to the fire, calculating how much I owe, is when my desk is heaped\n"
|
||||
"highest with letters that must be answered by the next post. When I like\n"
|
||||
"to dawdle longest over my dinner is when I have a heavy evening's work\n"
|
||||
"before me. And if, for some urgent reason, I ought to be up particularly\n"
|
||||
"early in the morning, it is then, more than at any other time, that I\n"
|
||||
"love to lie an extra half-hour in bed.\n"
|
||||
"\n"
|
||||
"Ah! how delicious it is to turn over and go to sleep again: \"just for\n"
|
||||
"five minutes.\" Is there any human being, I wonder, besides the hero of\n"
|
||||
"a Sunday-school \"tale for boys,\" who ever gets up willingly? There\n"
|
||||
"are some men to whom getting up at the proper time is an utter\n"
|
||||
"impossibility. If eight o'clock happens to be the time that they should\n"
|
||||
"turn out, then they lie till half-past. If circumstances change and\n"
|
||||
"half-past eight becomes early enough for them, then it is nine before\n"
|
||||
"they can rise. They are like the statesman of whom it was said that he\n"
|
||||
"was always punctually half an hour late. They try all manner of schemes.\n"
|
||||
"They buy alarm-clocks (artful contrivances that go off at the wrong time\n"
|
||||
"and alarm the wrong people). They tell Sarah Jane to knock at the door\n"
|
||||
"and call them, and Sarah Jane does knock at the door and does call them,\n"
|
||||
"and they grunt back \"awri\" and then go comfortably to sleep again. I\n"
|
||||
"knew one man who would actually get out and have a cold bath; and even\n"
|
||||
"that was of no use, for afterward he would jump into bed again to warm\n"
|
||||
"himself.\n"
|
||||
"\n"
|
||||
"I think myself that I could keep out of bed all right if I once got\n"
|
||||
"out. It is the wrenching away of the head from the pillow that I find so\n"
|
||||
"hard, and no amount of over-night determination makes it easier. I say\n"
|
||||
"to myself, after having wasted the whole evening, \"Well, I won't do\n"
|
||||
"any more work to-night; I'll get up early to-morrow morning;\" and I am\n"
|
||||
"thoroughly resolved to do so--then. In the morning, however, I feel less\n"
|
||||
"enthusiastic about the idea, and reflect that it would have been much\n"
|
||||
"better if I had stopped up last night. And then there is the trouble of\n"
|
||||
"dressing, and the more one thinks about that the more one wants to put\n"
|
||||
"it off.\n"
|
||||
"\n"
|
||||
"It is a strange thing this bed, this mimic grave, where we stretch our\n"
|
||||
"tired limbs and sink away so quietly into the silence and rest. \"O bed,\n"
|
||||
"O bed, delicious bed, that heaven on earth to the weary head,\" as sang\n"
|
||||
"poor Hood, you are a kind old nurse to us fretful boys and girls. Clever\n"
|
||||
"and foolish, naughty and good, you take us all in your motherly lap and\n"
|
||||
"hush our wayward crying. The strong man full of care--the sick man\n"
|
||||
"full of pain--the little maiden sobbing for her faithless lover--like\n"
|
||||
"children we lay our aching heads on your white bosom, and you gently\n"
|
||||
"soothe us off to by-by.\n"
|
||||
"\n"
|
||||
"Our trouble is sore indeed when you turn away and will not comfort us.\n"
|
||||
"How long the dawn seems coming when we cannot sleep! Oh! those hideous\n"
|
||||
"nights when we toss and turn in fever and pain, when we lie, like living\n"
|
||||
"men among the dead, staring out into the dark hours that drift so slowly\n"
|
||||
"between us and the light. And oh! those still more hideous nights when\n"
|
||||
"we sit by another in pain, when the low fire startles us every now and\n"
|
||||
"then with a falling cinder, and the tick of the clock seems a hammer\n"
|
||||
"beating out the life that we are watching.\n"
|
||||
"\n"
|
||||
"But enough of beds and bedrooms. I have kept to them too long, even for\n"
|
||||
"an idle fellow. Let us come out and have a smoke. That wastes time just\n"
|
||||
"as well and does not look so bad. Tobacco has been a blessing to us\n"
|
||||
"idlers. What the civil-service clerk before Sir Walter's time found\n"
|
||||
"to occupy their minds with it is hard to imagine. I attribute the\n"
|
||||
"quarrelsome nature of the Middle Ages young men entirely to the want of\n"
|
||||
"the soothing weed. They had no work to do and could not smoke, and\n"
|
||||
"the consequence was they were forever fighting and rowing. If, by any\n"
|
||||
"extraordinary chance, there was no war going, then they got up a deadly\n"
|
||||
"family feud with the next-door neighbor, and if, in spite of this, they\n"
|
||||
"still had a few spare moments on their hands, they occupied them with\n"
|
||||
"discussions as to whose sweetheart was the best looking, the arguments\n"
|
||||
"employed on both sides being battle-axes, clubs, etc. Questions of taste\n"
|
||||
"were soon decided in those days. When a twelfth-century youth fell in\n"
|
||||
"love he did not take three paces backward, gaze into her eyes, and tell\n"
|
||||
"her she was too beautiful to live. He said he would step outside and see\n"
|
||||
"about it. And if, when he got out, he met a man and broke his head--the\n"
|
||||
"other man's head, I mean--then that proved that his--the first\n"
|
||||
"fellow's--girl was a pretty girl. But if the other fellow broke _his_\n"
|
||||
"head--not his own, you know, but the other fellow's--the other fellow\n"
|
||||
"to the second fellow, that is, because of course the other fellow would\n"
|
||||
"only be the other fellow to him, not the first fellow who--well, if he\n"
|
||||
"broke his head, then _his_ girl--not the other fellow's, but the fellow\n"
|
||||
"who _was_ the--Look here, if A broke B's head, then A's girl was a\n"
|
||||
"pretty girl; but if B broke A's head, then A's girl wasn't a pretty\n"
|
||||
"girl, but B's girl was. That was their method of conducting art\n"
|
||||
"criticism.\n"
|
||||
"\n"
|
||||
"Nowadays we light a pipe and let the girls fight it out among\n"
|
||||
"themselves.\n"
|
||||
"\n"
|
||||
"They do it very well. They are getting to do all our work. They are\n"
|
||||
"doctors, and barristers, and artists. They manage theaters, and promote\n"
|
||||
"swindles, and edit newspapers. I am looking forward to the time when we\n"
|
||||
"men shall have nothing to do but lie in bed till twelve, read two novels\n"
|
||||
"a day, have nice little five-o'clock teas all to ourselves, and tax\n"
|
||||
"our brains with nothing more trying than discussions upon the latest\n"
|
||||
"patterns in trousers and arguments as to what Mr. Jones' coat was\n"
|
||||
"made of and whether it fitted him. It is a glorious prospect--for idle\n"
|
||||
"fellows.\n"
|
||||
"\n\n\n"
|
||||
;
|
||||
static const size_t IDLE_SIZE = sizeof(on_being_idle) - 1;
|
||||
|
|
|
@ -10,11 +10,17 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include "vc_compat.h"
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <openssl/md5.h>
|
||||
|
|
17
bin/prog.c
17
bin/prog.c
|
@ -16,7 +16,8 @@
|
|||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <getopt.h>
|
||||
#include "vc_compat.h"
|
||||
#include "getopt.h"
|
||||
#pragma warning(disable:4028)
|
||||
#endif// WIN32
|
||||
|
||||
|
@ -47,11 +48,20 @@ static const struct lsquic_packout_mem_if pmi = {
|
|||
};
|
||||
|
||||
|
||||
void
|
||||
int
|
||||
prog_init (struct prog *prog, unsigned flags,
|
||||
struct sport_head *sports,
|
||||
const struct lsquic_stream_if *stream_if, void *stream_if_ctx)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WSADATA wsd;
|
||||
int s = WSAStartup(MAKEWORD(2, 2), &wsd);
|
||||
if (s != 0)
|
||||
{
|
||||
LSQ_ERROR("WSAStartup failed: %d", s);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/* prog-specific initialization: */
|
||||
memset(prog, 0, sizeof(*prog));
|
||||
prog->prog_engine_flags = flags;
|
||||
|
@ -82,6 +92,7 @@ prog_init (struct prog *prog, unsigned flags,
|
|||
LSQUIC_GLOBAL_CLIENT);
|
||||
lsquic_log_to_fstream(stderr, LLTS_HHMMSSMS);
|
||||
lsquic_logger_lopt("=notice");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -245,8 +256,10 @@ int supports_gso(void)
|
|||
int
|
||||
prog_set_opt (struct prog *prog, int opt, const char *arg)
|
||||
{
|
||||
#ifndef WIN32
|
||||
struct stat st;
|
||||
int s;
|
||||
#endif
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
|
|
|
@ -55,7 +55,7 @@ struct prog
|
|||
} prog_flags;
|
||||
};
|
||||
|
||||
void
|
||||
int
|
||||
prog_init (struct prog *, unsigned lsquic_engine_flags, struct sport_head *,
|
||||
const struct lsquic_stream_if *, void *stream_if_ctx);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ static int
|
|||
select_alpn (SSL *ssl, const unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen, void *arg)
|
||||
{
|
||||
const unsigned char alpn[] = "\x5h3-25\x5h3-27";
|
||||
const unsigned char alpn[] = "\x5h3-27\x5h3-28";
|
||||
int r;
|
||||
|
||||
r = SSL_select_next_proto((unsigned char **) out, outlen, in, inlen,
|
||||
|
|
|
@ -31,8 +31,13 @@
|
|||
#include <fcntl.h>
|
||||
|
||||
#include "test_config.h"
|
||||
|
||||
#if HAVE_REGEX
|
||||
#ifndef WIN32
|
||||
#include <regex.h>
|
||||
#else
|
||||
#include <pcreposix.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <event2/event.h>
|
||||
|
@ -40,6 +45,7 @@
|
|||
#include "test_common.h"
|
||||
#include "lsquic.h"
|
||||
#include "prog.h"
|
||||
#include "lsxpack_header.h"
|
||||
|
||||
#include "../src/liblsquic/lsquic_logger.h"
|
||||
|
||||
|
@ -50,16 +56,6 @@
|
|||
#define LSQUIC_USE_POOLS 1
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
# define SOCKET_TYPE int
|
||||
# define CLOSE_SOCKET close
|
||||
# define CHAR_CAST
|
||||
#else
|
||||
# define SOCKET_TYPE SOCKET
|
||||
# define CLOSE_SOCKET closesocket
|
||||
# define CHAR_CAST (char *)
|
||||
#endif
|
||||
|
||||
#if __linux__
|
||||
# define NDROPPED_SZ CMSG_SPACE(sizeof(uint32_t)) /* SO_RXQ_OVFL */
|
||||
#else
|
||||
|
@ -178,9 +174,10 @@ allocate_packets_in (SOCKET_TYPE fd)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
n_alloc = (unsigned) recvsz / MAX_PACKET_SZ * 2;
|
||||
n_alloc = (unsigned) recvsz / 1370;
|
||||
LSQ_INFO("socket buffer size: %d bytes; max # packets is set to %u",
|
||||
recvsz, n_alloc);
|
||||
recvsz += MAX_PACKET_SZ;
|
||||
|
||||
packs_in = malloc(sizeof(*packs_in));
|
||||
packs_in->data_sz = recvsz;
|
||||
|
@ -521,7 +518,9 @@ read_one_packet (struct read_iter *iter)
|
|||
packs_in->vecs[iter->ri_idx].len = MAX_PACKET_SZ;
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
top:
|
||||
#endif
|
||||
ctl_buf = packs_in->ctlmsg_data + iter->ri_idx * CTL_SZ;
|
||||
|
||||
#ifndef WIN32
|
||||
|
@ -800,7 +799,11 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
struct event_base *eb)
|
||||
{
|
||||
const struct sockaddr *sa_local = (struct sockaddr *) &sport->sas;
|
||||
int sockfd, saved_errno, flags, s, on;
|
||||
int sockfd, saved_errno, s;
|
||||
#ifndef WIN32
|
||||
int flags;
|
||||
#endif
|
||||
SOCKOPT_VAL on;
|
||||
socklen_t socklen;
|
||||
char addr_str[0x20];
|
||||
|
||||
|
@ -817,6 +820,9 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
return -1;
|
||||
}
|
||||
|
||||
#if WIN32
|
||||
getExtensionPtrs();
|
||||
#endif
|
||||
sockfd = socket(sa_local->sa_family, SOCK_DGRAM, 0);
|
||||
if (-1 == sockfd)
|
||||
return -1;
|
||||
|
@ -830,6 +836,7 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
}
|
||||
|
||||
/* Make socket non-blocking */
|
||||
#ifndef WIN32
|
||||
flags = fcntl(sockfd, F_GETFL);
|
||||
if (-1 == flags) {
|
||||
saved_errno = errno;
|
||||
|
@ -844,20 +851,33 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
errno = saved_errno;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
{
|
||||
u_long on = 1;
|
||||
ioctlsocket(sockfd, FIONBIO, &on);
|
||||
}
|
||||
#endif
|
||||
|
||||
on = 1;
|
||||
if (AF_INET == sa_local->sa_family)
|
||||
s = setsockopt(sockfd, IPPROTO_IP,
|
||||
#if __linux__ && defined(IP_RECVORIGDSTADDR)
|
||||
IP_RECVORIGDSTADDR,
|
||||
#elif __linux__ || __APPLE__
|
||||
#elif __linux__ || __APPLE__ || defined(WIN32)
|
||||
IP_PKTINFO,
|
||||
#else
|
||||
IP_RECVDSTADDR,
|
||||
#endif
|
||||
&on, sizeof(on));
|
||||
CHAR_CAST &on, sizeof(on));
|
||||
else
|
||||
{
|
||||
#ifndef WIN32
|
||||
s = setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
|
||||
#else
|
||||
s = setsockopt(sockfd, IPPROTO_IPV6, IPV6_PKTINFO, CHAR_CAST &on, sizeof(on));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (0 != s)
|
||||
{
|
||||
saved_errno = errno;
|
||||
|
@ -866,12 +886,12 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
return -1;
|
||||
}
|
||||
|
||||
#if (__linux__ && !defined(IP_RECVORIGDSTADDR)) || __APPLE__
|
||||
#if (__linux__ && !defined(IP_RECVORIGDSTADDR)) || __APPLE__ || defined(WIN32)
|
||||
/* Need to set IP_PKTINFO for sending */
|
||||
if (AF_INET == sa_local->sa_family)
|
||||
{
|
||||
on = 1;
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, CHAR_CAST &on, sizeof(on));
|
||||
if (0 != s)
|
||||
{
|
||||
saved_errno = errno;
|
||||
|
@ -933,7 +953,7 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
sizeof(on));
|
||||
#else
|
||||
on = 1;
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, &on, sizeof(on));
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, CHAR_CAST &on, sizeof(on));
|
||||
#endif
|
||||
if (0 != s)
|
||||
{
|
||||
|
@ -949,9 +969,9 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
#if ECN_SUPPORTED
|
||||
on = 1;
|
||||
if (AF_INET == sa_local->sa_family)
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_RECVTOS, &on, sizeof(on));
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_RECVTOS, CHAR_CAST &on, sizeof(on));
|
||||
else
|
||||
s = setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVTCLASS, &on, sizeof(on));
|
||||
s = setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVTCLASS, CHAR_CAST &on, sizeof(on));
|
||||
if (0 != s)
|
||||
{
|
||||
saved_errno = errno;
|
||||
|
@ -963,7 +983,7 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
|
||||
if (sport->sp_flags & SPORT_SET_SNDBUF)
|
||||
{
|
||||
s = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sport->sp_sndbuf,
|
||||
s = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, CHAR_CAST &sport->sp_sndbuf,
|
||||
sizeof(sport->sp_sndbuf));
|
||||
if (0 != s)
|
||||
{
|
||||
|
@ -976,7 +996,7 @@ sport_init_server (struct service_port *sport, struct lsquic_engine *engine,
|
|||
|
||||
if (sport->sp_flags & SPORT_SET_RCVBUF)
|
||||
{
|
||||
s = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sport->sp_rcvbuf,
|
||||
s = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, CHAR_CAST &sport->sp_rcvbuf,
|
||||
sizeof(sport->sp_rcvbuf));
|
||||
if (0 != s)
|
||||
{
|
||||
|
@ -1122,7 +1142,7 @@ sport_init_client (struct service_port *sport, struct lsquic_engine *engine,
|
|||
sizeof(on));
|
||||
#elif WIN32
|
||||
on = 1;
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAGMENT, (char*)&on, sizeof(on));
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAGMENT, CHAR_CAST &on, sizeof(on));
|
||||
#else
|
||||
on = 1;
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, &on, sizeof(on));
|
||||
|
@ -1142,10 +1162,11 @@ sport_init_client (struct service_port *sport, struct lsquic_engine *engine,
|
|||
{
|
||||
int on = 1;
|
||||
if (AF_INET == sa_local->sa_family)
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_RECVTOS, &on, sizeof(on));
|
||||
s = setsockopt(sockfd, IPPROTO_IP, IP_RECVTOS,
|
||||
CHAR_CAST &on, sizeof(on));
|
||||
else
|
||||
s = setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVTCLASS, &on,
|
||||
sizeof(on));
|
||||
s = setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVTCLASS,
|
||||
CHAR_CAST &on, sizeof(on));
|
||||
if (0 != s)
|
||||
{
|
||||
saved_errno = errno;
|
||||
|
@ -1549,6 +1570,7 @@ send_packets_one_by_one (const struct lsquic_out_spec *specs, unsigned count,
|
|||
#else
|
||||
DWORD bytes;
|
||||
WSAMSG msg;
|
||||
WSABUF wsaBuf;
|
||||
#endif
|
||||
union {
|
||||
/* cmsg(3) recommends union for proper alignment */
|
||||
|
@ -1612,12 +1634,14 @@ send_packets_one_by_one (const struct lsquic_out_spec *specs, unsigned count,
|
|||
msg.msg_iovlen = specs[n].iovlen;
|
||||
msg.msg_flags = 0;
|
||||
#else
|
||||
wsaBuf.buf = specs[n].iov->iov_base;
|
||||
wsaBuf.len = specs[n].iov->iov_len;
|
||||
msg.name = (void *) specs[n].dest_sa;
|
||||
msg.namelen = (AF_INET == specs[n].dest_sa->sa_family ?
|
||||
sizeof(struct sockaddr_in) :
|
||||
sizeof(struct sockaddr_in6)),
|
||||
msg.lpBuffers = specs[n].iov;
|
||||
msg.dwBufferCount = specs[n].iovlen;
|
||||
sizeof(struct sockaddr_in6));
|
||||
msg.dwBufferCount = 1;
|
||||
msg.lpBuffers = &wsaBuf;
|
||||
msg.dwFlags = 0;
|
||||
#endif
|
||||
if ((sport->sp_flags & SPORT_SERVER) && specs[n].local_sa->sa_family)
|
||||
|
@ -1882,13 +1906,13 @@ set_engine_option (struct lsquic_engine_settings *settings,
|
|||
settings->es_versions = 0;
|
||||
}
|
||||
enum lsquic_version ver = lsquic_str2ver(val, strlen(val));
|
||||
if (ver < N_LSQVER)
|
||||
if ((unsigned) ver < N_LSQVER)
|
||||
{
|
||||
settings->es_versions |= 1 << ver;
|
||||
return 0;
|
||||
}
|
||||
ver = lsquic_alpn2ver(val, strlen(val));
|
||||
if (ver < N_LSQVER)
|
||||
if ((unsigned) ver < N_LSQVER)
|
||||
{
|
||||
settings->es_versions |= 1 << ver;
|
||||
return 0;
|
||||
|
@ -2049,11 +2073,6 @@ set_engine_option (struct lsquic_engine_settings *settings,
|
|||
settings->es_qpack_dec_max_size = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
if (0 == strncmp(name, "max_packet_size_rx", 18))
|
||||
{
|
||||
settings->es_max_packet_size_rx = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
if (0 == strncmp(name, "max_header_list_size", 20))
|
||||
|
@ -2079,6 +2098,13 @@ set_engine_option (struct lsquic_engine_settings *settings,
|
|||
return 0;
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
if (0 == strncmp(name, "max_udp_payload_size_rx", 18))
|
||||
{
|
||||
settings->es_max_udp_payload_size_rx = atoi(val);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
if (0 == strncmp(name, "init_max_stream_data_uni", 24))
|
||||
{
|
||||
|
@ -2339,3 +2365,22 @@ sport_set_token (struct service_port *sport, const char *token_str)
|
|||
sport->sp_token_sz = len / 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
header_set_ptr (struct lsxpack_header *hdr, struct header_buf *header_buf,
|
||||
const char *name, size_t name_len,
|
||||
const char *val, size_t val_len)
|
||||
{
|
||||
if (header_buf->off + name_len + val_len <= sizeof(header_buf->buf))
|
||||
{
|
||||
memcpy(header_buf->buf + header_buf->off, name, name_len);
|
||||
memcpy(header_buf->buf + header_buf->off + name_len, val, val_len);
|
||||
lsxpack_header_set_offset2(hdr, header_buf->buf + header_buf->off,
|
||||
0, name_len, name_len, val_len);
|
||||
header_buf->off += name_len + val_len;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
# include <net/if.h> /* For IFNAMSIZ */
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
struct lsquic_engine;
|
||||
struct lsquic_engine_settings;
|
||||
struct lsquic_out_spec;
|
||||
|
@ -19,6 +24,19 @@ struct packets_in;
|
|||
struct lsquic_conn;
|
||||
struct prog;
|
||||
struct reader_ctx;
|
||||
struct lsxpack_header;
|
||||
|
||||
#ifndef WIN32
|
||||
# define SOCKOPT_VAL int
|
||||
# define SOCKET_TYPE int
|
||||
# define CLOSE_SOCKET close
|
||||
# define CHAR_CAST
|
||||
#else
|
||||
# define SOCKOPT_VAL DWORD
|
||||
# define SOCKET_TYPE SOCKET
|
||||
# define CLOSE_SOCKET closesocket
|
||||
# define CHAR_CAST (char *)
|
||||
#endif
|
||||
|
||||
enum sport_flags
|
||||
{
|
||||
|
@ -51,8 +69,8 @@ struct service_port {
|
|||
struct sockaddr_storage sp_local_addr;
|
||||
struct packets_in *packs_in;
|
||||
enum sport_flags sp_flags;
|
||||
int sp_sndbuf; /* If SPORT_SET_SNDBUF is set */
|
||||
int sp_rcvbuf; /* If SPORT_SET_RCVBUF is set */
|
||||
SOCKOPT_VAL sp_sndbuf; /* If SPORT_SET_SNDBUF is set */
|
||||
SOCKOPT_VAL sp_rcvbuf; /* If SPORT_SET_RCVBUF is set */
|
||||
struct prog *sp_prog;
|
||||
unsigned char *sp_token_buf;
|
||||
size_t sp_token_sz;
|
||||
|
@ -140,4 +158,15 @@ destroy_lsquic_reader_ctx (struct reader_ctx *ctx);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
struct header_buf
|
||||
{
|
||||
unsigned off;
|
||||
char buf[UINT16_MAX];
|
||||
};
|
||||
|
||||
int
|
||||
header_set_ptr (struct lsxpack_header *hdr, struct header_buf *header_buf,
|
||||
const char *name, size_t name_len,
|
||||
const char *val, size_t val_len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -693,7 +693,7 @@ settings structure:
|
|||
|
||||
Default value is @ref LSQUIC_DF_TIMESTAMPS
|
||||
|
||||
.. member:: unsigned short es_max_packet_size_rx
|
||||
.. member:: unsigned short es_max_udp_payload_size_rx
|
||||
|
||||
Maximum packet size we are willing to receive. This is sent to
|
||||
peer in transport parameters: the library does not enforce this
|
||||
|
@ -701,7 +701,7 @@ settings structure:
|
|||
|
||||
If set to zero, limit is not set.
|
||||
|
||||
Default value is :macro:`LSQUIC_DF_MAX_PACKET_SIZE_RX`
|
||||
Default value is :macro:`LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX`
|
||||
|
||||
To initialize the settings structure to library defaults, use the following
|
||||
convenience function:
|
||||
|
@ -877,7 +877,7 @@ out of date. Please check your :file:`lsquic.h` for actual values.*
|
|||
|
||||
Delayed ACKs are off by default.
|
||||
|
||||
.. macro:: LSQUIC_DF_MAX_PACKET_SIZE_RX
|
||||
.. macro:: LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
|
||||
|
||||
By default, incoming packet size is not limited.
|
||||
|
||||
|
@ -1099,7 +1099,7 @@ callback.
|
|||
|
||||
In client mode, a new connection is created by
|
||||
|
||||
.. function:: lsquic_conn_t * lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version, const struct sockaddr *local_sa, const struct sockaddr *peer_sa, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, const char *sni, unsigned short max_packet_size, const unsigned char *zero_rtt, size_t zero_rtt_len, const unsigned char *token, size_t token_sz)
|
||||
.. function:: lsquic_conn_t * lsquic_engine_connect (lsquic_engine_t *engine, enum lsquic_version version, const struct sockaddr *local_sa, const struct sockaddr *peer_sa, void *peer_ctx, lsquic_conn_ctx_t *conn_ctx, const char *sni, unsigned short max_udp_payload_size, const unsigned char *zero_rtt, size_t zero_rtt_len, const unsigned char *token, size_t token_sz)
|
||||
|
||||
:param engine: Engine to use.
|
||||
|
||||
|
@ -1132,7 +1132,7 @@ In client mode, a new connection is created by
|
|||
The SNI is required for Google QUIC connections; it is optional for
|
||||
IETF QUIC and may be set to NULL.
|
||||
|
||||
:param max_packet_size:
|
||||
:param max_udp_payload_size:
|
||||
|
||||
Maximum packet size. If set to zero, it is inferred based on `peer_sa`
|
||||
and `version`.
|
||||
|
@ -1168,11 +1168,7 @@ Closing Connections
|
|||
Mark connection as going away: send GOAWAY frame and do not accept
|
||||
any more incoming streams, nor generate streams of our own.
|
||||
|
||||
In the server mode, of course, we can call this function just fine in both
|
||||
Google and IETF QUIC.
|
||||
|
||||
In client mode, calling this function in for an IETF QUIC connection does
|
||||
not do anything, as the client MUST NOT send GOAWAY frames.
|
||||
Only applicable to HTTP/3 and GQUIC connections. Otherwise a no-op.
|
||||
|
||||
.. function:: void lsquic_conn_close (lsquic_conn_t *conn)
|
||||
|
||||
|
@ -1531,7 +1527,9 @@ fields yourself. In that case, the header set must be "read" from the stream vi
|
|||
.. member:: enum lsquic_hsi_flag hsi_flags
|
||||
|
||||
These flags specify properties of decoded headers passed to
|
||||
``hsi_process_header()``.
|
||||
``hsi_process_header()``. This is only applicable to QPACK headers;
|
||||
HPACK library header properties are based on compilation, not
|
||||
run-time, options.
|
||||
|
||||
.. function:: void * lsquic_stream_get_hset (lsquic_stream_t *stream)
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@ copyright = u'2020, LiteSpeed Technologies'
|
|||
author = u'LiteSpeed Technologies'
|
||||
|
||||
# The short X.Y version
|
||||
version = u'2.14'
|
||||
version = u'2.16'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.14.8'
|
||||
release = u'2.16.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
|
@ -4,10 +4,8 @@ Getting Started
|
|||
Supported Platforms
|
||||
-------------------
|
||||
|
||||
LSQUIC compiles and runs on Linux, FreeBSD, Mac OS, and Android. It has been
|
||||
tested on i386, x86_64, and ARM (Raspberry Pi and Android).
|
||||
|
||||
Windows support is on the TODO list.
|
||||
LSQUIC compiles and runs on Linux, Windows, FreeBSD, Mac OS, and Android.
|
||||
It has been tested on i386, x86_64, and ARM (Raspberry Pi and Android).
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
@ -25,8 +23,8 @@ What's in the box
|
|||
-----------------
|
||||
|
||||
- ``src/liblsquic`` -- the library
|
||||
- ``test`` -- demo client and server programs
|
||||
- ``test/unittests`` -- unit tests
|
||||
- ``bin`` -- demo client and server programs
|
||||
- ``tests`` -- unit tests
|
||||
|
||||
Building
|
||||
--------
|
||||
|
|
|
@ -16,7 +16,7 @@ Most of the code in this distribution has been used in our own products
|
|||
-- `LiteSpeed Web Server`_, `LiteSpeed Web ADC`_, and OpenLiteSpeed_ --
|
||||
since 2017.
|
||||
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-25, and ID-27.
|
||||
Currently supported QUIC versions are Q043, Q046, Q050, ID-27, and ID-28.
|
||||
Support for newer versions will be added soon after they are released.
|
||||
|
||||
LSQUIC is licensed under the `MIT License`_; see LICENSE in the source
|
||||
|
|
|
@ -24,8 +24,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 14
|
||||
#define LSQUIC_PATCH_VERSION 8
|
||||
#define LSQUIC_MINOR_VERSION 16
|
||||
#define LSQUIC_PATCH_VERSION 0
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
@ -76,16 +76,16 @@ enum lsquic_version
|
|||
#define LSQUIC_EXPERIMENTAL_Q098 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IETF QUIC Draft-25
|
||||
*/
|
||||
LSQVER_ID25,
|
||||
|
||||
/**
|
||||
* IETF QUIC Draft-27
|
||||
*/
|
||||
LSQVER_ID27,
|
||||
|
||||
/**
|
||||
* IETF QUIC Draft-28
|
||||
*/
|
||||
LSQVER_ID28,
|
||||
|
||||
/**
|
||||
* Special version to trigger version negotiation.
|
||||
* [draft-ietf-quic-transport-11], Section 3.
|
||||
|
@ -96,7 +96,7 @@ enum lsquic_version
|
|||
};
|
||||
|
||||
/**
|
||||
* We currently support versions 43, 46, 50, Draft-25, and Draft-27.
|
||||
* We currently support versions 43, 46, 50, Draft-27, and Draft-28.
|
||||
* @see lsquic_version
|
||||
*/
|
||||
#define LSQUIC_SUPPORTED_VERSIONS ((1 << N_LSQVER) - 1)
|
||||
|
@ -113,10 +113,10 @@ enum lsquic_version
|
|||
|
||||
#define LSQUIC_GQUIC_HEADER_VERSIONS (1 << LSQVER_043)
|
||||
|
||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID25) | (1 << LSQVER_ID27) \
|
||||
#define LSQUIC_IETF_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
|
||||
| (1 << LSQVER_VERNEG))
|
||||
|
||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID25) | (1 << LSQVER_ID27) \
|
||||
#define LSQUIC_IETF_DRAFT_VERSIONS ((1 << LSQVER_ID27) | (1 << LSQVER_ID28) \
|
||||
| (1 << LSQVER_VERNEG))
|
||||
|
||||
enum lsquic_hsk_status
|
||||
|
@ -341,7 +341,7 @@ typedef struct ssl_ctx_st * (*lsquic_lookup_cert_f)(
|
|||
#define LSQUIC_DF_CC_ALGO 1
|
||||
|
||||
/** By default, incoming packet size is not limited. */
|
||||
#define LSQUIC_DF_MAX_PACKET_SIZE_RX 0
|
||||
#define LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX 0
|
||||
|
||||
struct lsquic_engine_settings {
|
||||
/**
|
||||
|
@ -749,9 +749,9 @@ struct lsquic_engine_settings {
|
|||
*
|
||||
* If set to zero, limit is not set.
|
||||
*
|
||||
* Default value is @ref LSQUIC_DF_MAX_PACKET_SIZE_RX
|
||||
* Default value is @ref LSQUIC_DF_MAX_UDP_PAYLOAD_SIZE_RX
|
||||
*/
|
||||
unsigned short es_max_packet_size_rx;
|
||||
unsigned short es_max_udp_payload_size_rx;
|
||||
};
|
||||
|
||||
/* Initialize `settings' to default values */
|
||||
|
@ -943,7 +943,9 @@ struct lsquic_hset_if
|
|||
void (*hsi_discard_header_set)(void *hdr_set);
|
||||
/**
|
||||
* These flags specify properties of decoded headers passed to
|
||||
* hsi_process_header().
|
||||
* hsi_process_header(). This is only applicable to QPACK headers;
|
||||
* HPACK library header properties are based on compilation, not
|
||||
* run-time, options.
|
||||
*/
|
||||
enum lsquic_hsi_flag hsi_flags;
|
||||
};
|
||||
|
@ -1078,7 +1080,7 @@ lsquic_engine_new (unsigned lsquic_engine_flags,
|
|||
* To let the engine specify QUIC version, use N_LSQVER. If zero-rtt info
|
||||
* is supplied, version is picked from there instead.
|
||||
*
|
||||
* If `max_packet_size' is set to zero, it is inferred based on `peer_sa':
|
||||
* If `max_udp_payload_size' is set to zero, it is inferred based on `peer_sa':
|
||||
* 1350 for IPv6 and 1370 for IPv4.
|
||||
*/
|
||||
lsquic_conn_t *
|
||||
|
@ -1086,7 +1088,7 @@ lsquic_engine_connect (lsquic_engine_t *, enum lsquic_version,
|
|||
const struct sockaddr *local_sa,
|
||||
const struct sockaddr *peer_sa,
|
||||
void *peer_ctx, lsquic_conn_ctx_t *conn_ctx,
|
||||
const char *hostname, unsigned short max_packet_size,
|
||||
const char *hostname, unsigned short max_udp_payload_size,
|
||||
const unsigned char *zero_rtt, size_t zero_rtt_len,
|
||||
/** Resumption token: optional */
|
||||
const unsigned char *token, size_t token_sz);
|
||||
|
@ -1174,12 +1176,7 @@ lsquic_conn_cancel_pending_streams (lsquic_conn_t *, unsigned n);
|
|||
* Mark connection as going away: send GOAWAY frame and do not accept
|
||||
* any more incoming streams, nor generate streams of our own.
|
||||
*
|
||||
* In the server mode, of course, we can call this function just fine in both
|
||||
* Google and IETF QUIC.
|
||||
*
|
||||
* In client mode, calling this function in for an IETF QUIC connection does
|
||||
* not do anything, as the client MUST NOT send GOAWAY frames.
|
||||
* See [draft-ietf-quic-http-17] Section 4.2.7.
|
||||
* Only applicable to HTTP/3 and GQUIC connections. Otherwise a no-op.
|
||||
*/
|
||||
void
|
||||
lsquic_conn_going_away (lsquic_conn_t *);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#ifndef LSXPACK_HEADER_H_v205
|
||||
#define LSXPACK_HEADER_H_v205
|
||||
#ifndef LSXPACK_HEADER_H_v206
|
||||
#define LSXPACK_HEADER_H_v206
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -26,7 +26,7 @@ typedef uint32_t lsxpack_strlen_t;
|
|||
|
||||
enum lsxpack_flag
|
||||
{
|
||||
LSXPACK_HPACK_IDX = 1,
|
||||
LSXPACK_HPACK_VAL_MATCHED = 1,
|
||||
LSXPACK_QPACK_IDX = 2,
|
||||
LSXPACK_APP_IDX = 4,
|
||||
LSXPACK_NAME_HASH = 8,
|
||||
|
@ -47,7 +47,6 @@ enum lsxpack_flag
|
|||
struct lsxpack_header
|
||||
{
|
||||
char *buf; /* the buffer for headers */
|
||||
const char *name_ptr; /* the name pointer can be optionally set for encoding */
|
||||
uint32_t name_hash; /* hash value for name */
|
||||
uint32_t nameval_hash; /* hash value for name + value */
|
||||
lsxpack_strlen_t name_offset; /* the offset for name in the buffer */
|
||||
|
@ -74,7 +73,6 @@ lsxpack_header_set_idx(lsxpack_header_t *hdr, int hpack_idx,
|
|||
hdr->buf = (char *)val;
|
||||
hdr->hpack_index = hpack_idx;
|
||||
assert(hpack_idx != 0);
|
||||
hdr->flags = LSXPACK_HPACK_IDX;
|
||||
assert(val_len <= LSXPACK_MAX_STRLEN);
|
||||
hdr->val_len = val_len;
|
||||
}
|
||||
|
@ -94,21 +92,6 @@ lsxpack_header_set_qpack_idx(lsxpack_header_t *hdr, int qpack_idx,
|
|||
}
|
||||
|
||||
|
||||
static inline void
|
||||
lsxpack_header_set_ptr(lsxpack_header_t *hdr,
|
||||
const char *name, size_t name_len,
|
||||
const char *val, size_t val_len)
|
||||
{
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
hdr->buf = (char *)val;
|
||||
assert(val_len <= LSXPACK_MAX_STRLEN);
|
||||
hdr->val_len = val_len;
|
||||
hdr->name_ptr = name;
|
||||
assert(name_len <= LSXPACK_MAX_STRLEN);
|
||||
hdr->name_len = name_len;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
lsxpack_header_set_offset(lsxpack_header_t *hdr, const char *buf,
|
||||
size_t name_offset, size_t name_len,
|
||||
|
@ -161,9 +144,7 @@ lsxpack_header_prepare_decode(lsxpack_header_t *hdr,
|
|||
static inline const char *
|
||||
lsxpack_header_get_name(const lsxpack_header_t *hdr)
|
||||
{
|
||||
return hdr->name_ptr ? hdr->name_ptr
|
||||
: (hdr->name_len) ? hdr->buf + hdr->name_offset
|
||||
: NULL;
|
||||
return (hdr->name_len)? hdr->buf + hdr->name_offset : NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -179,10 +160,10 @@ static inline void
|
|||
lsxpack_header_mark_val_changed(lsxpack_header_t *hdr)
|
||||
{
|
||||
hdr->flags = (enum lsxpack_flag)(hdr->flags &
|
||||
~(LSXPACK_VAL_MATCHED|LSXPACK_NAMEVAL_HASH));
|
||||
~(LSXPACK_HPACK_VAL_MATCHED|LSXPACK_VAL_MATCHED|LSXPACK_NAMEVAL_HASH));
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //LSXPACK_HEADER_H_v205
|
||||
#endif //LSXPACK_HEADER_H_v206
|
||||
|
|
|
@ -79,7 +79,9 @@ SET(lsquic_STAT_SRCS
|
|||
lsquic_version.c
|
||||
)
|
||||
|
||||
IF(NOT MSVC)
|
||||
set_source_files_properties(ls-qpack/lsqpack.c PROPERTIES COMPILE_FLAGS -Wno-uninitialized)
|
||||
ENDIF()
|
||||
|
||||
include_directories(ls-qpack)
|
||||
|
||||
|
@ -95,8 +97,8 @@ ENDIF()
|
|||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/lsquic_versions_to_string.c
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/gen-verstrs.pl
|
||||
ARGS ${CMAKE_CURRENT_SOURCE_DIR}/../../include/lsquic.h ${CMAKE_CURRENT_SOURCE_DIR}/lsquic_versions_to_string.c
|
||||
COMMAND ${PERL}
|
||||
ARGS ${CMAKE_CURRENT_SOURCE_DIR}/gen-verstrs.pl ${CMAKE_CURRENT_SOURCE_DIR}/../../include/lsquic.h ${CMAKE_CURRENT_SOURCE_DIR}/lsquic_versions_to_string.c
|
||||
DEPENDS ./gen-verstrs.pl ${CMAKE_CURRENT_SOURCE_DIR}/../../include/lsquic.h
|
||||
)
|
||||
SET(lsquic_STAT_SRCS ${lsquic_STAT_SRCS} lsquic_versions_to_string.c)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit f41613843f6164bb83993e435e8a164c1bb157e2
|
||||
Subproject commit a8ae6ef90197df0620ffd51891fb16016b1bb807
|
|
@ -33,6 +33,8 @@ enum alarm_id {
|
|||
AL_PATH_CHAL,
|
||||
AL_PATH_CHAL_0 = AL_PATH_CHAL,
|
||||
AL_PATH_CHAL_1,
|
||||
AL_PATH_CHAL_2,
|
||||
AL_PATH_CHAL_3,
|
||||
AL_SESS_TICKET,
|
||||
AL_BLOCKED_KA, /* Blocked Keep-Alive */
|
||||
MAX_LSQUIC_ALARMS
|
||||
|
@ -51,6 +53,8 @@ enum alarm_id_bit {
|
|||
ALBIT_CID_THROT = 1 << AL_CID_THROT,
|
||||
ALBIT_PATH_CHAL_0 = 1 << AL_PATH_CHAL_0,
|
||||
ALBIT_PATH_CHAL_1 = 1 << AL_PATH_CHAL_1,
|
||||
ALBIT_PATH_CHAL_2 = 1 << AL_PATH_CHAL_2,
|
||||
ALBIT_PATH_CHAL_3 = 1 << AL_PATH_CHAL_3,
|
||||
ALBIT_SESS_TICKET = 1 << AL_SESS_TICKET,
|
||||
ALBIT_BLOCKED_KA = 1 << AL_BLOCKED_KA,
|
||||
};
|
||||
|
|
|
@ -180,7 +180,7 @@ init_bbr (struct lsquic_bbr *bbr)
|
|||
bbr->bbr_min_cwnd = kDefaultMinimumCongestionWindow;
|
||||
bbr->bbr_high_gain = kDefaultHighGain;
|
||||
bbr->bbr_high_cwnd_gain = kDefaultHighGain;
|
||||
bbr->bbr_drain_gain = 1.0 / kDefaultHighGain;
|
||||
bbr->bbr_drain_gain = 1.0f / kDefaultHighGain;
|
||||
bbr->bbr_pacing_rate = BW_ZERO();
|
||||
bbr->bbr_pacing_gain = 1.0;
|
||||
bbr->bbr_cwnd_gain = 1.0;
|
||||
|
@ -298,7 +298,7 @@ is_pipe_sufficiently_full (struct lsquic_bbr *bbr, uint64_t bytes_in_flight)
|
|||
else
|
||||
// If bytes_in_flight are above the target congestion window, it should
|
||||
// be possible to observe the same or more bandwidth if it's available.
|
||||
return bytes_in_flight >= get_target_cwnd(bbr, 1.1);
|
||||
return bytes_in_flight >= get_target_cwnd(bbr, 1.1f);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -79,11 +79,11 @@ bw_sampler_abort_conn (struct bw_sampler *sampler)
|
|||
}
|
||||
|
||||
|
||||
#define BW_WARN_ONCE(msg...) do { \
|
||||
#define BW_WARN_ONCE(...) do { \
|
||||
if (!(sampler->bws_flags & BWS_WARNED)) \
|
||||
{ \
|
||||
sampler->bws_flags |= BWS_WARNED; \
|
||||
LSQ_WARN(msg); \
|
||||
LSQ_WARN(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
|
|
@ -243,6 +243,10 @@ struct conn_iface
|
|||
/* Optional method. Only used by the IETF client code. */
|
||||
void
|
||||
(*ci_drop_crypto_streams) (struct lsquic_conn *);
|
||||
|
||||
/* Optional method. Only used by IETF connections */
|
||||
void
|
||||
(*ci_count_garbage) (struct lsquic_conn *, size_t);
|
||||
};
|
||||
|
||||
#define LSCONN_CCE_BITS 3
|
||||
|
|
|
@ -276,6 +276,9 @@ struct enc_session_funcs_iquic
|
|||
(*esfi_reset_dcid) (enc_session_t *, const struct lsquic_cid *,
|
||||
const struct lsquic_cid *);
|
||||
|
||||
void
|
||||
(*esfi_set_iscid) (enc_session_t *, const struct lsquic_packet_in *);
|
||||
|
||||
int
|
||||
(*esfi_init_server) (enc_session_t *);
|
||||
|
||||
|
@ -288,7 +291,8 @@ struct enc_session_funcs_iquic
|
|||
const struct lsquic_cid *,
|
||||
void *(crypto_streams)[4],
|
||||
const struct crypto_stream_if *,
|
||||
const struct lsquic_cid *odcid);
|
||||
const struct lsquic_cid *odcid,
|
||||
const struct lsquic_cid *iscid );
|
||||
|
||||
void
|
||||
(*esfi_shake_stream)(enc_session_t *, struct lsquic_stream *,
|
||||
|
@ -328,8 +332,8 @@ struct enc_session_funcs_gquic lsquic_enc_session_gquic_gquic_1;
|
|||
extern const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1;
|
||||
|
||||
#define select_esf_common_by_ver(ver) ( \
|
||||
ver == LSQVER_ID25 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_ID27 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_ID28 ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_VERNEG ? &lsquic_enc_session_common_ietf_v1 : \
|
||||
ver == LSQVER_050 ? &lsquic_enc_session_common_gquic_2 : \
|
||||
&lsquic_enc_session_common_gquic_1 )
|
||||
|
|
|
@ -71,9 +71,9 @@ static const struct alpn_map {
|
|||
enum lsquic_version version;
|
||||
const unsigned char *alpn;
|
||||
} s_h3_alpns[] = {
|
||||
{ LSQVER_ID25, (unsigned char *) "\x05h3-25", },
|
||||
{ LSQVER_ID27, (unsigned char *) "\x05h3-27", },
|
||||
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-27", },
|
||||
{ LSQVER_ID28, (unsigned char *) "\x05h3-28", },
|
||||
{ LSQVER_VERNEG, (unsigned char *) "\x05h3-28", },
|
||||
};
|
||||
|
||||
struct enc_sess_iquic;
|
||||
|
@ -221,6 +221,8 @@ struct enc_sess_iquic
|
|||
struct header_prot *esi_hsk_hps;
|
||||
lsquic_packno_t esi_max_packno[N_PNS];
|
||||
lsquic_cid_t esi_odcid;
|
||||
lsquic_cid_t esi_rscid; /* Retry SCID */
|
||||
lsquic_cid_t esi_iscid; /* Initial SCID */
|
||||
unsigned esi_key_phase;
|
||||
enum {
|
||||
ESI_INITIALIZED = 1 << 0,
|
||||
|
@ -237,6 +239,9 @@ struct enc_sess_iquic
|
|||
ESI_WANT_TICKET = 1 << 11,
|
||||
ESI_RECV_QL_BITS = 1 << 12,
|
||||
ESI_SEND_QL_BITS = 1 << 13,
|
||||
ESI_RSCID = 1 << 14,
|
||||
ESI_ISCID = 1 << 15,
|
||||
ESI_RETRY = 1 << 16, /* Connection was retried */
|
||||
} esi_flags;
|
||||
enum evp_aead_direction_t
|
||||
esi_dir[2]; /* client, server */
|
||||
|
@ -429,9 +434,15 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
|
|||
const struct lsquic_engine_settings *const settings =
|
||||
&enc_sess->esi_enpub->enp_settings;
|
||||
struct transport_params params;
|
||||
const enum lsquic_version version = enc_sess->esi_conn->cn_version;
|
||||
int len;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
if (version > LSQVER_ID27)
|
||||
{
|
||||
params.tp_initial_source_cid = *CN_SCID(enc_sess->esi_conn);
|
||||
params.tp_set |= 1 << TPI_INITIAL_SOURCE_CID;
|
||||
}
|
||||
if (enc_sess->esi_flags & ESI_SERVER)
|
||||
{
|
||||
const struct lsquic_conn *const lconn = enc_sess->esi_conn;
|
||||
|
@ -442,8 +453,8 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
|
|||
|
||||
if (enc_sess->esi_flags & ESI_ODCID)
|
||||
{
|
||||
params.tp_original_cid = enc_sess->esi_odcid;
|
||||
params.tp_set |= 1 << TPI_ORIGINAL_CONNECTION_ID;
|
||||
params.tp_original_dest_cid = enc_sess->esi_odcid;
|
||||
params.tp_set |= 1 << TPI_ORIGINAL_DEST_CID;
|
||||
}
|
||||
#if LSQUIC_PREFERRED_ADDR
|
||||
char addr_buf[INET6_ADDRSTRLEN + 6 /* port */ + 1];
|
||||
|
@ -544,10 +555,10 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
|
|||
| (1 << TPI_MAX_ACK_DELAY)
|
||||
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT)
|
||||
;
|
||||
if (settings->es_max_packet_size_rx)
|
||||
if (settings->es_max_udp_payload_size_rx)
|
||||
{
|
||||
params.tp_max_packet_size = settings->es_max_packet_size_rx;
|
||||
params.tp_set |= 1 << TPI_MAX_PACKET_SIZE;
|
||||
params.tp_max_udp_payload_size = settings->es_max_udp_payload_size_rx;
|
||||
params.tp_set |= 1 << TPI_MAX_UDP_PAYLOAD_SIZE;
|
||||
}
|
||||
if (!settings->es_allow_migration)
|
||||
params.tp_set |= 1 << TPI_DISABLE_ACTIVE_MIGRATION;
|
||||
|
@ -564,10 +575,15 @@ gen_trans_params (struct enc_sess_iquic *enc_sess, unsigned char *buf,
|
|||
if (settings->es_timestamps)
|
||||
params.tp_set |= 1 << TPI_TIMESTAMPS;
|
||||
|
||||
len = (enc_sess->esi_conn->cn_version == LSQVER_ID25 ? lsquic_tp_encode_id25 :
|
||||
lsquic_tp_encode)(¶ms, enc_sess->esi_flags & ESI_SERVER, buf, bufsz);
|
||||
len = (version == LSQVER_ID27 ? lsquic_tp_encode_27 : lsquic_tp_encode)(
|
||||
¶ms, enc_sess->esi_flags & ESI_SERVER, buf, bufsz);
|
||||
if (len >= 0)
|
||||
{
|
||||
char str[MAX_TP_STR_SZ];
|
||||
LSQ_DEBUG("generated transport parameters buffer of %d bytes", len);
|
||||
LSQ_DEBUG("%s", ((version == LSQVER_ID27 ? lsquic_tp_to_str_27
|
||||
: lsquic_tp_to_str)(¶ms, str, sizeof(str)), str));
|
||||
}
|
||||
else
|
||||
LSQ_WARN("cannot generate transport parameters: %d", errno);
|
||||
return len;
|
||||
|
@ -726,6 +742,9 @@ iquic_esfi_create_client (const char *hostname,
|
|||
enc_sess->esi_dir[0] = evp_aead_seal;
|
||||
enc_sess->esi_dir[1] = evp_aead_open;
|
||||
|
||||
enc_sess->esi_odcid = *dcid;
|
||||
enc_sess->esi_flags |= ESI_ODCID;
|
||||
|
||||
LSQ_DEBUGC("created client, DCID: %"CID_FMT, CID_BITS(dcid));
|
||||
{
|
||||
const char *log;
|
||||
|
@ -793,7 +812,8 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
|
|||
struct lsquic_conn *lconn, const lsquic_cid_t *first_dcid,
|
||||
void *(crypto_streams)[4],
|
||||
const struct crypto_stream_if *cryst_if,
|
||||
const struct lsquic_cid *odcid)
|
||||
const struct lsquic_cid *odcid,
|
||||
const struct lsquic_cid *iscid )
|
||||
{
|
||||
struct enc_sess_iquic *enc_sess;
|
||||
|
||||
|
@ -819,6 +839,8 @@ iquic_esfi_create_server (struct lsquic_engine_public *enpub,
|
|||
enc_sess->esi_odcid = *odcid;
|
||||
enc_sess->esi_flags |= ESI_ODCID;
|
||||
}
|
||||
enc_sess->esi_iscid = *iscid;
|
||||
enc_sess->esi_flags |= ESI_ISCID;
|
||||
|
||||
init_frals(enc_sess);
|
||||
|
||||
|
@ -1470,6 +1492,7 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
|
|||
const uint8_t *params_buf;
|
||||
size_t bufsz;
|
||||
char *params_str;
|
||||
const enum lsquic_version version = enc_sess->esi_conn->cn_version;
|
||||
|
||||
SSL_get_peer_quic_transport_params(enc_sess->esi_ssl, ¶ms_buf, &bufsz);
|
||||
if (!params_buf)
|
||||
|
@ -1479,8 +1502,8 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
|
|||
}
|
||||
|
||||
LSQ_DEBUG("have peer transport parameters (%zu bytes)", bufsz);
|
||||
if (0 > (enc_sess->esi_conn->cn_version == LSQVER_ID25
|
||||
? lsquic_tp_decode_id25 : lsquic_tp_decode)(params_buf, bufsz,
|
||||
if (0 > (version == LSQVER_ID27 ? lsquic_tp_decode_27
|
||||
: lsquic_tp_decode)(params_buf, bufsz,
|
||||
!(enc_sess->esi_flags & ESI_SERVER),
|
||||
trans_params))
|
||||
{
|
||||
|
@ -1501,30 +1524,72 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((enc_sess->esi_flags & (ESI_ODCID|ESI_SERVER)) == ESI_ODCID)
|
||||
const lsquic_cid_t *const cids[LAST_TPI + 1] = {
|
||||
[TP_CID_IDX(TPI_ORIGINAL_DEST_CID)] = enc_sess->esi_flags & ESI_ODCID ? &enc_sess->esi_odcid : NULL,
|
||||
[TP_CID_IDX(TPI_RETRY_SOURCE_CID)] = enc_sess->esi_flags & ESI_RSCID ? &enc_sess->esi_rscid : NULL,
|
||||
[TP_CID_IDX(TPI_INITIAL_SOURCE_CID)] = enc_sess->esi_flags & ESI_ISCID ? &enc_sess->esi_iscid : NULL,
|
||||
};
|
||||
|
||||
unsigned must_have, must_not_have = 0;
|
||||
if (version > LSQVER_ID27)
|
||||
{
|
||||
if (!(trans_params->tp_set & (1 << TPI_ORIGINAL_CONNECTION_ID)))
|
||||
must_have = 1 << TPI_INITIAL_SOURCE_CID;
|
||||
if (enc_sess->esi_flags & ESI_SERVER)
|
||||
must_not_have |= 1 << TPI_ORIGINAL_DEST_CID;
|
||||
else
|
||||
must_have |= 1 << TPI_ORIGINAL_DEST_CID;
|
||||
if ((enc_sess->esi_flags & (ESI_RETRY|ESI_SERVER)) == ESI_RETRY)
|
||||
must_have |= 1 << TPI_RETRY_SOURCE_CID;
|
||||
else
|
||||
must_not_have |= 1 << TPI_RETRY_SOURCE_CID;
|
||||
}
|
||||
else if ((enc_sess->esi_flags & (ESI_RETRY|ESI_SERVER)) == ESI_RETRY)
|
||||
must_have = 1 << TPI_ORIGINAL_DEST_CID;
|
||||
else
|
||||
must_have = 0;
|
||||
|
||||
enum transport_param_id tpi;
|
||||
for (tpi = FIRST_TP_CID; tpi <= LAST_TP_CID; ++tpi)
|
||||
{
|
||||
if (!(must_have & (1 << tpi)))
|
||||
continue;
|
||||
if (!(trans_params->tp_set & (1 << tpi)))
|
||||
{
|
||||
LSQ_DEBUG("server did not produce original DCID (ODCID)");
|
||||
LSQ_DEBUG("server did not produce %s", lsquic_tpi2str[tpi]);
|
||||
return -1;
|
||||
}
|
||||
if (LSQUIC_CIDS_EQ(&enc_sess->esi_odcid,
|
||||
&trans_params->tp_original_cid))
|
||||
LSQ_DEBUG("ODCID values match");
|
||||
if (!cids[TP_CID_IDX(tpi)])
|
||||
{
|
||||
LSQ_WARN("do not have CID %s for checking",
|
||||
lsquic_tpi2str[tpi]);
|
||||
return -1;
|
||||
}
|
||||
if (LSQUIC_CIDS_EQ(cids[TP_CID_IDX(tpi)],
|
||||
&trans_params->tp_cids[TP_CID_IDX(tpi)]))
|
||||
LSQ_DEBUG("%s values match", lsquic_tpi2str[tpi]);
|
||||
else
|
||||
{
|
||||
if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG))
|
||||
{
|
||||
char cidbuf[2][MAX_CID_LEN * 2 + 1];
|
||||
lsquic_cid2str(&enc_sess->esi_odcid, cidbuf[0]);
|
||||
lsquic_cid2str(&trans_params->tp_original_cid, cidbuf[1]);
|
||||
LSQ_DEBUG("server provided ODCID %s that does not match "
|
||||
"our ODCID %s", cidbuf[1], cidbuf[0]);
|
||||
LSQ_DEBUG("server provided %s %"CID_FMT" that does not "
|
||||
"match ours %"CID_FMT, lsquic_tpi2str[tpi],
|
||||
CID_BITS_B(&trans_params->tp_cids[TP_CID_IDX(tpi)],
|
||||
cidbuf[0]),
|
||||
CID_BITS_B(cids[TP_CID_IDX(tpi)], cidbuf[1]));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (tpi = FIRST_TP_CID; tpi <= LAST_TP_CID; ++tpi)
|
||||
if (must_not_have & (1 << tpi) & trans_params->tp_set)
|
||||
{
|
||||
LSQ_DEBUG("server transport parameters unexpectedly contain %s",
|
||||
lsquic_tpi2str[tpi]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((trans_params->tp_set & (1 << TPI_LOSS_BITS))
|
||||
&& enc_sess->esi_enpub->enp_settings.es_ql_bits)
|
||||
{
|
||||
|
@ -2239,6 +2304,21 @@ iquic_esf_zero_rtt_enabled (enc_session_t *enc_session_p)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
iquic_esfi_set_iscid (enc_session_t *enc_session_p,
|
||||
const struct lsquic_packet_in *packet_in)
|
||||
{
|
||||
struct enc_sess_iquic *const enc_sess = enc_session_p;
|
||||
|
||||
if (!(enc_sess->esi_flags & ESI_ISCID))
|
||||
{
|
||||
lsquic_scid_from_packet_in(packet_in, &enc_sess->esi_iscid);
|
||||
enc_sess->esi_flags |= ESI_ISCID;
|
||||
LSQ_DEBUGC("set ISCID to %"CID_FMT, CID_BITS(&enc_sess->esi_iscid));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
|
||||
const lsquic_cid_t *old_dcid, const lsquic_cid_t *new_dcid)
|
||||
|
@ -2247,7 +2327,8 @@ iquic_esfi_reset_dcid (enc_session_t *enc_session_p,
|
|||
struct crypto_ctx_pair *pair;
|
||||
|
||||
enc_sess->esi_odcid = *old_dcid;
|
||||
enc_sess->esi_flags |= ESI_ODCID;
|
||||
enc_sess->esi_rscid = *new_dcid;
|
||||
enc_sess->esi_flags |= ESI_ODCID|ESI_RSCID|ESI_RETRY;
|
||||
|
||||
/* Free previous handshake keys */
|
||||
assert(enc_sess->esi_hsk_pairs);
|
||||
|
@ -2340,6 +2421,7 @@ const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1 =
|
|||
= iquic_esfi_get_peer_transport_params,
|
||||
.esfi_reset_dcid = iquic_esfi_reset_dcid,
|
||||
.esfi_init_server = iquic_esfi_init_server,
|
||||
.esfi_set_iscid = iquic_esfi_set_iscid,
|
||||
.esfi_set_streams = iquic_esfi_set_streams,
|
||||
.esfi_create_server = iquic_esfi_create_server,
|
||||
.esfi_shake_stream = iquic_esfi_shake_stream,
|
||||
|
|
|
@ -25,6 +25,15 @@
|
|||
|
||||
#ifndef NDEBUG
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || defined(NDEBUG)
|
||||
#define CAN_LOSE_PACKETS 0
|
||||
#else
|
||||
#define CAN_LOSE_PACKETS 1
|
||||
#endif
|
||||
|
||||
#if CAN_LOSE_PACKETS
|
||||
#include <regex.h> /* For code that loses packets */
|
||||
#endif
|
||||
|
||||
|
@ -208,7 +217,11 @@ struct lsquic_engine
|
|||
= (1 << 9), /* Connections are hashed by address */
|
||||
#ifndef NDEBUG
|
||||
ENG_COALESCE = (1 << 24), /* Packet coalescing is enabled */
|
||||
#endif
|
||||
#if CAN_LOSE_PACKETS
|
||||
ENG_LOSE_PACKETS= (1 << 25), /* Lose *some* outgoing packets */
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
ENG_DTOR = (1 << 26), /* Engine destructor */
|
||||
#endif
|
||||
} flags;
|
||||
|
@ -223,13 +236,14 @@ struct lsquic_engine
|
|||
struct min_heap conns_out;
|
||||
struct eng_hist history;
|
||||
unsigned batch_size;
|
||||
struct lsquic_conn *curr_conn;
|
||||
struct pr_queue *pr_queue;
|
||||
struct attq *attq;
|
||||
/* Track time last time a packet was sent to give new connections
|
||||
* priority lower than that of existing connections.
|
||||
*/
|
||||
lsquic_time_t last_sent;
|
||||
#ifndef NDEBUG
|
||||
#if CAN_LOSE_PACKETS
|
||||
regex_t lose_packets_re;
|
||||
const char *lose_packets_str;
|
||||
#endif
|
||||
|
@ -638,6 +652,7 @@ lsquic_engine_new (unsigned flags,
|
|||
{
|
||||
const char *env;
|
||||
env = getenv("LSQUIC_LOSE_PACKETS_RE");
|
||||
#if CAN_LOSE_PACKETS
|
||||
if (env)
|
||||
{
|
||||
if (0 != regcomp(&engine->lose_packets_re, env,
|
||||
|
@ -651,6 +666,7 @@ lsquic_engine_new (unsigned flags,
|
|||
LSQ_WARN("will lose packets that match the following regex: %s",
|
||||
env);
|
||||
}
|
||||
#endif
|
||||
env = getenv("LSQUIC_COALESCE");
|
||||
if (env)
|
||||
{
|
||||
|
@ -1320,8 +1336,12 @@ process_packet_in (lsquic_engine_t *engine, lsquic_packet_in_t *packet_in,
|
|||
}
|
||||
|
||||
if (engine->flags & ENG_SERVER)
|
||||
{
|
||||
conn = find_or_create_conn(engine, packet_in, ppstate, sa_local,
|
||||
sa_peer, peer_ctx, packet_in_size);
|
||||
if (!engine->curr_conn)
|
||||
engine->curr_conn = conn;
|
||||
}
|
||||
else
|
||||
conn = find_conn(engine, packet_in, ppstate, sa_local);
|
||||
|
||||
|
@ -1434,7 +1454,7 @@ lsquic_engine_destroy (lsquic_engine_t *engine)
|
|||
lsquic_stock_shared_hash_destroy(engine->pub.enp_shi_ctx);
|
||||
lsquic_mm_cleanup(&engine->pub.enp_mm);
|
||||
free(engine->conns_tickable.mh_elems);
|
||||
#ifndef NDEBUG
|
||||
#if CAN_LOSE_PACKETS
|
||||
if (engine->flags & ENG_LOSE_PACKETS)
|
||||
regfree(&engine->lose_packets_re);
|
||||
#endif
|
||||
|
@ -2032,7 +2052,7 @@ coi_reheap (struct conns_out_iter *iter, lsquic_engine_t *engine)
|
|||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if CAN_LOSE_PACKETS
|
||||
static void
|
||||
lose_matching_packets (const lsquic_engine_t *engine, struct out_batch *batch,
|
||||
unsigned n)
|
||||
|
@ -2131,7 +2151,7 @@ send_batch (lsquic_engine_t *engine, const struct send_batch_ctx *sb_ctx,
|
|||
CONST_BATCH struct out_batch *const batch = sb_ctx->batch;
|
||||
struct lsquic_packet_out *CONST_BATCH *packet_out, *CONST_BATCH *end;
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if CAN_LOSE_PACKETS
|
||||
if (engine->flags & ENG_LOSE_PACKETS)
|
||||
lose_matching_packets(engine, batch, n_to_send);
|
||||
#endif
|
||||
|
@ -2641,6 +2661,20 @@ process_connections (lsquic_engine_t *engine, conn_iter_f next_conn,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
maybe_count_garbage (struct lsquic_engine *engine, size_t garbage_sz)
|
||||
{
|
||||
/* This is not very pretty (action at a distance via engine->curr_conn),
|
||||
* but it's the cheapest I can come up with to handle the "count garbage
|
||||
* toward amplification limit" requirement in
|
||||
* [draft-ietf-quic-transport-28] Section 8.1.
|
||||
*/
|
||||
if (engine->curr_conn && engine->curr_conn->cn_if->ci_count_garbage)
|
||||
engine->curr_conn->cn_if->ci_count_garbage(engine->curr_conn,
|
||||
garbage_sz);
|
||||
}
|
||||
|
||||
|
||||
/* Return 0 if packet is being processed by a real connection, 1 if the
|
||||
* packet was processed, but not by a connection, and -1 on error.
|
||||
*/
|
||||
|
@ -2680,20 +2714,25 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
|
|||
parse_packet_in_begin = lsquic_Q050_parse_packet_in_begin;
|
||||
else
|
||||
{
|
||||
assert(conn->cn_version == LSQVER_046
|
||||
#if LSQUIC_USE_Q098
|
||||
|| conn->cn_version == LSQVER_098
|
||||
assert(conn->cn_version == LSQVER_046 || conn->cn_version == LSQVER_098);
|
||||
#else
|
||||
assert(conn->cn_version == LSQVER_046);
|
||||
#endif
|
||||
|
||||
);
|
||||
parse_packet_in_begin = lsquic_Q046_parse_packet_in_begin;
|
||||
}
|
||||
}
|
||||
else
|
||||
parse_packet_in_begin = lsquic_parse_packet_in_begin;
|
||||
|
||||
engine->curr_conn = NULL;
|
||||
n_zeroes = 0;
|
||||
is_ietf = 0;
|
||||
#ifdef _MSC_VER
|
||||
s = 0;
|
||||
cid.len = 0;
|
||||
cid.idbuf[0] = 0;
|
||||
#endif
|
||||
do
|
||||
{
|
||||
packet_in = lsquic_mm_get_packet_in(&engine->pub.enp_mm);
|
||||
|
@ -2709,6 +2748,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
|
|||
engine->pub.enp_settings.es_scid_len, &ppstate))
|
||||
{
|
||||
LSQ_DEBUG("Cannot parse incoming packet's header");
|
||||
maybe_count_garbage(engine, packet_end - packet_in_data);
|
||||
lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in);
|
||||
s = 1;
|
||||
break;
|
||||
|
@ -2724,6 +2764,7 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
|
|||
&& LSQUIC_CIDS_EQ(&packet_in->pi_dcid, &cid)))
|
||||
{
|
||||
packet_in_data += packet_in->pi_data_sz;
|
||||
maybe_count_garbage(engine, packet_in->pi_data_sz);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -528,15 +528,10 @@ lsquic_frame_writer_write_promise (struct lsquic_frame_writer *fw,
|
|||
|
||||
free(buf);
|
||||
|
||||
if (0 == s)
|
||||
{
|
||||
EV_LOG_GENERATED_HTTP_PUSH_PROMISE(LSQUIC_LOG_CONN_ID, stream_id,
|
||||
htonl(promised_stream_id), headers);
|
||||
hfc_terminate_frame(&hfc, HFHF_END_HEADERS);
|
||||
return lsquic_frame_writer_flush(fw);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
EV_LOG_GENERATED_HTTP_PUSH_PROMISE(LSQUIC_LOG_CONN_ID, stream_id,
|
||||
htonl(promised_stream_id), headers);
|
||||
hfc_terminate_frame(&hfc, HFHF_END_HEADERS);
|
||||
return lsquic_frame_writer_flush(fw);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ enum more_flags
|
|||
};
|
||||
|
||||
|
||||
#define N_PATHS 2
|
||||
#define N_PATHS 4
|
||||
|
||||
enum send
|
||||
{
|
||||
|
@ -154,9 +154,13 @@ enum send
|
|||
SEND_PATH_CHAL,
|
||||
SEND_PATH_CHAL_PATH_0 = SEND_PATH_CHAL + 0,
|
||||
SEND_PATH_CHAL_PATH_1 = SEND_PATH_CHAL + 1,
|
||||
SEND_PATH_CHAL_PATH_2 = SEND_PATH_CHAL + 2,
|
||||
SEND_PATH_CHAL_PATH_3 = SEND_PATH_CHAL + 3,
|
||||
SEND_PATH_RESP,
|
||||
SEND_PATH_RESP_PATH_0 = SEND_PATH_RESP + 0,
|
||||
SEND_PATH_RESP_PATH_1 = SEND_PATH_RESP + 1,
|
||||
SEND_PATH_RESP_PATH_2 = SEND_PATH_RESP + 2,
|
||||
SEND_PATH_RESP_PATH_3 = SEND_PATH_RESP + 3,
|
||||
SEND_MAX_DATA,
|
||||
SEND_PING,
|
||||
SEND_NEW_CID,
|
||||
|
@ -181,9 +185,13 @@ enum send_flags
|
|||
SF_SEND_PATH_CHAL = 1 << SEND_PATH_CHAL,
|
||||
SF_SEND_PATH_CHAL_PATH_0 = 1 << SEND_PATH_CHAL_PATH_0,
|
||||
SF_SEND_PATH_CHAL_PATH_1 = 1 << SEND_PATH_CHAL_PATH_1,
|
||||
SF_SEND_PATH_CHAL_PATH_2 = 1 << SEND_PATH_CHAL_PATH_2,
|
||||
SF_SEND_PATH_CHAL_PATH_3 = 1 << SEND_PATH_CHAL_PATH_3,
|
||||
SF_SEND_PATH_RESP = 1 << SEND_PATH_RESP,
|
||||
SF_SEND_PATH_RESP_PATH_0 = 1 << SEND_PATH_RESP_PATH_0,
|
||||
SF_SEND_PATH_RESP_PATH_1 = 1 << SEND_PATH_RESP_PATH_1,
|
||||
SF_SEND_PATH_RESP_PATH_2 = 1 << SEND_PATH_RESP_PATH_2,
|
||||
SF_SEND_PATH_RESP_PATH_3 = 1 << SEND_PATH_RESP_PATH_3,
|
||||
SF_SEND_NEW_CID = 1 << SEND_NEW_CID,
|
||||
SF_SEND_RETIRE_CID = 1 << SEND_RETIRE_CID,
|
||||
SF_SEND_CONN_CLOSE = 1 << SEND_CONN_CLOSE,
|
||||
|
@ -464,6 +472,10 @@ ietf_full_conn_ci_get_log_cid (const struct lsquic_conn *);
|
|||
static void
|
||||
ietf_full_conn_ci_destroy (struct lsquic_conn *);
|
||||
|
||||
static int
|
||||
insert_new_dcid (struct ietf_full_conn *, uint64_t seqno,
|
||||
const lsquic_cid_t *, const unsigned char *token, int update_cur_dcid);
|
||||
|
||||
static unsigned
|
||||
highest_bit_set (unsigned sz)
|
||||
{
|
||||
|
@ -652,11 +664,11 @@ migra_begin (struct ietf_full_conn *conn, struct conn_path *copath,
|
|||
copath->cop_path.np_pack_size = IQUIC_MAX_IPv6_PACKET_SZ;
|
||||
else
|
||||
copath->cop_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
|
||||
if ((params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
|
||||
&& params->tp_numerics[TPI_MAX_PACKET_SIZE]
|
||||
if ((params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
|
||||
&& params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
|
||||
< copath->cop_path.np_pack_size)
|
||||
copath->cop_path.np_pack_size
|
||||
= params->tp_numerics[TPI_MAX_PACKET_SIZE];
|
||||
= params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
|
||||
memcpy(&copath->cop_path.np_local_addr, NP_LOCAL_SA(CUR_NPATH(conn)),
|
||||
sizeof(copath->cop_path.np_local_addr));
|
||||
memcpy(&copath->cop_path.np_peer_addr, dest_sa,
|
||||
|
@ -1113,6 +1125,8 @@ ietf_full_conn_init (struct ietf_full_conn *conn,
|
|||
conn->ifc_max_ack_packno[PNS_APP] = IQUIC_INVALID_PACKNO;
|
||||
conn->ifc_paths[0].cop_path.np_path_id = 0;
|
||||
conn->ifc_paths[1].cop_path.np_path_id = 1;
|
||||
conn->ifc_paths[2].cop_path.np_path_id = 2;
|
||||
conn->ifc_paths[3].cop_path.np_path_id = 3;
|
||||
#define valid_stream_id(v) ((v) <= VINT_MAX_VALUE)
|
||||
conn->ifc_max_req_id = VINT_MAX_VALUE + 1;
|
||||
conn->ifc_ping_unretx_thresh = 20;
|
||||
|
@ -2740,7 +2754,7 @@ ietf_full_conn_ci_going_away (struct lsquic_conn *lconn)
|
|||
{
|
||||
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
|
||||
|
||||
if ((conn->ifc_flags & (IFC_SERVER|IFC_HTTP)) == (IFC_SERVER|IFC_HTTP))
|
||||
if (conn->ifc_flags & IFC_HTTP)
|
||||
{
|
||||
if (!(conn->ifc_flags & (IFC_CLOSING|IFC_GOING_AWAY)))
|
||||
{
|
||||
|
@ -2760,7 +2774,7 @@ ietf_full_conn_ci_going_away (struct lsquic_conn *lconn)
|
|||
}
|
||||
}
|
||||
else
|
||||
LSQ_NOTICE("going away has no effect in IETF QUIC");
|
||||
LSQ_NOTICE("going away has no effect in non-HTTP mode");
|
||||
}
|
||||
|
||||
|
||||
|
@ -2834,8 +2848,8 @@ retire_cid_from_tp (struct ietf_full_conn *conn,
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
begin_migra_or_retire_cid (struct ietf_full_conn *conn,
|
||||
static enum { BM_MIGRATING, BM_NOT_MIGRATING, BM_ERROR, }
|
||||
try_to_begin_migration (struct ietf_full_conn *conn,
|
||||
const struct transport_params *params)
|
||||
{
|
||||
struct conn_path *copath;
|
||||
|
@ -2853,8 +2867,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
|
|||
LSQ_DEBUG("TP disables migration: retire PreferredAddress CID");
|
||||
else
|
||||
LSQ_DEBUG("Migration not allowed: retire PreferredAddress CID");
|
||||
retire_cid_from_tp(conn, params);
|
||||
return 0;
|
||||
return BM_NOT_MIGRATING;
|
||||
}
|
||||
|
||||
is_ipv6 = NP_IS_IPv6(CUR_NPATH(conn));
|
||||
|
@ -2867,8 +2880,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
|
|||
*/
|
||||
LSQ_DEBUG("Cannot migrate from IPv%u to IPv%u", is_ipv6 ? 6 : 4,
|
||||
is_ipv6 ? 4 : 6);
|
||||
retire_cid_from_tp(conn, params);
|
||||
return 0;
|
||||
return BM_NOT_MIGRATING;
|
||||
}
|
||||
|
||||
if (0 == params->tp_preferred_address.cid.len)
|
||||
|
@ -2877,15 +2889,14 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
|
|||
* DCID becomes available.
|
||||
*/
|
||||
LSQ_DEBUG("Cannot migrate using zero-length DCID");
|
||||
retire_cid_from_tp(conn, params);
|
||||
return 0;
|
||||
return BM_NOT_MIGRATING;
|
||||
}
|
||||
|
||||
dce = get_new_dce(conn);
|
||||
if (!dce)
|
||||
{
|
||||
ABORT_WARN("cannot allocate DCE");
|
||||
return -1;
|
||||
return BM_ERROR;
|
||||
}
|
||||
|
||||
memset(dce, 0, sizeof(*dce));
|
||||
|
@ -2902,7 +2913,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
|
|||
{
|
||||
lsquic_malo_put(dce);
|
||||
ABORT_WARN("cannot insert DCE");
|
||||
return -1;
|
||||
return BM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2925,7 +2936,7 @@ begin_migra_or_retire_cid (struct ietf_full_conn *conn,
|
|||
assert(!(conn->ifc_used_paths & (1 << (copath - conn->ifc_paths))));
|
||||
|
||||
migra_begin(conn, copath, dce, (struct sockaddr *) &sockaddr, params);
|
||||
return 0;
|
||||
return BM_MIGRATING;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2938,10 +2949,33 @@ maybe_start_migration (struct ietf_full_conn *conn)
|
|||
params = lconn->cn_esf.i->esfi_get_peer_transport_params(
|
||||
lconn->cn_enc_session);
|
||||
if (params->tp_set & (1 << TPI_PREFERRED_ADDRESS))
|
||||
{
|
||||
if (0 != begin_migra_or_retire_cid(conn, params))
|
||||
switch (try_to_begin_migration(conn, params))
|
||||
{
|
||||
case BM_MIGRATING:
|
||||
break;
|
||||
case BM_NOT_MIGRATING:
|
||||
if (lconn->cn_version == LSQVER_ID27)
|
||||
retire_cid_from_tp(conn, params);
|
||||
else
|
||||
{
|
||||
/*
|
||||
* [draft-ietf-quic-transport-28] Section 5.1.1:
|
||||
" Connection IDs that are issued and not
|
||||
" retired are considered active; any active connection ID is valid for
|
||||
" use with the current connection at any time, in any packet type.
|
||||
" This includes the connection ID issued by the server via the
|
||||
" preferred_address transport parameter.
|
||||
*/
|
||||
LSQ_DEBUG("not migrating: save DCID from transport params");
|
||||
(void) insert_new_dcid(conn, 1,
|
||||
¶ms->tp_preferred_address.cid,
|
||||
params->tp_preferred_address.srst, 0);
|
||||
}
|
||||
break;
|
||||
case BM_ERROR:
|
||||
ABORT_QUIETLY(0, TEC_INTERNAL_ERROR, "error initiating migration");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2955,7 +2989,7 @@ handshake_ok (struct lsquic_conn *lconn)
|
|||
const struct transport_params *params;
|
||||
enum stream_id_type sit;
|
||||
uint64_t limit;
|
||||
char buf[0x200];
|
||||
char buf[MAX_TP_STR_SZ];
|
||||
|
||||
fiu_return_on("full_conn_ietf/handshake_ok", -1);
|
||||
|
||||
|
@ -2973,7 +3007,8 @@ handshake_ok (struct lsquic_conn *lconn)
|
|||
}
|
||||
|
||||
LSQ_DEBUG("peer transport parameters: %s",
|
||||
(lsquic_tp_to_str(params, buf, sizeof(buf)), buf));
|
||||
((lconn->cn_version == LSQVER_ID27 ? lsquic_tp_to_str_27
|
||||
: lsquic_tp_to_str)(params, buf, sizeof(buf)), buf));
|
||||
|
||||
if ((params->tp_set & (1 << TPI_LOSS_BITS))
|
||||
&& conn->ifc_settings->es_ql_bits == 2)
|
||||
|
@ -3088,12 +3123,12 @@ handshake_ok (struct lsquic_conn *lconn)
|
|||
|
||||
conn->ifc_max_peer_ack_usec = params->tp_max_ack_delay * 1000;
|
||||
|
||||
if ((params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
|
||||
&& params->tp_numerics[TPI_MAX_PACKET_SIZE]
|
||||
if ((params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
|
||||
&& params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
|
||||
< CUR_NPATH(conn)->np_pack_size)
|
||||
{
|
||||
CUR_NPATH(conn)->np_pack_size
|
||||
= params->tp_numerics[TPI_MAX_PACKET_SIZE];
|
||||
= params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
|
||||
LSQ_DEBUG("decrease packet size to %hu bytes",
|
||||
CUR_NPATH(conn)->np_pack_size);
|
||||
}
|
||||
|
@ -3937,6 +3972,20 @@ generate_path_chal_1 (struct ietf_full_conn *conn, lsquic_time_t now)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
generate_path_chal_2 (struct ietf_full_conn *conn, lsquic_time_t now)
|
||||
{
|
||||
generate_path_chal_frame(conn, now, 2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
generate_path_chal_3 (struct ietf_full_conn *conn, lsquic_time_t now)
|
||||
{
|
||||
generate_path_chal_frame(conn, now, 3);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
generate_path_resp_frame (struct ietf_full_conn *conn, lsquic_time_t now,
|
||||
unsigned path_id)
|
||||
|
@ -3986,6 +4035,20 @@ generate_path_resp_1 (struct ietf_full_conn *conn, lsquic_time_t now)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
generate_path_resp_2 (struct ietf_full_conn *conn, lsquic_time_t now)
|
||||
{
|
||||
generate_path_resp_frame(conn, now, 2);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
generate_path_resp_3 (struct ietf_full_conn *conn, lsquic_time_t now)
|
||||
{
|
||||
generate_path_resp_frame(conn, now, 3);
|
||||
}
|
||||
|
||||
|
||||
static struct lsquic_packet_out *
|
||||
ietf_full_conn_ci_next_packet_to_send (struct lsquic_conn *lconn, size_t size)
|
||||
{
|
||||
|
@ -5140,17 +5203,91 @@ retire_dcids_prior_to (struct ietf_full_conn *conn, unsigned retire_prior_to)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
insert_new_dcid (struct ietf_full_conn *conn, uint64_t seqno,
|
||||
const lsquic_cid_t *cid, const unsigned char *token, int update_cur_dcid)
|
||||
{
|
||||
struct dcid_elem **dce, **el;
|
||||
char tokstr[IQUIC_SRESET_TOKEN_SZ * 2 + 1];
|
||||
|
||||
dce = NULL;
|
||||
for (el = conn->ifc_dces; el < conn->ifc_dces + sizeof(conn->ifc_dces)
|
||||
/ sizeof(conn->ifc_dces[0]); ++el)
|
||||
if (*el)
|
||||
{
|
||||
if ((*el)->de_seqno == seqno)
|
||||
{
|
||||
if (!LSQUIC_CIDS_EQ(&(*el)->de_cid, cid))
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
|
||||
"NEW_CONNECTION_ID: already have CID seqno %"PRIu64
|
||||
" but with a different CID", seqno);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_DEBUG("Ignore duplicate CID seqno %"PRIu64, seqno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (LSQUIC_CIDS_EQ(&(*el)->de_cid, cid))
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
|
||||
"NEW_CONNECTION_ID: received the same CID with sequence "
|
||||
"numbers %u and %"PRIu64, (*el)->de_seqno, seqno);
|
||||
return -1;
|
||||
}
|
||||
else if (((*el)->de_flags & DE_SRST)
|
||||
&& 0 == memcmp((*el)->de_srst, token,
|
||||
IQUIC_SRESET_TOKEN_SZ))
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
|
||||
"NEW_CONNECTION_ID: received second instance of reset "
|
||||
"token %s in seqno %"PRIu64", same as in seqno %u",
|
||||
(lsquic_hexstr(token, IQUIC_SRESET_TOKEN_SZ, tokstr,
|
||||
sizeof(tokstr)), tokstr),
|
||||
seqno, (*el)->de_seqno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (!dce)
|
||||
dce = el;
|
||||
|
||||
if (!dce)
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_CONNECTION_ID_LIMIT_ERROR,
|
||||
"NEW_CONNECTION_ID: received connection ID that is going over the "
|
||||
"limit of %u CIDs", MAX_IETF_CONN_DCIDS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*dce = lsquic_malo_get(conn->ifc_pub.mm->malo.dcid_elem);
|
||||
if (*dce)
|
||||
{
|
||||
memset(*dce, 0, sizeof(**dce));
|
||||
(*dce)->de_seqno = seqno;
|
||||
(*dce)->de_cid = *cid;
|
||||
memcpy((*dce)->de_srst, token, sizeof((*dce)->de_srst));
|
||||
(*dce)->de_flags |= DE_SRST;
|
||||
if (update_cur_dcid)
|
||||
*CUR_DCID(conn) = *cid;
|
||||
}
|
||||
else
|
||||
LSQ_WARN("cannot allocate dce to insert DCID seqno %"PRIu64, seqno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static unsigned
|
||||
process_new_connection_id_frame (struct ietf_full_conn *conn,
|
||||
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
|
||||
{
|
||||
struct dcid_elem **dce, **el;
|
||||
const unsigned char *token;
|
||||
const char *action_str;
|
||||
lsquic_cid_t cid;
|
||||
uint64_t seqno, retire_prior_to;
|
||||
int parsed_len, update_cur_dcid;
|
||||
char tokstr[IQUIC_SRESET_TOKEN_SZ * 2 + 1];
|
||||
|
||||
parsed_len = conn->ifc_conn.cn_pf->pf_parse_new_conn_id(p, len,
|
||||
&seqno, &retire_prior_to, &cid, &token);
|
||||
|
@ -5194,71 +5331,9 @@ process_new_connection_id_frame (struct ietf_full_conn *conn,
|
|||
else
|
||||
update_cur_dcid = 0;
|
||||
|
||||
dce = NULL;
|
||||
for (el = conn->ifc_dces; el < conn->ifc_dces + sizeof(conn->ifc_dces)
|
||||
/ sizeof(conn->ifc_dces[0]); ++el)
|
||||
if (*el)
|
||||
{
|
||||
if ((*el)->de_seqno == seqno)
|
||||
{
|
||||
if (!LSQUIC_CIDS_EQ(&(*el)->de_cid, &cid))
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
|
||||
"NEW_CONNECTION_ID: already have CID seqno %"PRIu64
|
||||
" but with a different CID", seqno);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LSQ_DEBUG("Ignore duplicate CID seqno %"PRIu64, seqno);
|
||||
return parsed_len;
|
||||
}
|
||||
}
|
||||
else if (LSQUIC_CIDS_EQ(&(*el)->de_cid, &cid))
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
|
||||
"NEW_CONNECTION_ID: received the same CID with sequence "
|
||||
"numbers %u and %"PRIu64, (*el)->de_seqno, seqno);
|
||||
return 0;
|
||||
}
|
||||
else if (((*el)->de_flags & DE_SRST)
|
||||
&& 0 == memcmp((*el)->de_srst, token,
|
||||
IQUIC_SRESET_TOKEN_SZ))
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_PROTOCOL_VIOLATION,
|
||||
"NEW_CONNECTION_ID: received second instance of reset "
|
||||
"token %s in seqno %"PRIu64", same as in seqno %u",
|
||||
(lsquic_hexstr(token, IQUIC_SRESET_TOKEN_SZ, tokstr,
|
||||
sizeof(tokstr)), tokstr),
|
||||
seqno, (*el)->de_seqno);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!dce)
|
||||
dce = el;
|
||||
|
||||
if (!dce)
|
||||
{
|
||||
ABORT_QUIETLY(0, TEC_CONNECTION_ID_LIMIT_ERROR,
|
||||
"NEW_CONNECTION_ID: received connection ID that is going over the "
|
||||
"limit of %u CIDs", MAX_IETF_CONN_DCIDS);
|
||||
if (0 != insert_new_dcid(conn, seqno, &cid, token, update_cur_dcid))
|
||||
return 0;
|
||||
}
|
||||
|
||||
*dce = lsquic_malo_get(conn->ifc_pub.mm->malo.dcid_elem);
|
||||
if (*dce)
|
||||
{
|
||||
memset(*dce, 0, sizeof(**dce));
|
||||
(*dce)->de_seqno = seqno;
|
||||
(*dce)->de_cid = cid;
|
||||
memcpy((*dce)->de_srst, token, sizeof((*dce)->de_srst));
|
||||
(*dce)->de_flags |= DE_SRST;
|
||||
action_str = "Saved";
|
||||
if (update_cur_dcid)
|
||||
*CUR_DCID(conn) = cid;
|
||||
}
|
||||
else
|
||||
action_str = "Ignored (alloc failure)";
|
||||
action_str = "Saved";
|
||||
|
||||
end:
|
||||
LSQ_DEBUGC("Got new connection ID from peer: seq=%"PRIu64"; "
|
||||
|
@ -5642,7 +5717,8 @@ process_packet_frame (struct ietf_full_conn *conn,
|
|||
|
||||
enc_level = lsquic_packet_in_enc_level(packet_in);
|
||||
type = conn->ifc_conn.cn_pf->pf_parse_frame_type(p, len);
|
||||
if (lsquic_legal_frames_by_level[enc_level] & (1 << type))
|
||||
if (lsquic_legal_frames_by_level[conn->ifc_conn.cn_version][enc_level]
|
||||
& (1 << type))
|
||||
{
|
||||
LSQ_DEBUG("about to process %s frame", frame_type_2_str[type]);
|
||||
packet_in->pi_frame_types |= 1 << type;
|
||||
|
@ -5724,11 +5800,11 @@ init_new_path (struct ietf_full_conn *conn, struct conn_path *path,
|
|||
path->cop_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
|
||||
params = lconn->cn_esf.i->esfi_get_peer_transport_params(
|
||||
lconn->cn_enc_session);
|
||||
if (params && (params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
|
||||
&& params->tp_numerics[TPI_MAX_PACKET_SIZE]
|
||||
if (params && (params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
|
||||
&& params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
|
||||
< path->cop_path.np_pack_size)
|
||||
path->cop_path.np_pack_size
|
||||
= params->tp_numerics[TPI_MAX_PACKET_SIZE];
|
||||
= params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
|
||||
|
||||
LSQ_DEBUG("initialized path %u", (unsigned) (path - conn->ifc_paths));
|
||||
|
||||
|
@ -6158,6 +6234,9 @@ process_regular_packet (struct ietf_full_conn *conn,
|
|||
return process_retry_packet(conn, packet_in);
|
||||
|
||||
pns = lsquic_hety2pns[ packet_in->pi_header_type ];
|
||||
if (pns == PNS_INIT)
|
||||
conn->ifc_conn.cn_esf.i->esfi_set_iscid(conn->ifc_conn.cn_enc_session,
|
||||
packet_in);
|
||||
if ((pns == PNS_INIT && (conn->ifc_flags & IFC_IGNORE_INIT))
|
||||
|| (pns == PNS_HSK && (conn->ifc_flags & IFC_IGNORE_HSK)))
|
||||
{
|
||||
|
@ -6241,6 +6320,10 @@ process_regular_packet (struct ietf_full_conn *conn,
|
|||
"decrypter reports protocol violation");
|
||||
return -1;
|
||||
case DECPI_OK:
|
||||
/* Receiving any other type of packet precludes subsequent retries.
|
||||
* We only set it if decryption is successful.
|
||||
*/
|
||||
conn->ifc_flags |= IFC_RETRIED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6344,13 +6427,6 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
|
|||
|
||||
if (lsquic_packet_in_is_verneg(packet_in))
|
||||
{
|
||||
if (!verneg_ok(conn))
|
||||
{
|
||||
ABORT_ERROR("version negotiation not permitted in this version "
|
||||
"of QUIC");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LSQ_DEBUG("Processing version-negotiation packet");
|
||||
|
||||
if (conn->ifc_u.cli.ifcli_ver_neg.vn_state != VN_START)
|
||||
|
@ -6383,10 +6459,26 @@ process_incoming_packet_verneg (struct ietf_full_conn *conn,
|
|||
}
|
||||
}
|
||||
|
||||
/* [draft-ietf-quic-transport-28] Section 6.2:
|
||||
" A client MUST discard a Version Negotiation packet that lists the
|
||||
" QUIC version selected by the client.
|
||||
*/
|
||||
if (versions & (1 << conn->ifc_u.cli.ifcli_ver_neg.vn_ver))
|
||||
{
|
||||
ABORT_ERROR("server replied with version we support: %s",
|
||||
LSQ_DEBUG("server replied with version we sent, %s, ignore",
|
||||
lsquic_ver2str[conn->ifc_u.cli.ifcli_ver_neg.vn_ver]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* [draft-ietf-quic-transport-28] Section 6.2:
|
||||
" A client that supports only this version of QUIC MUST abandon the
|
||||
" current connection attempt if it receives a Version Negotiation
|
||||
" packet [...]
|
||||
*/
|
||||
if (!verneg_ok(conn))
|
||||
{
|
||||
ABORT_ERROR("version negotiation not permitted in this version "
|
||||
"of QUIC");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -6530,8 +6622,12 @@ static void (*const send_funcs[N_SEND])(
|
|||
[SEND_STOP_SENDING] = generate_stop_sending_frames,
|
||||
[SEND_PATH_CHAL_PATH_0] = generate_path_chal_0,
|
||||
[SEND_PATH_CHAL_PATH_1] = generate_path_chal_1,
|
||||
[SEND_PATH_CHAL_PATH_2] = generate_path_chal_2,
|
||||
[SEND_PATH_CHAL_PATH_3] = generate_path_chal_3,
|
||||
[SEND_PATH_RESP_PATH_0] = generate_path_resp_0,
|
||||
[SEND_PATH_RESP_PATH_1] = generate_path_resp_1,
|
||||
[SEND_PATH_RESP_PATH_2] = generate_path_resp_2,
|
||||
[SEND_PATH_RESP_PATH_3] = generate_path_resp_3,
|
||||
[SEND_PING] = generate_ping_frame,
|
||||
[SEND_HANDSHAKE_DONE] = generate_handshake_done_frame,
|
||||
[SEND_ACK_FREQUENCY] = generate_ack_frequency_frame,
|
||||
|
@ -6543,7 +6639,9 @@ static void (*const send_funcs[N_SEND])(
|
|||
|SF_SEND_STREAMS_BLOCKED_UNI|SF_SEND_STREAMS_BLOCKED_BIDI\
|
||||
|SF_SEND_MAX_STREAMS_UNI|SF_SEND_MAX_STREAMS_BIDI\
|
||||
|SF_SEND_PATH_CHAL_PATH_0|SF_SEND_PATH_CHAL_PATH_1\
|
||||
|SF_SEND_PATH_CHAL_PATH_2|SF_SEND_PATH_CHAL_PATH_3\
|
||||
|SF_SEND_PATH_RESP_PATH_0|SF_SEND_PATH_RESP_PATH_1\
|
||||
|SF_SEND_PATH_RESP_PATH_2|SF_SEND_PATH_RESP_PATH_3\
|
||||
|SF_SEND_PING|SF_SEND_HANDSHAKE_DONE\
|
||||
|SF_SEND_ACK_FREQUENCY\
|
||||
|SF_SEND_STOP_SENDING)
|
||||
|
@ -7119,6 +7217,17 @@ ietf_full_conn_ci_drop_crypto_streams (struct lsquic_conn *lconn)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
ietf_full_conn_ci_count_garbage (struct lsquic_conn *lconn, size_t garbage_sz)
|
||||
{
|
||||
struct ietf_full_conn *conn = (struct ietf_full_conn *) lconn;
|
||||
|
||||
conn->ifc_pub.bytes_in = garbage_sz;
|
||||
LSQ_DEBUG("count %zd bytes of garbage, new value: %u bytes", garbage_sz,
|
||||
conn->ifc_pub.bytes_in);
|
||||
}
|
||||
|
||||
|
||||
#define IETF_FULL_CONN_FUNCS \
|
||||
.ci_abort = ietf_full_conn_ci_abort, \
|
||||
.ci_abort_error = ietf_full_conn_ci_abort_error, \
|
||||
|
@ -7127,6 +7236,7 @@ ietf_full_conn_ci_drop_crypto_streams (struct lsquic_conn *lconn)
|
|||
.ci_cancel_pending_streams = ietf_full_conn_ci_cancel_pending_streams, \
|
||||
.ci_client_call_on_new = ietf_full_conn_ci_client_call_on_new, \
|
||||
.ci_close = ietf_full_conn_ci_close, \
|
||||
.ci_count_garbage = ietf_full_conn_ci_count_garbage, \
|
||||
.ci_destroy = ietf_full_conn_ci_destroy, \
|
||||
.ci_drain_time = ietf_full_conn_ci_drain_time, \
|
||||
.ci_drop_crypto_streams = ietf_full_conn_ci_drop_crypto_streams, \
|
||||
|
@ -7630,4 +7740,4 @@ static const struct lsquic_stream_if unicla_if =
|
|||
|
||||
static const struct lsquic_stream_if *unicla_if_ptr = &unicla_if;
|
||||
|
||||
typedef char dcid_elem_fits_in_128_bytes[(sizeof(struct dcid_elem) <= 128) - 1];
|
||||
typedef char dcid_elem_fits_in_128_bytes[sizeof(struct dcid_elem) <= 128 ? 1 : - 1];
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#define _GNU_SOURCE /* for memmem */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
@ -11,6 +8,8 @@
|
|||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -126,12 +126,12 @@ lsquic_hcso_write_settings (struct hcso_writer *writer,
|
|||
unsigned bits;
|
||||
int was_empty;
|
||||
#ifdef NDEBUG
|
||||
const unsigned frame_size_len = 1;
|
||||
# define frame_size_len 1
|
||||
#else
|
||||
/* Need to use two bytes for frame length, as randomization may require
|
||||
* more than 63 bytes.
|
||||
*/
|
||||
const unsigned frame_size_len = 2;
|
||||
# define frame_size_len 2
|
||||
#endif
|
||||
unsigned char buf[1 /* Frame type */ + /* Frame size */ frame_size_len
|
||||
/* There are maximum three settings that need to be written out and
|
||||
|
|
|
@ -81,17 +81,8 @@ static lsquic_stream_ctx_t *
|
|||
headers_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
|
||||
{
|
||||
struct headers_stream *hs = stream_if_ctx;
|
||||
enum lshpack_dec_flags flags;
|
||||
|
||||
flags = 0;
|
||||
if (hs->hs_enpub->enp_hsi_if->hsi_flags & LSQUIC_HSI_HTTP1X)
|
||||
flags |= LSHPACK_DEC_HTTP1X;
|
||||
if (hs->hs_enpub->enp_hsi_if->hsi_flags & LSQUIC_HSI_HASH_NAME)
|
||||
flags |= LSHPACK_DEC_HASH_NAME;
|
||||
if (hs->hs_enpub->enp_hsi_if->hsi_flags & LSQUIC_HSI_HASH_NAMEVAL)
|
||||
flags |= LSHPACK_DEC_HASH_NAMEVAL;
|
||||
|
||||
lshpack_dec_init(&hs->hs_hdec, flags);
|
||||
lshpack_dec_init(&hs->hs_hdec);
|
||||
if (0 != lshpack_enc_init(&hs->hs_henc))
|
||||
{
|
||||
LSQ_WARN("could not initialize HPACK encoder: %s", strerror(errno));
|
||||
|
|
|
@ -17,7 +17,12 @@ lsquic_qhkdf_expand (const EVP_MD *md, const unsigned char *secret,
|
|||
#ifndef NDEBUG
|
||||
int s;
|
||||
#endif
|
||||
const size_t len = 2 + 1 + 6 + label_len + 1;
|
||||
#ifndef WIN32
|
||||
unsigned char info[ 2 + 1 + 6 + label_len + 1];
|
||||
#else
|
||||
unsigned char info[ 2 + 1 + 6 + UINT8_MAX + 1];
|
||||
#endif
|
||||
|
||||
info[0] = out_len >> 8;
|
||||
info[1] = out_len;
|
||||
|
@ -35,6 +40,6 @@ lsquic_qhkdf_expand (const EVP_MD *md, const unsigned char *secret,
|
|||
#else
|
||||
(void)
|
||||
#endif
|
||||
HKDF_expand(out, out_len, md, secret, secret_len, info, sizeof(info));
|
||||
HKDF_expand(out, out_len, md, secret, secret_len, info, len);
|
||||
assert(s);
|
||||
}
|
||||
|
|
|
@ -527,17 +527,13 @@ h1h_prepare_decode (void *hset, struct lsxpack_header *xhdr, size_t req_space)
|
|||
if (0 == hwc->hwc_header_buf_nalloc
|
||||
|| req_space > hwc->hwc_header_buf_nalloc)
|
||||
{
|
||||
if (req_space < 0x100)
|
||||
nalloc = 0x100;
|
||||
else
|
||||
nalloc = req_space;
|
||||
buf = malloc(nalloc);
|
||||
buf = malloc(req_space);
|
||||
if (!buf)
|
||||
{
|
||||
LSQ_DEBUG("cannot allocate %zd bytes", nalloc);
|
||||
LSQ_DEBUG("cannot allocate %zd bytes", req_space);
|
||||
return NULL;
|
||||
}
|
||||
hwc->hwc_header_buf_nalloc = nalloc;
|
||||
hwc->hwc_header_buf_nalloc = req_space;
|
||||
}
|
||||
else
|
||||
buf = hwc->hwc_xhdr.buf;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
/* Things specific to the IETF version of QUIC that do not fit anywhere else */
|
||||
|
||||
/* [draft-ietf-quic-transport-25] Section 22.4 */
|
||||
/* [draft-ietf-quic-transport-28] Section 20 */
|
||||
enum trans_error_code
|
||||
{
|
||||
TEC_NO_ERROR = 0x0,
|
||||
|
@ -19,6 +19,7 @@ enum trans_error_code
|
|||
TEC_CONNECTION_ID_LIMIT_ERROR = 0x9,
|
||||
TEC_PROTOCOL_VIOLATION = 0xA,
|
||||
TEC_INVALID_TOKEN = 0xB,
|
||||
TEC_APPLICATION_ERROR = 0xC,
|
||||
TEC_CRYPTO_BUFFER_EXCEEDED = 0xD,
|
||||
};
|
||||
|
||||
|
|
|
@ -248,8 +248,10 @@ lsquic_logger_lopt (const char *optarg);
|
|||
|
||||
#define CID_FMT ".*s"
|
||||
|
||||
#define CID_BITS(cid) 2 * (int) (cid)->len, \
|
||||
(lsquic_cid2str(cid, cidbuf_), cidbuf_)
|
||||
#define CID_BITS_B(cid, b) 2 * (int) (cid)->len, \
|
||||
(lsquic_cid2str(cid, b), b)
|
||||
|
||||
#define CID_BITS(cid) CID_BITS_B(cid, cidbuf_)
|
||||
|
||||
void
|
||||
lsquic_cid2str (const struct lsquic_cid *, char *out);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_int_types.h"
|
||||
|
@ -95,7 +96,7 @@ process_deferred_packets (struct mini_conn *mc);
|
|||
|
||||
/* If this is not true, highest_bit_set() may be broken */
|
||||
typedef char packno_set_is_unsigned_long[
|
||||
(sizeof(unsigned long long) == sizeof(mconn_packno_set_t)) - 1];
|
||||
sizeof(unsigned long long) == sizeof(mconn_packno_set_t) ? 1 : -1 ];
|
||||
|
||||
static unsigned
|
||||
highest_bit_set (unsigned long long sz)
|
||||
|
@ -2030,7 +2031,10 @@ mini_conn_ci_destroy (struct lsquic_conn *lconn)
|
|||
(int) (sizeof(mc->mc_hist_buf) - hist_idx),
|
||||
mc->mc_hist_buf + hist_idx, (int) hist_idx, mc->mc_hist_buf);
|
||||
#else
|
||||
LSQ_LOG(log_level, "destroyed. Diagnostics: conn flags: 0x%X, "
|
||||
if (LSQ_LOG_ENABLED(log_level))
|
||||
lsquic_logger_log2(log_level, LSQUIC_LOGGER_MODULE,
|
||||
LSQUIC_LOG_CONN_ID,
|
||||
"destroyed. Diagnostics: conn flags: 0x%X, "
|
||||
"mc flags: 0x%X, "
|
||||
#if LSQUIC_RECORD_INORD_HIST
|
||||
"incoming-history (trunc: %d) %s, "
|
||||
|
@ -2235,8 +2239,8 @@ static const struct conn_iface mini_conn_iface_standard_Q050 = {
|
|||
|
||||
typedef char largest_recv_holds_at_least_16_seconds[
|
||||
((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) / 1000000
|
||||
>= 16) - 1];
|
||||
>= 16) ? 1 : -1];
|
||||
|
||||
typedef char max_lifespan_smaller_than_largest_recv[
|
||||
((1 << (sizeof(((struct mini_conn *) 0)->mc_largest_recv) * 8)) >
|
||||
MAX_MINI_CONN_LIFESPAN_IN_USEC) - 1];
|
||||
MAX_MINI_CONN_LIFESPAN_IN_USEC) ? 1 : -1];
|
||||
|
|
|
@ -188,12 +188,12 @@ imico_maybe_process_params (struct ietf_mini_conn *conn)
|
|||
{
|
||||
conn->imc_flags |= IMC_HAVE_TP;
|
||||
conn->imc_ack_exp = params->tp_ack_delay_exponent;
|
||||
if (params->tp_set & (1 << TPI_MAX_PACKET_SIZE))
|
||||
if (params->tp_set & (1 << TPI_MAX_UDP_PAYLOAD_SIZE))
|
||||
{
|
||||
if (params->tp_numerics[TPI_MAX_PACKET_SIZE]
|
||||
if (params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
|
||||
< conn->imc_path.np_pack_size)
|
||||
conn->imc_path.np_pack_size =
|
||||
params->tp_numerics[TPI_MAX_PACKET_SIZE];
|
||||
params->tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE];
|
||||
}
|
||||
LSQ_DEBUG("read transport params, packet size is set to %hu bytes",
|
||||
conn->imc_path.np_pack_size);
|
||||
|
@ -493,6 +493,7 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
|
|||
conn->imc_conn.cn_cur_cce_idx = 1;
|
||||
|
||||
conn->imc_conn.cn_flags = LSCONN_MINI|LSCONN_IETF|LSCONN_SERVER;
|
||||
conn->imc_conn.cn_version = version;
|
||||
|
||||
for (i = 0; i < N_ENC_LEVS; ++i)
|
||||
{
|
||||
|
@ -503,7 +504,7 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
|
|||
esfi = select_esf_iquic_by_ver(version);
|
||||
enc_sess = esfi->esfi_create_server(enpub, &conn->imc_conn,
|
||||
&packet_in->pi_dcid, conn->imc_stream_ps, &crypto_stream_if,
|
||||
odcid);
|
||||
&conn->imc_cces[0].cce_cid, &conn->imc_path.np_dcid);
|
||||
if (!enc_sess)
|
||||
{
|
||||
lsquic_malo_put(conn);
|
||||
|
@ -518,7 +519,6 @@ lsquic_mini_conn_ietf_new (struct lsquic_engine_public *enpub,
|
|||
if (getenv("LSQUIC_CN_PACK_SIZE"))
|
||||
conn->imc_path.np_pack_size = atoi(getenv("LSQUIC_CN_PACK_SIZE"));
|
||||
#endif
|
||||
conn->imc_conn.cn_version = version;
|
||||
conn->imc_conn.cn_pf = select_pf_by_ver(version);
|
||||
conn->imc_conn.cn_esf.i = esfi;
|
||||
conn->imc_conn.cn_enc_session = enc_sess;
|
||||
|
@ -1099,7 +1099,8 @@ imico_process_packet_frame (struct ietf_mini_conn *conn,
|
|||
|
||||
enc_level = lsquic_packet_in_enc_level(packet_in);
|
||||
type = conn->imc_conn.cn_pf->pf_parse_frame_type(p, len);
|
||||
if (lsquic_legal_frames_by_level[enc_level] & (1 << type))
|
||||
if (lsquic_legal_frames_by_level[conn->imc_conn.cn_version][enc_level]
|
||||
& (1 << type))
|
||||
{
|
||||
packet_in->pi_frame_types |= 1 << type;
|
||||
return imico_process_frames[type](conn, packet_in, p, len);
|
||||
|
@ -1193,6 +1194,17 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
|
|||
enum dec_packin dec_packin;
|
||||
enum packnum_space pns;
|
||||
|
||||
/* Update "bytes in" count as early as possible. From
|
||||
* [draft-ietf-quic-transport-28] Section 8.1:
|
||||
" For the purposes of
|
||||
" avoiding amplification prior to address validation, servers MUST
|
||||
" count all of the payload bytes received in datagrams that are
|
||||
" uniquely attributed to a single connection. This includes datagrams
|
||||
" that contain packets that are successfully processed and datagrams
|
||||
" that contain packets that are all discarded.
|
||||
*/
|
||||
conn->imc_bytes_in += packet_in->pi_data_sz;
|
||||
|
||||
if (conn->imc_flags & IMC_ERROR)
|
||||
{
|
||||
LSQ_DEBUG("ignore incoming packet: connection is in error state");
|
||||
|
@ -1216,7 +1228,6 @@ ietf_mini_conn_ci_packet_in (struct lsquic_conn *lconn,
|
|||
}
|
||||
|
||||
EV_LOG_PACKET_IN(LSQUIC_LOG_CONN_ID, packet_in);
|
||||
conn->imc_bytes_in += packet_in->pi_data_sz + IQUIC_TAG_LEN;
|
||||
|
||||
if (pns == PNS_APP)
|
||||
{
|
||||
|
@ -1580,7 +1591,7 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
|
|||
else if (conn->imc_flags & IMC_BAD_TRANS_PARAMS)
|
||||
{
|
||||
is_app = 0;
|
||||
error_code = TEC_NO_ERROR;
|
||||
error_code = TEC_PROTOCOL_VIOLATION;
|
||||
reason = "bad transport parameters";
|
||||
rlen = 24;
|
||||
}
|
||||
|
@ -1607,7 +1618,7 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
|
|||
}
|
||||
|
||||
|
||||
/* [draft-ietf-quic-transport-23] Section 12.2:
|
||||
/* [draft-ietf-quic-transport-28] Section 10.3.1:
|
||||
*
|
||||
" A client will always know whether the server has Handshake keys (see
|
||||
" Section 17.2.2.1), but it is possible that a server does not know
|
||||
|
@ -1615,7 +1626,25 @@ imico_generate_conn_close (struct ietf_mini_conn *conn)
|
|||
" server SHOULD send a CONNECTION_CLOSE frame in both Handshake and
|
||||
" Initial packets to ensure that at least one of them is processable by
|
||||
" the client.
|
||||
--- 8< ---
|
||||
" Sending a CONNECTION_CLOSE of type 0x1d in an Initial or Handshake
|
||||
" packet could expose application state or be used to alter application
|
||||
" state. A CONNECTION_CLOSE of type 0x1d MUST be replaced by a
|
||||
" CONNECTION_CLOSE of type 0x1c when sending the frame in Initial or
|
||||
" Handshake packets. Otherwise, information about the application
|
||||
" state might be revealed. Endpoints MUST clear the value of the
|
||||
" Reason Phrase field and SHOULD use the APPLICATION_ERROR code when
|
||||
" converting to a CONNECTION_CLOSE of type 0x1c.
|
||||
*/
|
||||
LSQ_DEBUG("sending CONNECTION_CLOSE, is_app: %d, error code: %u, "
|
||||
"reason: %.*s", is_app, error_code, rlen, reason);
|
||||
if (is_app && conn->imc_conn.cn_version > LSQVER_ID27)
|
||||
{
|
||||
LSQ_DEBUG("convert to 0x1C, replace code and reason");
|
||||
is_app = 0;
|
||||
error_code = TEC_APPLICATION_ERROR;
|
||||
rlen = 0;
|
||||
}
|
||||
|
||||
pns = (conn->imc_flags >> IMCBIT_PNS_BIT_SHIFT) & 3;
|
||||
switch ((!!(conn->imc_flags & IMC_HSK_PACKET_SENT) << 1)
|
||||
|
@ -1844,9 +1873,21 @@ ietf_mini_conn_ci_record_addrs (struct lsquic_conn *lconn, void *peer_ctx,
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
ietf_mini_conn_ci_count_garbage (struct lsquic_conn *lconn, size_t garbage_sz)
|
||||
{
|
||||
struct ietf_mini_conn *conn = (struct ietf_mini_conn *) lconn;
|
||||
|
||||
conn->imc_bytes_in += garbage_sz;
|
||||
LSQ_DEBUG("count %zd bytes of garbage, new value: %u bytes", garbage_sz,
|
||||
conn->imc_bytes_in);
|
||||
}
|
||||
|
||||
|
||||
static const struct conn_iface mini_conn_ietf_iface = {
|
||||
.ci_abort_error = ietf_mini_conn_ci_abort_error,
|
||||
.ci_client_call_on_new = ietf_mini_conn_ci_client_call_on_new,
|
||||
.ci_count_garbage = ietf_mini_conn_ci_count_garbage,
|
||||
.ci_destroy = ietf_mini_conn_ci_destroy,
|
||||
.ci_get_engine = ietf_mini_conn_ci_get_engine,
|
||||
.ci_get_log_cid = ietf_mini_conn_ci_get_log_cid,
|
||||
|
|
|
@ -238,6 +238,6 @@ extern const char *const lsquic_pns2str[];
|
|||
ALL_IQUIC_FRAMES & ~(QUIC_FTBIT_PADDING|QUIC_FTBIT_PATH_RESPONSE \
|
||||
|QUIC_FTBIT_PATH_CHALLENGE|QUIC_FTBIT_ACK|QUIC_FTBIT_TIMESTAMP))
|
||||
|
||||
extern const enum quic_ft_bit lsquic_legal_frames_by_level[];
|
||||
extern const enum quic_ft_bit lsquic_legal_frames_by_level[][4];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -217,9 +217,38 @@ lsquic_cid_from_packet (const unsigned char *buf, size_t bufsz,
|
|||
}
|
||||
|
||||
|
||||
/* See [draft-ietf-quic-transport-25], Section 12.4 (Table 3) */
|
||||
const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
|
||||
/* See [draft-ietf-quic-transport-28], Section 12.4 (Table 3) */
|
||||
const enum quic_ft_bit lsquic_legal_frames_by_level[N_LSQVER][N_ENC_LEVS] =
|
||||
{
|
||||
[LSQVER_ID28] = {
|
||||
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
|
||||
| QUIC_FTBIT_BLOCKED | QUIC_FTBIT_CONNECTION_CLOSE
|
||||
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
|
||||
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
|
||||
| QUIC_FTBIT_STREAMS_BLOCKED
|
||||
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
|
||||
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
|
||||
| QUIC_FTBIT_RETIRE_CONNECTION_ID,
|
||||
[ENC_LEV_INIT] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK| QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_FORW] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE
|
||||
| QUIC_FTBIT_STREAM | QUIC_FTBIT_RST_STREAM
|
||||
| QUIC_FTBIT_BLOCKED
|
||||
| QUIC_FTBIT_MAX_DATA | QUIC_FTBIT_MAX_STREAM_DATA
|
||||
| QUIC_FTBIT_MAX_STREAMS | QUIC_FTBIT_STREAM_BLOCKED
|
||||
| QUIC_FTBIT_STREAMS_BLOCKED
|
||||
| QUIC_FTBIT_NEW_CONNECTION_ID | QUIC_FTBIT_STOP_SENDING
|
||||
| QUIC_FTBIT_PATH_CHALLENGE | QUIC_FTBIT_PATH_RESPONSE
|
||||
| QUIC_FTBIT_HANDSHAKE_DONE | QUIC_FTBIT_ACK_FREQUENCY
|
||||
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
|
||||
| QUIC_FTBIT_TIMESTAMP
|
||||
,
|
||||
},
|
||||
[LSQVER_ID27] = {
|
||||
[ENC_LEV_CLEAR] = QUIC_FTBIT_CRYPTO | QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
| QUIC_FTBIT_ACK | QUIC_FTBIT_CONNECTION_CLOSE,
|
||||
[ENC_LEV_EARLY] = QUIC_FTBIT_PADDING | QUIC_FTBIT_PING
|
||||
|
@ -246,4 +275,5 @@ const enum quic_ft_bit lsquic_legal_frames_by_level[N_ENC_LEVS] =
|
|||
| QUIC_FTBIT_RETIRE_CONNECTION_ID | QUIC_FTBIT_NEW_TOKEN
|
||||
| QUIC_FTBIT_TIMESTAMP
|
||||
,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#ifndef LSQUIC_PARSE_COMMON_H
|
||||
#define LSQUIC_PARSE_COMMON_H 1
|
||||
|
||||
#ifdef WIN32
|
||||
#include "vc_compat.h"
|
||||
#endif
|
||||
|
||||
struct lsquic_packet_in;
|
||||
struct packin_parse_state;
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ static const unsigned char simple_prst_payload[] = {
|
|||
|
||||
|
||||
typedef char correct_simple_prst_size[(GQUIC_RESET_SZ ==
|
||||
1 + GQUIC_CID_LEN + sizeof(simple_prst_payload)) - 1];
|
||||
1 + GQUIC_CID_LEN + sizeof(simple_prst_payload)) ? 1 : -1 ];
|
||||
|
||||
|
||||
ssize_t
|
||||
|
|
|
@ -353,6 +353,10 @@ ietf_v1_gen_stream_frame (unsigned char *buf, size_t buf_len,
|
|||
unsigned slen, olen, dlen;
|
||||
unsigned char *p = buf + 1;
|
||||
|
||||
#if _MSC_VER
|
||||
obits = 0, dbits = 0;
|
||||
#endif
|
||||
|
||||
assert(!!fin ^ !!size);
|
||||
|
||||
/* We do not check that stream_id, offset, and size are smaller
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/rand.h>
|
||||
|
@ -355,7 +358,7 @@ lsquic_prq_new_req (struct pr_queue *prq, enum packet_req_type type,
|
|||
version = lsquic_tag2ver(ver_tag);
|
||||
}
|
||||
else /* Got to set it to something sensible... */
|
||||
version = LSQVER_ID25;
|
||||
version = LSQVER_ID27;
|
||||
|
||||
lsquic_scid_from_packet_in(packet_in, &scid);
|
||||
return lsquic_prq_new_req_ext(prq, type, flags, version,
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_int_types.h"
|
||||
|
@ -333,13 +337,22 @@ qeh_write_headers (struct qpack_enc_hdl *qeh, lsquic_stream_id_t stream_id,
|
|||
enum lsqpack_enc_status st;
|
||||
int i, s, write_to_stream;
|
||||
enum lsqpack_enc_flags enc_flags;
|
||||
enum qwh_status retval;
|
||||
#ifndef WIN32
|
||||
unsigned char enc_buf[ qeh->qeh_encoder.qpe_cur_max_capacity * 2 ];
|
||||
#else
|
||||
unsigned char *enc_buf;
|
||||
enc_buf = _malloca(qeh->qeh_encoder.qpe_cur_max_capacity * 2);
|
||||
if (!enc_buf)
|
||||
return QWH_ERR;
|
||||
#endif
|
||||
|
||||
s = lsqpack_enc_start_header(&qeh->qeh_encoder, stream_id, 0);
|
||||
if (s != 0)
|
||||
{
|
||||
LSQ_WARN("cannot start header");
|
||||
return QWH_ERR;
|
||||
retval = QWH_ERR;
|
||||
goto end;
|
||||
}
|
||||
LSQ_DEBUG("begin encoding headers for stream %"PRIu64, stream_id);
|
||||
|
||||
|
@ -384,7 +397,8 @@ qeh_write_headers (struct qpack_enc_hdl *qeh, lsquic_stream_id_t stream_id,
|
|||
{
|
||||
LSQ_INFO("could not write to encoder stream: %s",
|
||||
strerror(errno));
|
||||
return QWH_ERR;
|
||||
retval = QWH_ERR;
|
||||
goto end;
|
||||
}
|
||||
write_to_stream = 0;
|
||||
enc_p = enc_buf + (size_t) nw;
|
||||
|
@ -395,18 +409,22 @@ qeh_write_headers (struct qpack_enc_hdl *qeh, lsquic_stream_id_t stream_id,
|
|||
if (0 != lsquic_frab_list_write(&qeh->qeh_fral, enc_p, enc_sz))
|
||||
{
|
||||
LSQ_INFO("could not write to frab list");
|
||||
return QWH_ERR;
|
||||
retval = QWH_ERR;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LQES_NOBUF_HEAD:
|
||||
return QWH_ENOBUF;
|
||||
retval = QWH_ENOBUF;
|
||||
goto end;
|
||||
default:
|
||||
assert(0);
|
||||
return QWH_ERR;
|
||||
retval = QWH_ERR;
|
||||
goto end;
|
||||
case LQES_NOBUF_ENC:
|
||||
LSQ_DEBUG("not enough room to write encoder stream data");
|
||||
return QWH_ERR;
|
||||
retval = QWH_ERR;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,7 +433,8 @@ qeh_write_headers (struct qpack_enc_hdl *qeh, lsquic_stream_id_t stream_id,
|
|||
if (nw <= 0)
|
||||
{
|
||||
LSQ_WARN("could not end header: %zd", nw);
|
||||
return QWH_ERR;
|
||||
retval = QWH_ERR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((size_t) nw < *prefix_sz)
|
||||
|
@ -429,7 +448,8 @@ qeh_write_headers (struct qpack_enc_hdl *qeh, lsquic_stream_id_t stream_id,
|
|||
LSQ_DEBUG("all %zd bytes of encoder stream written out; header block "
|
||||
"is %zd bytes; estimated compression ratio %.3f", total_enc_sz,
|
||||
*headers_sz, lsqpack_enc_ratio(&qeh->qeh_encoder));
|
||||
return QWH_FULL;
|
||||
retval = QWH_FULL;
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -439,8 +459,15 @@ qeh_write_headers (struct qpack_enc_hdl *qeh, lsquic_stream_id_t stream_id,
|
|||
"buffered; header block is %zd bytes; estimated compression ratio "
|
||||
"%.3f", total_enc_sz, lsquic_frab_list_size(&qeh->qeh_fral),
|
||||
*headers_sz, lsqpack_enc_ratio(&qeh->qeh_encoder));
|
||||
return QWH_PARTIAL;
|
||||
retval = QWH_PARTIAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
#ifdef WIN32
|
||||
_freea(enc_buf);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1542,6 +1542,9 @@ lsquic_send_ctl_do_sanity_check (const struct lsquic_send_ctl *ctl)
|
|||
unsigned count, bytes;
|
||||
enum packnum_space pns;
|
||||
|
||||
#if _MSC_VER
|
||||
prev_packno = 0;
|
||||
#endif
|
||||
count = 0, bytes = 0;
|
||||
for (pns = PNS_INIT; pns <= PNS_APP; ++pns)
|
||||
{
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic.h"
|
||||
|
||||
|
|
|
@ -205,4 +205,4 @@ const struct lsquic_shared_hash_if stock_shi =
|
|||
|
||||
/* Need this to save one malloc using malo: */
|
||||
typedef char hash_not_larger_than_hash_elem [
|
||||
(sizeof(struct stock_shared_hash) <= sizeof(struct hash_elem)) - 1];
|
||||
(sizeof(struct stock_shared_hash) <= sizeof(struct hash_elem)) ? 1 : -1];
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#include <sys/queue.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "fiu-local.h"
|
||||
|
||||
#include "lsquic.h"
|
||||
|
@ -3173,6 +3177,10 @@ update_buffered_hq_frames (struct lsquic_stream *stream, size_t len,
|
|||
uint64_t cur_off, end;
|
||||
size_t frame_sz;
|
||||
unsigned extendable;
|
||||
#if _MSC_VER
|
||||
end = 0;
|
||||
extendable = 0;
|
||||
#endif
|
||||
|
||||
cur_off = stream->sm_payload + stream->sm_n_buffered;
|
||||
STAILQ_FOREACH(shf, &stream->sm_hq_frames, shf_next)
|
||||
|
@ -3437,7 +3445,15 @@ send_headers_ietf (struct lsquic_stream *stream,
|
|||
ssize_t nw;
|
||||
unsigned char *header_block;
|
||||
enum lsqpack_enc_header_flags hflags;
|
||||
unsigned char buf[max_push_size + max_prefix_size + MAX_HEADERS_SIZE];
|
||||
int rv;
|
||||
const size_t buf_sz = max_push_size + max_prefix_size + MAX_HEADERS_SIZE;
|
||||
#ifndef WIN32
|
||||
unsigned char buf[buf_sz];
|
||||
#else
|
||||
unsigned char *buf = _malloca(buf_sz);
|
||||
if (!buf)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
stream->stream_flags &= ~STREAM_PUSHING;
|
||||
stream->stream_flags |= STREAM_NOPUSH;
|
||||
|
@ -3446,7 +3462,7 @@ send_headers_ietf (struct lsquic_stream *stream,
|
|||
* back to a larger buffer if that fails.
|
||||
*/
|
||||
prefix_sz = max_prefix_size;
|
||||
headers_sz = sizeof(buf) - max_prefix_size - max_push_size;
|
||||
headers_sz = buf_sz - max_prefix_size - max_push_size;
|
||||
qwh = lsquic_qeh_write_headers(stream->conn_pub->u.ietf.qeh, stream->id, 0,
|
||||
headers, buf + max_push_size + max_prefix_size, &prefix_sz,
|
||||
&headers_sz, &stream->sm_hb_compl, &hflags);
|
||||
|
@ -3457,7 +3473,7 @@ send_headers_ietf (struct lsquic_stream *stream,
|
|||
LSQ_INFO("not enough room for header block");
|
||||
else
|
||||
LSQ_WARN("internal error encoding and sending HTTP headers");
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (hflags & LSQECH_REF_NEW_ENTRIES)
|
||||
|
@ -3471,7 +3487,7 @@ send_headers_ietf (struct lsquic_stream *stream,
|
|||
if (!stream_activate_hq_frame(stream,
|
||||
stream->sm_payload + stream->sm_n_buffered, HQFT_PUSH_PREAMBLE,
|
||||
SHF_FIXED_SIZE|SHF_PHANTOM, push_sz))
|
||||
return -1;
|
||||
goto err;
|
||||
buf[max_push_size + max_prefix_size - prefix_sz - push_sz] = HQUST_PUSH;
|
||||
vint_write(buf + max_push_size + max_prefix_size - prefix_sz
|
||||
- push_sz + 1,stream->sm_promise->pp_id, bits, 1 << bits);
|
||||
|
@ -3485,7 +3501,7 @@ send_headers_ietf (struct lsquic_stream *stream,
|
|||
if (!stream_activate_hq_frame(stream,
|
||||
stream->sm_payload + stream->sm_n_buffered + push_sz,
|
||||
HQFT_HEADERS, SHF_FIXED_SIZE, hblock_sz - push_sz))
|
||||
return -1;
|
||||
goto err;
|
||||
|
||||
if (qwh == QWH_FULL)
|
||||
{
|
||||
|
@ -3496,14 +3512,14 @@ send_headers_ietf (struct lsquic_stream *stream,
|
|||
if (nw < 0)
|
||||
{
|
||||
LSQ_WARN("cannot write to stream: %s", strerror(errno));
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
if ((size_t) nw == hblock_sz)
|
||||
{
|
||||
stream->stream_flags |= STREAM_HEADERS_SENT;
|
||||
stream_hblock_sent(stream);
|
||||
LSQ_DEBUG("wrote all %zu bytes of header block", hblock_sz);
|
||||
return 0;
|
||||
goto end;
|
||||
}
|
||||
LSQ_DEBUG("wrote only %zd bytes of header block, stash", nw);
|
||||
}
|
||||
|
@ -3528,14 +3544,25 @@ send_headers_ietf (struct lsquic_stream *stream,
|
|||
{
|
||||
LSQ_WARN("cannot allocate %zd bytes to stash %s header block",
|
||||
hblock_sz - (size_t) nw, qwh == QWH_FULL ? "full" : "partial");
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
memcpy(stream->sm_header_block, header_block + (size_t) nw,
|
||||
hblock_sz - (size_t) nw);
|
||||
stream->sm_hblock_sz = hblock_sz - (size_t) nw;
|
||||
stream->sm_hblock_off = 0;
|
||||
LSQ_DEBUG("stashed %u bytes of header block", stream->sm_hblock_sz);
|
||||
return 0;
|
||||
|
||||
end:
|
||||
rv = 0;
|
||||
clean:
|
||||
#ifdef WIN32
|
||||
_freea(buf);
|
||||
#endif
|
||||
return rv;
|
||||
|
||||
err:
|
||||
rv = -1;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4560,7 +4587,7 @@ pp_reader_read (void *lsqr_ctx, void *buf, size_t count)
|
|||
{
|
||||
struct push_promise *const promise = lsqr_ctx;
|
||||
unsigned char *dst = buf;
|
||||
unsigned char *const end = buf + count;
|
||||
unsigned char *const end = dst + count;
|
||||
size_t len;
|
||||
|
||||
while (dst < end)
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#include <assert.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/hkdf.h>
|
||||
#include <openssl/rand.h>
|
||||
|
@ -31,7 +34,7 @@
|
|||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
#define TOKGEN_VERSION 1
|
||||
#define TOKGEN_VERSION 2
|
||||
|
||||
#define CRYPTER_KEY_SIZE 16
|
||||
#define SRST_MAX_PRK_SIZE EVP_MAX_MD_SIZE
|
||||
|
@ -65,6 +68,8 @@ struct crypter
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct token_generator
|
||||
{
|
||||
/* We encrypt different token types using different keys. */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,7 @@ enum transport_param_id
|
|||
* Numeric transport parameters that have default values:
|
||||
*/
|
||||
TPI_MAX_IDLE_TIMEOUT,
|
||||
TPI_MAX_PACKET_SIZE,
|
||||
TPI_MAX_UDP_PAYLOAD_SIZE,
|
||||
TPI_INIT_MAX_DATA,
|
||||
TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL,
|
||||
TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE,
|
||||
|
@ -45,7 +45,12 @@ enum transport_param_id
|
|||
* Custom handlers:
|
||||
*/
|
||||
TPI_PREFERRED_ADDRESS,
|
||||
TPI_ORIGINAL_CONNECTION_ID,
|
||||
/* CIDs must be in a contiguous range for tp_cids array to work */
|
||||
#define FIRST_TP_CID TPI_ORIGINAL_DEST_CID
|
||||
TPI_ORIGINAL_DEST_CID,
|
||||
TPI_INITIAL_SOURCE_CID,
|
||||
#define LAST_TP_CID TPI_RETRY_SOURCE_CID
|
||||
TPI_RETRY_SOURCE_CID,
|
||||
#if LSQUIC_TEST_QUANTUM_READINESS
|
||||
/* https://github.com/quicwg/base-drafts/wiki/Quantum-Readiness-test */
|
||||
#define QUANTUM_READY_SZ 1200
|
||||
|
@ -54,6 +59,8 @@ enum transport_param_id
|
|||
TPI_STATELESS_RESET_TOKEN, LAST_TPI = TPI_STATELESS_RESET_TOKEN
|
||||
};
|
||||
|
||||
#define TP_CID_IDX(tpi_) ((tpi_) - FIRST_TP_CID)
|
||||
|
||||
|
||||
struct transport_params
|
||||
{
|
||||
|
@ -72,7 +79,7 @@ struct transport_params
|
|||
#define tp_max_idle_timeout tp_numerics[TPI_MAX_IDLE_TIMEOUT]
|
||||
#define tp_init_max_streams_bidi tp_numerics[TPI_INIT_MAX_STREAMS_BIDI]
|
||||
#define tp_init_max_streams_uni tp_numerics[TPI_INIT_MAX_STREAMS_UNI]
|
||||
#define tp_max_packet_size tp_numerics[TPI_MAX_PACKET_SIZE]
|
||||
#define tp_max_udp_payload_size tp_numerics[TPI_MAX_UDP_PAYLOAD_SIZE]
|
||||
#define tp_ack_delay_exponent tp_numerics[TPI_ACK_DELAY_EXPONENT]
|
||||
#define tp_max_ack_delay tp_numerics[TPI_MAX_ACK_DELAY]
|
||||
#define tp_active_connection_id_limit tp_numerics[TPI_ACTIVE_CONNECTION_ID_LIMIT]
|
||||
|
@ -87,10 +94,20 @@ struct transport_params
|
|||
lsquic_cid_t cid;
|
||||
uint8_t srst[IQUIC_SRESET_TOKEN_SZ];
|
||||
} tp_preferred_address;
|
||||
lsquic_cid_t tp_original_cid;
|
||||
lsquic_cid_t tp_cids[3];
|
||||
#define tp_original_dest_cid tp_cids[TP_CID_IDX(TPI_ORIGINAL_DEST_CID)]
|
||||
#define tp_initial_source_cid tp_cids[TP_CID_IDX(TPI_INITIAL_SOURCE_CID)]
|
||||
#define tp_retry_source_cid tp_cids[TP_CID_IDX(TPI_RETRY_SOURCE_CID)]
|
||||
};
|
||||
|
||||
#define TP_DEF_MAX_PACKET_SIZE 65527
|
||||
#define MAX_TP_STR_SZ ((LAST_TPI + 1) * \
|
||||
(34 /* longest entry in tt2str */ + 2 /* semicolon */ + 2 /* colon */) \
|
||||
+ INET_ADDRSTRLEN + INET6_ADDRSTRLEN + 5 /* Port */ * 2 \
|
||||
+ MAX_CID_LEN * 2 * 4 /* there are four CIDs */ \
|
||||
+ 11 * (MAX_NUMERIC_TPI + 1) \
|
||||
+ IQUIC_SRESET_TOKEN_SZ * 2 * 2 /* there are two reset tokens */)
|
||||
|
||||
#define TP_DEF_MAX_UDP_PAYLOAD_SIZE 65527
|
||||
#define TP_DEF_ACK_DELAY_EXP 3
|
||||
#define TP_DEF_INIT_MAX_STREAMS_UNI 0
|
||||
#define TP_DEF_INIT_MAX_STREAMS_BIDI 0
|
||||
|
@ -111,7 +128,7 @@ struct transport_params
|
|||
.tp_active_connection_id_limit = TP_DEF_ACTIVE_CONNECTION_ID_LIMIT, \
|
||||
.tp_max_idle_timeout = TP_DEF_MAX_IDLE_TIMEOUT, \
|
||||
.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY, \
|
||||
.tp_max_packet_size = TP_DEF_MAX_PACKET_SIZE, \
|
||||
.tp_max_udp_payload_size = TP_DEF_MAX_UDP_PAYLOAD_SIZE, \
|
||||
.tp_ack_delay_exponent = TP_DEF_ACK_DELAY_EXP, \
|
||||
.tp_init_max_streams_bidi = TP_DEF_INIT_MAX_STREAMS_BIDI, \
|
||||
.tp_init_max_streams_uni = TP_DEF_INIT_MAX_STREAMS_UNI, \
|
||||
|
@ -124,10 +141,10 @@ struct transport_params
|
|||
|
||||
int
|
||||
lsquic_tp_encode (const struct transport_params *, int is_server,
|
||||
unsigned char *buf, size_t bufsz);
|
||||
unsigned char *const buf, size_t bufsz);
|
||||
|
||||
int
|
||||
lsquic_tp_decode (const unsigned char *buf, size_t bufsz,
|
||||
lsquic_tp_decode (const unsigned char *const buf, size_t bufsz,
|
||||
/* This argument specifies whose transport parameters we are parsing. If
|
||||
* true, we are parsing parameters sent by the server; if false, we are
|
||||
* parsing parameteres sent by the client.
|
||||
|
@ -135,21 +152,27 @@ lsquic_tp_decode (const unsigned char *buf, size_t bufsz,
|
|||
int is_server,
|
||||
struct transport_params *);
|
||||
|
||||
int
|
||||
lsquic_tp_encode_id25 (const struct transport_params *, int is_server,
|
||||
unsigned char *buf, size_t bufsz);
|
||||
|
||||
int
|
||||
lsquic_tp_decode_id25 (const unsigned char *buf, size_t bufsz,
|
||||
int is_server, struct transport_params *);
|
||||
|
||||
void
|
||||
lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz);
|
||||
|
||||
int
|
||||
lsquic_tp_encode_27 (const struct transport_params *, int is_server,
|
||||
unsigned char *const buf, size_t bufsz);
|
||||
|
||||
int
|
||||
lsquic_tp_decode_27 (const unsigned char *const buf, size_t bufsz,
|
||||
int is_server,
|
||||
struct transport_params *);
|
||||
|
||||
void
|
||||
lsquic_tp_to_str_27 (const struct transport_params *params, char *buf, size_t sz);
|
||||
|
||||
int
|
||||
lsquic_tp_has_pref_ipv4 (const struct transport_params *);
|
||||
|
||||
int
|
||||
lsquic_tp_has_pref_ipv6 (const struct transport_params *);
|
||||
|
||||
extern const char * const lsquic_tpi2str[LAST_TPI + 1];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,14 +9,15 @@
|
|||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <vc_compat.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__)
|
||||
#include <mach/mach_time.h>
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_version.h"
|
||||
|
||||
#if _MSC_VER
|
||||
#include "vc_compat.h"
|
||||
#endif
|
||||
|
||||
|
||||
static const unsigned char version_tags[N_LSQVER][4] =
|
||||
{
|
||||
|
@ -14,8 +18,8 @@ static const unsigned char version_tags[N_LSQVER][4] =
|
|||
#if LSQUIC_USE_Q098
|
||||
[LSQVER_098] = { 'Q', '0', '9', '8', },
|
||||
#endif
|
||||
[LSQVER_ID25] = { 0xFF, 0, 0, 25, },
|
||||
[LSQVER_ID27] = { 0xFF, 0, 0, 27, },
|
||||
[LSQVER_ID28] = { 0xFF, 0, 0, 28, },
|
||||
[LSQVER_VERNEG] = { 0xFA, 0xFA, 0xFA, 0xFA, },
|
||||
};
|
||||
|
||||
|
@ -52,8 +56,8 @@ const char *const lsquic_ver2str[N_LSQVER] = {
|
|||
#if LSQUIC_USE_Q098
|
||||
[LSQVER_098] = "Q098",
|
||||
#endif
|
||||
[LSQVER_ID25] = "FF000019",
|
||||
[LSQVER_ID27] = "FF00001B",
|
||||
[LSQVER_ID28] = "FF00001C",
|
||||
[LSQVER_VERNEG] = "FAFAFAFA",
|
||||
};
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 8d4b795ff661e73e10b7d46ce06cba3b88499769
|
||||
Subproject commit b577d56964e443972adb38ec56706181846cc47f
|
|
@ -45,7 +45,6 @@ SET(TESTS
|
|||
frame_writer
|
||||
goaway_gquic_be
|
||||
h3_framing
|
||||
hcsi_reader
|
||||
hkdf
|
||||
lsquic_hash
|
||||
packet_out
|
||||
|
@ -82,6 +81,8 @@ ENDIF()
|
|||
IF (NOT CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
# No regexes on Windows
|
||||
SET(TESTS ${TESTS} ack_merge)
|
||||
# No open_memstream() on Windows
|
||||
SET(TESTS ${TESTS} hcsi_reader)
|
||||
ENDIF()
|
||||
|
||||
|
||||
|
@ -98,21 +99,27 @@ ADD_TEST(stream_hash test_stream -h)
|
|||
ADD_TEST(stream_A test_stream -A)
|
||||
ADD_TEST(stream_hash_A test_stream -A -h)
|
||||
|
||||
IF(NOT MSVC)
|
||||
ADD_EXECUTABLE(graph_cubic graph_cubic.c ${ADDL_SOURCES})
|
||||
TARGET_LINK_LIBRARIES(graph_cubic ${LIBS})
|
||||
|
||||
ADD_EXECUTABLE(mini_parse mini_parse.c ${ADDL_SOURCES})
|
||||
TARGET_LINK_LIBRARIES(mini_parse ${LIBS})
|
||||
ENDIF()
|
||||
|
||||
ADD_EXECUTABLE(test_min_heap test_min_heap.c ../src/liblsquic/lsquic_min_heap.c)
|
||||
ADD_TEST(min_heap test_min_heap)
|
||||
|
||||
ADD_EXECUTABLE(test_malo_pooled test_malo.c ../src/liblsquic/lsquic_malo.c)
|
||||
SET(MALO_SRC test_malo.c ../src/liblsquic/lsquic_malo.c)
|
||||
IF(MSVC)
|
||||
LIST(APPEND MALO_SRC ../wincompat/getopt.c)
|
||||
ENDIF()
|
||||
ADD_EXECUTABLE(test_malo_pooled ${MALO_SRC})
|
||||
SET_TARGET_PROPERTIES(test_malo_pooled
|
||||
PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -DLSQUIC_USE_POOLS=1")
|
||||
ADD_TEST(malo_pooled test_malo_pooled)
|
||||
|
||||
ADD_EXECUTABLE(test_malo_nopool test_malo.c ../src/liblsquic/lsquic_malo.c)
|
||||
ADD_EXECUTABLE(test_malo_nopool ${MALO_SRC})
|
||||
SET_TARGET_PROPERTIES(test_malo_nopool
|
||||
PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -DLSQUIC_USE_POOLS=0")
|
||||
ADD_TEST(malo_nopool test_malo_nopool)
|
||||
|
|
|
@ -10,12 +10,16 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_types.h"
|
||||
|
|
|
@ -179,7 +179,7 @@ run_test (const struct test *test)
|
|||
size_t sz;
|
||||
unsigned char buf[0x1000];
|
||||
|
||||
pf = select_pf_by_ver(LSQVER_ID25);
|
||||
pf = select_pf_by_ver(LSQVER_ID27);
|
||||
if (!test->skip_gen)
|
||||
{
|
||||
rechist.acki = &test->acki;
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "vc_compat.h"
|
||||
#endif
|
||||
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_rechist.h"
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include "vc_compat.h"
|
||||
#endif
|
||||
|
||||
#include "lsquic_types.h"
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include "vc_compat.h"
|
||||
#endif
|
||||
|
||||
#include "lsquic_types.h"
|
||||
|
@ -17,7 +19,7 @@
|
|||
|
||||
static struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 0);
|
||||
|
||||
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID25);
|
||||
static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_ID27);
|
||||
|
||||
|
||||
static void
|
||||
|
|
|
@ -105,7 +105,8 @@ main (void)
|
|||
unsigned const count = popcount(i);
|
||||
unsigned const min_n = i % count;
|
||||
unsigned const min_t = t++;
|
||||
unsigned j, n, ids[2];
|
||||
unsigned j, n;
|
||||
enum alarm_id ids[2];
|
||||
for (j = 0, n = 0; j < MAX_LSQUIC_ALARMS; ++j)
|
||||
{
|
||||
if ((1u << j) & i)
|
||||
|
|
|
@ -115,6 +115,9 @@ test_attq_ordering (enum sort_action sa)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
prev = 0;
|
||||
#endif
|
||||
for (i = 0; i < sizeof(curiosity); ++i)
|
||||
{
|
||||
next_attq = lsquic_attq_next(q);
|
||||
|
|
|
@ -33,7 +33,7 @@ struct test {
|
|||
static const struct test tests[] = {
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.offset = 0,
|
||||
.data_sz = 10,
|
||||
.data = "0123456789",
|
||||
|
@ -49,7 +49,7 @@ static const struct test tests[] = {
|
|||
},
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.offset = 500,
|
||||
.data_sz = 10,
|
||||
.data = "0123456789",
|
||||
|
|
|
@ -38,7 +38,7 @@ test_post_quiescence_explosion (void)
|
|||
struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 8);
|
||||
struct lsquic_conn_public conn_pub = { .lconn = &lconn, };
|
||||
int i;
|
||||
struct lsquic_packet_out packet_out = {};
|
||||
struct lsquic_packet_out packet_out; memset(&packet_out, 0, sizeof(packet_out));
|
||||
|
||||
cci->cci_init(&cubic, &conn_pub, 0);
|
||||
cubic.cu_ssthresh = cubic.cu_cwnd = 32 * 1370;
|
||||
|
@ -72,7 +72,7 @@ test_post_quiescence_explosion2 (void)
|
|||
struct lsquic_conn lconn = LSCONN_INITIALIZER_CIDLEN(lconn, 8);
|
||||
struct lsquic_conn_public conn_pub = { .lconn = &lconn, };
|
||||
int i;
|
||||
struct lsquic_packet_out packet_out = {};
|
||||
struct lsquic_packet_out packet_out; memset(&packet_out, 0, sizeof(packet_out));
|
||||
|
||||
cci->cci_init(&cubic, &conn_pub, 0);
|
||||
cubic.cu_ssthresh = cubic.cu_cwnd = 32 * 1370;
|
||||
|
|
|
@ -442,6 +442,8 @@ run_ekt_test (const struct export_key_test *test)
|
|||
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
if (i && !(test->ekt_ikm_sz == 32 && test->ekt_client_key_sz == 16 && test->ekt_server_key_sz == 16))
|
||||
continue;
|
||||
s = lsquic_export_key_material(test->ekt_ikm, (uint32_t)test->ekt_ikm_sz,
|
||||
test->ekt_salt, (int)test->ekt_salt_sz,
|
||||
test->ekt_context, (uint32_t)test->ekt_context_sz,
|
||||
|
|
|
@ -94,7 +94,7 @@ stream_write (struct lsquic_stream *stream, struct lsquic_reader *reader)
|
|||
}
|
||||
|
||||
|
||||
#define XHDR(name_, value_) .buf = value_, .name_ptr = name_, .val_len = sizeof(value_) - 1, .name_len = sizeof(name_) - 1
|
||||
#define XHDR(name_, value_) .buf = name_ value_, .name_offset = 0, .name_len = sizeof(name_) - 1, .val_offset = sizeof(name_) - 1, .val_len = sizeof(value_) - 1,
|
||||
|
||||
|
||||
static void
|
||||
|
|
|
@ -1136,7 +1136,7 @@ test_one_frt (const struct frame_reader_test *frt)
|
|||
|
||||
top:
|
||||
lsquic_mm_init(&mm);
|
||||
lshpack_dec_init(&hdec, LSHPACK_DEC_HTTP1X);
|
||||
lshpack_dec_init(&hdec);
|
||||
memset(&input, 0, sizeof(input));
|
||||
memcpy(input.in_buf, frt->frt_buf, frt->frt_bufsz);
|
||||
input.in_sz = frt->frt_bufsz;
|
||||
|
|
|
@ -225,7 +225,7 @@ test_rw (unsigned max_frame_sz)
|
|||
|
||||
lsquic_mm_init(&mm);
|
||||
lshpack_enc_init(&henc);
|
||||
lshpack_dec_init(&hdec, LSHPACK_DEC_HTTP1X);
|
||||
lshpack_dec_init(&hdec);
|
||||
stream = stream_new();
|
||||
stream->sm_max_sz = 1;
|
||||
|
||||
|
@ -340,7 +340,7 @@ main (int argc, char **argv)
|
|||
}
|
||||
|
||||
|
||||
#define XHDR(name_, value_) .buf = value_, .name_ptr = name_, .val_len = sizeof(value_) - 1, .name_len = sizeof(name_) - 1
|
||||
#define XHDR(name_, value_) .buf = name_ value_, .name_offset = 0, .name_len = sizeof(name_) - 1, .val_offset = sizeof(name_) - 1, .val_len = sizeof(value_) - 1,
|
||||
|
||||
/* This list is hardcoded to make the test deterministic */
|
||||
static struct lsxpack_header header_arr[N_HEADERS] =
|
||||
|
|
|
@ -63,7 +63,7 @@ output_write (struct lsquic_stream *stream, struct lsquic_reader *reader)
|
|||
|
||||
|
||||
#define IOV(v) { .iov_base = (v), .iov_len = sizeof(v) - 1, }
|
||||
#define XHDR(name_, value_) .buf = value_, .name_ptr = name_, .val_len = sizeof(value_) - 1, .name_len = sizeof(name_) - 1
|
||||
#define XHDR(name_, value_) .buf = name_ value_, .name_offset = 0, .name_len = sizeof(name_) - 1, .val_offset = sizeof(name_) - 1, .val_len = sizeof(value_) - 1,
|
||||
|
||||
|
||||
static void
|
||||
|
@ -162,6 +162,31 @@ test_one_header (void)
|
|||
lsquic_mm_cleanup(&mm);
|
||||
}
|
||||
|
||||
struct header_buf
|
||||
{
|
||||
unsigned off;
|
||||
char buf[UINT16_MAX];
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
header_set_ptr (struct lsxpack_header *hdr, struct header_buf *header_buf,
|
||||
const char *name, size_t name_len,
|
||||
const char *val, size_t val_len)
|
||||
{
|
||||
if (header_buf->off + name_len + val_len <= sizeof(header_buf->buf))
|
||||
{
|
||||
memcpy(header_buf->buf + header_buf->off, name, name_len);
|
||||
memcpy(header_buf->buf + header_buf->off + name_len, val, val_len);
|
||||
lsxpack_header_set_offset2(hdr, header_buf->buf + header_buf->off,
|
||||
0, name_len, name_len, val_len);
|
||||
header_buf->off += name_len + val_len;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_oversize_header (void)
|
||||
|
@ -172,6 +197,7 @@ test_oversize_header (void)
|
|||
struct lsquic_mm mm;
|
||||
const size_t big_len = LSXPACK_MAX_STRLEN - 20;
|
||||
char *value;
|
||||
struct header_buf hbuf;
|
||||
|
||||
lshpack_enc_init(&henc);
|
||||
lsquic_mm_init(&mm);
|
||||
|
@ -190,8 +216,9 @@ test_oversize_header (void)
|
|||
{
|
||||
{ XHDR(":status", "302") },
|
||||
};
|
||||
lsxpack_header_set_ptr(&header_arr[1], "some-header", 10, value, big_len);
|
||||
lsxpack_header_set_ptr(&header_arr[2], "another-header", 10, value, big_len);
|
||||
hbuf.off = 0;
|
||||
header_set_ptr(&header_arr[1], &hbuf, "some-header", 10, value, big_len);
|
||||
header_set_ptr(&header_arr[2], &hbuf, "another-header", 10, value, big_len);
|
||||
|
||||
struct lsquic_http_headers headers = {
|
||||
.count = sizeof(header_arr) / sizeof(header_arr[0]),
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#include "lsquic_hq.h"
|
||||
#include "lsquic_data_in_if.h"
|
||||
|
||||
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID25);
|
||||
static const struct parse_funcs *g_pf = select_pf_by_ver(LSQVER_ID27);
|
||||
|
||||
struct test_ctl_settings
|
||||
{
|
||||
|
@ -302,7 +302,7 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
|
|||
memset(tobjs, 0, sizeof(*tobjs));
|
||||
LSCONN_INITIALIZE(&tobjs->lconn);
|
||||
tobjs->lconn.cn_pf = g_pf;
|
||||
tobjs->lconn.cn_version = LSQVER_ID25;
|
||||
tobjs->lconn.cn_version = LSQVER_ID27;
|
||||
tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_ietf_v1;
|
||||
network_path.np_pack_size = packet_sz;
|
||||
tobjs->lconn.cn_if = &our_conn_if;
|
||||
|
@ -493,6 +493,8 @@ static const struct lsquic_stream_if packetization_inside_many_stream_if = {
|
|||
};
|
||||
|
||||
|
||||
#define XHDR(name_, value_) .buf = name_ value_, .name_offset = 0, .name_len = sizeof(name_) - 1, .val_offset = sizeof(name_) - 1, .val_len = sizeof(value_) - 1,
|
||||
|
||||
static void
|
||||
test_hq_framing (int sched_immed, int dispatch_once, unsigned wsize,
|
||||
int flush_after_each_write, size_t conn_limit,
|
||||
|
@ -509,8 +511,7 @@ test_hq_framing (int sched_immed, int dispatch_once, unsigned wsize,
|
|||
* data-framing writer. This is simply so that we don't have to
|
||||
* expose more stream things only for testing.
|
||||
*/
|
||||
struct lsxpack_header header;
|
||||
lsxpack_header_set_ptr(&header, ":method", 7, "GET", 3);
|
||||
struct lsxpack_header header = { XHDR(":method", "GET") };
|
||||
struct lsquic_http_headers headers = { 1, &header, };
|
||||
|
||||
buf_in = malloc(buf_in_sz);
|
||||
|
@ -739,8 +740,7 @@ test_frame_header_split (unsigned n_packets, unsigned extra_sz,
|
|||
const unsigned wsize = 70;
|
||||
const size_t buf_in_sz = wsize, buf_out_sz = 0x500000;
|
||||
|
||||
struct lsxpack_header header;
|
||||
lsxpack_header_set_ptr(&header, ":method", 7, "GET", 3);
|
||||
struct lsxpack_header header = { XHDR(":method", "GET") };
|
||||
struct lsquic_http_headers headers = { 1, &header, };
|
||||
|
||||
buf_in = malloc(buf_in_sz);
|
||||
|
@ -855,8 +855,7 @@ test_zero_size_frame (void)
|
|||
const unsigned wsize = 7000;
|
||||
const size_t buf_in_sz = wsize, buf_out_sz = 0x500000;
|
||||
|
||||
struct lsxpack_header header;
|
||||
lsxpack_header_set_ptr(&header, ":method", 7, "GET", 3);
|
||||
struct lsxpack_header header = { XHDR(":method", "GET") };
|
||||
struct lsquic_http_headers headers = { 1, &header, };
|
||||
|
||||
buf_in = malloc(buf_in_sz);
|
||||
|
|
|
@ -35,7 +35,7 @@ main (int argc, char **argv)
|
|||
else
|
||||
nelems = 1000000;
|
||||
|
||||
widgets = malloc(sizeof(widgets[0]) * nelems);
|
||||
widgets = calloc(nelems, sizeof(widgets[0]));
|
||||
|
||||
for (n = 0; n < nelems; ++n)
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <getopt.h>
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include "lsquic_malo.h"
|
||||
|
|
|
@ -46,6 +46,9 @@ test_min_heap (void)
|
|||
for (i = 0; i < MAX_ELEMS; ++i)
|
||||
lsquic_mh_insert(&heap, (void *) i, i);
|
||||
verify_min_heap(&heap);
|
||||
#ifdef _MSC_VER
|
||||
prev_val = 0;
|
||||
#endif
|
||||
for (i = 0; i < MAX_ELEMS; ++i)
|
||||
{
|
||||
p = lsquic_mh_pop(&heap);
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ main (void)
|
|||
.sin_port = htons(443),
|
||||
.sin_addr = peer_addr,
|
||||
};
|
||||
lsquic_cid_t cid = {};
|
||||
lsquic_cid_t cid; memset(&cid, 0, sizeof(cid));
|
||||
lsquic_qlog_create_connection(&cid, (const struct sockaddr *)&local,
|
||||
(const struct sockaddr *)&peer);
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include "vc_compat.h"
|
||||
#endif
|
||||
|
||||
#include "lsquic_types.h"
|
||||
#include "lsquic_int_types.h"
|
||||
#include "lsquic_rechist.h"
|
||||
|
|
|
@ -161,8 +161,8 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
|
|||
int s;
|
||||
memset(tobjs, 0, sizeof(*tobjs));
|
||||
LSCONN_INITIALIZE(&tobjs->lconn);
|
||||
tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID25);
|
||||
tobjs->lconn.cn_version = LSQVER_ID25;
|
||||
tobjs->lconn.cn_pf = select_pf_by_ver(LSQVER_ID27);
|
||||
tobjs->lconn.cn_version = LSQVER_ID27;
|
||||
tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_ietf_v1;
|
||||
network_path.np_pack_size = IQUIC_MAX_IPv4_PACKET_SZ;
|
||||
tobjs->lconn.cn_if = &our_conn_if;
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "vc_compat.h"
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_stock_shi.h"
|
||||
|
@ -85,7 +90,11 @@ test_shi (const struct order *order)
|
|||
assert(0 == s);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
sleep(2); /* Let the thing expire */
|
||||
#else
|
||||
Sleep(2000); /* Let the thing expire */
|
||||
#endif
|
||||
|
||||
for (i = 0; i < N_PAIRS; ++i)
|
||||
{
|
||||
|
|
|
@ -325,7 +325,7 @@ init_test_objs (struct test_objs *tobjs, unsigned initial_conn_window,
|
|||
LSCONN_INITIALIZE(&tobjs->lconn);
|
||||
tobjs->lconn.cn_pf = pf ? pf : g_pf;
|
||||
tobjs->lconn.cn_version = tobjs->lconn.cn_pf == &lsquic_parse_funcs_ietf_v1 ?
|
||||
LSQVER_ID25 : LSQVER_043;
|
||||
LSQVER_ID27 : LSQVER_043;
|
||||
tobjs->lconn.cn_esf_c = &lsquic_enc_session_common_gquic_1;
|
||||
network_path.np_pack_size = 1370;
|
||||
tobjs->lconn.cn_if = &our_conn_if;
|
||||
|
@ -2243,7 +2243,7 @@ test_changing_pack_size (void)
|
|||
enum lsquic_version versions_to_test[3] =
|
||||
{
|
||||
LSQVER_046,
|
||||
LSQVER_ID25,
|
||||
LSQVER_ID27,
|
||||
};
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
|
@ -3173,7 +3173,7 @@ main (int argc, char **argv)
|
|||
|
||||
/* Redo some tests using crypto streams and frames */
|
||||
g_use_crypto_ctor = 1;
|
||||
g_pf = select_pf_by_ver(LSQVER_ID25);
|
||||
g_pf = select_pf_by_ver(LSQVER_ID27);
|
||||
main_test_packetization();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -279,7 +279,7 @@ static const struct test tests[] = {
|
|||
*/
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.fin = { 0, 1, },
|
||||
.offset = 0x0807060504030201UL,
|
||||
.stream_id = 0x210,
|
||||
|
@ -299,7 +299,7 @@ static const struct test tests[] = {
|
|||
},
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.fin = { 0, 0, },
|
||||
.offset = 0,
|
||||
.stream_id = 0x210,
|
||||
|
@ -318,7 +318,7 @@ static const struct test tests[] = {
|
|||
},
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.fin = { 0, 0, },
|
||||
.offset = 0,
|
||||
.stream_id = 0x21,
|
||||
|
@ -336,7 +336,7 @@ static const struct test tests[] = {
|
|||
},
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.fin = { 0, 0, },
|
||||
.offset = 0x0807060504030201UL,
|
||||
.stream_id = 0x210,
|
||||
|
@ -356,7 +356,7 @@ static const struct test tests[] = {
|
|||
},
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.fin = { 1, 0, },
|
||||
.offset = 0x0807060504030201UL,
|
||||
.stream_id = 0x210,
|
||||
|
@ -374,7 +374,7 @@ static const struct test tests[] = {
|
|||
},
|
||||
|
||||
{ .lineno = __LINE__,
|
||||
.pf = select_pf_by_ver(LSQVER_ID25),
|
||||
.pf = select_pf_by_ver(LSQVER_ID27),
|
||||
.fin = { 1, 0, },
|
||||
.offset = 0x0807060504030201UL,
|
||||
.stream_id = 0x210,
|
||||
|
|
|
@ -243,7 +243,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Balls to the wall: every possible bit is set",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
|
||||
0x41, 0x23, /* Stream ID */
|
||||
|
@ -262,7 +262,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Balls to the wall #2: every possible bit is set except FIN",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 1<<1 | 0<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
@ -281,7 +281,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Data length is zero",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 0<<1 | 0<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
@ -299,7 +299,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Sanity check: what happens when data length is zero #1",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 1<<1 | 0<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
@ -318,7 +318,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Sanity check: what happens when data length is zero #2",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 1<<1 | 0<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
@ -337,7 +337,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Sanity check: what happens when data length is zero #3",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 0<<2 | 1<<1 | 0<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
@ -355,7 +355,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Sanity check: what happens when data length is zero #3",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
@ -374,7 +374,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Check data bounds #1",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
@ -393,7 +393,7 @@ static const struct test tests[] = {
|
|||
|
||||
{ "Check data bounds #2",
|
||||
__LINE__,
|
||||
select_pf_by_ver(LSQVER_ID25),
|
||||
select_pf_by_ver(LSQVER_ID27),
|
||||
/* TYPE OFF DLEN FIN */
|
||||
{ 0x10 | 1<<2 | 1<<1 | 1<<0,
|
||||
0x81, 0x23, 0x00, 0xE4, /* Stream ID */
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include "lsquic.h"
|
||||
#include "lsquic_types.h"
|
||||
|
@ -58,18 +62,20 @@ static const struct trapa_test tests[] =
|
|||
| (1 << TPI_INIT_MAX_DATA)
|
||||
| (1 << TPI_MAX_IDLE_TIMEOUT)
|
||||
| (1 << TPI_MAX_ACK_DELAY)
|
||||
| (1 << TPI_MAX_PACKET_SIZE)
|
||||
| (1 << TPI_MAX_UDP_PAYLOAD_SIZE)
|
||||
| (1 << TPI_ACK_DELAY_EXPONENT)
|
||||
| (1 << TPI_INITIAL_SOURCE_CID)
|
||||
| (1 << TPI_ACTIVE_CONNECTION_ID_LIMIT),
|
||||
.tp_init_max_stream_data_bidi_local = 0x12348877,
|
||||
.tp_init_max_data = 0xAABB,
|
||||
.tp_max_packet_size = 1213,
|
||||
.tp_max_udp_payload_size = 1213,
|
||||
.tp_max_idle_timeout = 10 * 1000,
|
||||
.tp_max_ack_delay = TP_DEF_MAX_ACK_DELAY,
|
||||
.tp_active_connection_id_limit = 7,
|
||||
.tp_initial_source_cid = { .len = 8, .u_cid.id = 0x0807060504030201ull, },
|
||||
},
|
||||
.is_server = 0,
|
||||
.enc_len = 26,
|
||||
.enc_len = 36,
|
||||
.encoded =
|
||||
/* Idle timeout */ "\x01\x02\x67\x10"
|
||||
/* Packet size */ "\x03\x02\x44\xBD"
|
||||
|
@ -77,6 +83,7 @@ static const struct trapa_test tests[] =
|
|||
/* Bidi local */ "\x05\x04\x92\x34\x88\x77"
|
||||
/* Ack delay exp */ "\x0A\x01\x00"
|
||||
/* Active CID limit */ "\x0E\x01\x07"
|
||||
/* Initial SCID */ "\x0F\x08\x01\x02\x03\x04\x05\x06\x07\x08"
|
||||
/* Trailer to make the end easily visible in gdb: */
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
},
|
||||
|
@ -104,7 +111,7 @@ static const struct trapa_test tests[] =
|
|||
TP_DEFAULT_VALUES,
|
||||
.tp_init_max_data = 0x123456,
|
||||
.tp_init_max_stream_data_bidi_local = 0xABCDEF88,
|
||||
.tp_max_packet_size = 0x555,
|
||||
.tp_max_udp_payload_size = 0x555,
|
||||
},
|
||||
.is_server = 1,
|
||||
.addl_set = 1 << TPI_DISABLE_ACTIVE_MIGRATION,
|
||||
|
@ -125,7 +132,7 @@ static const struct trapa_test tests[] =
|
|||
.params = {
|
||||
TP_DEFAULT_VALUES,
|
||||
.tp_max_ack_delay = 25,
|
||||
.tp_max_packet_size = 0x555,
|
||||
.tp_max_udp_payload_size = 0x555,
|
||||
.tp_preferred_address = {
|
||||
.ipv4_addr = "\x01\x02\x03\x04",
|
||||
.ipv4_port = 0x1234,
|
||||
|
@ -172,8 +179,8 @@ params_are_equal (const struct transport_params *a,
|
|||
&& a->tp_preferred_address.ipv4_port == b->tp_preferred_address.ipv4_port
|
||||
&& a->tp_preferred_address.ipv6_port == b->tp_preferred_address.ipv6_port
|
||||
&& a->tp_preferred_address.cid.len == b->tp_preferred_address.cid.len
|
||||
&& MCMP(tp_original_cid.idbuf)
|
||||
&& a->tp_original_cid.len == b->tp_original_cid.len
|
||||
&& MCMP(tp_original_dest_cid.idbuf)
|
||||
&& a->tp_original_dest_cid.len == b->tp_original_dest_cid.len
|
||||
;
|
||||
#undef MCMP
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE.
|
||||
- only debug and release are expected in the Cmakelists.txt. If you need a different config, please follow the model in that file to add it.
|
||||
|
||||
- vcpkg does not have boringssl, so you'll have to build it yourself. Follow the instructions at the boringssl repository.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/* Getopt for GNU.
|
||||
NOTE: getopt is now part of the C library, so if you don't know what
|
||||
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/* Declarations for getopt.
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
|
||||
Free Software Foundation, Inc.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <winsock2.h>
|
||||
|
@ -7,7 +8,9 @@ struct iovec {
|
|||
size_t iov_len; /* Number of bytes to transfer */
|
||||
};
|
||||
#define strcasecmp(a,b) _strcmpi(a,b)
|
||||
#define strncasecmp _strnicmp
|
||||
#define strdup _strdup
|
||||
#define PATH_MAX MAX_PATH
|
||||
|
||||
#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)
|
||||
|
||||
|
|
Loading…
Reference in New Issue