Fix Windows support

This commit is contained in:
Dmitri Tikhonov 2020-06-03 00:13:30 -04:00
parent 41d574f34c
commit fb3e20e0bc
72 changed files with 912 additions and 475 deletions

View file

@ -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})

View file

@ -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,

63
appveyor.yml Normal file
View file

@ -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

View file

@ -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)

View file

@ -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))
{

View file

@ -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"

View file

@ -531,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,
@ -1072,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
@ -1157,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];
@ -1215,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)
@ -1426,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);

View file

@ -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;

View file

@ -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>

View file

@ -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;
}
@ -215,8 +226,10 @@ prog_print_common_options (const struct prog *prog, FILE *out)
int
prog_set_opt (struct prog *prog, int opt, const char *arg)
{
#ifndef WIN32
struct stat st;
int s;
#endif
switch (opt)
{

View file

@ -54,7 +54,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);

View file

@ -30,8 +30,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>
@ -39,6 +44,7 @@
#include "test_common.h"
#include "lsquic.h"
#include "prog.h"
#include "lsxpack_header.h"
#include "../src/liblsquic/lsquic_logger.h"
@ -49,16 +55,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
@ -177,9 +173,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;
@ -520,7 +517,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
@ -799,7 +798,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];
@ -816,6 +819,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;
@ -829,6 +835,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;
@ -843,20 +850,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;
@ -865,12 +885,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;
@ -932,7 +952,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)
{
@ -948,9 +968,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;
@ -962,7 +982,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)
{
@ -975,7 +995,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)
{
@ -1121,7 +1141,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));
@ -1141,10 +1161,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;
@ -1527,6 +1548,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 */
@ -1589,12 +1611,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)
@ -1748,13 +1772,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;
@ -2207,3 +2231,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;
}

View file

@ -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;
@ -125,4 +143,15 @@ destroy_lsquic_reader_ctx (struct reader_ctx *ctx);
#define LITESPEED_ID "lsquic" "/" TOSTRING(LSQUIC_MAJOR_VERSION) "." \
TOSTRING(LSQUIC_MINOR_VERSION) "." TOSTRING(LSQUIC_PATCH_VERSION)
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

View file

@ -1527,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)

View file

@ -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
--------

View file

@ -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;
};

View file

@ -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

View file

@ -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)

View file

@ -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);
}

View file

@ -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)

View file

@ -1545,6 +1545,8 @@ get_peer_transport_params (struct enc_sess_iquic *enc_sess)
}
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)

View file

@ -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;
@ -230,7 +243,7 @@ struct lsquic_engine
* 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
@ -639,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,
@ -652,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)
{
@ -1439,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
@ -2037,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)
@ -2136,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
@ -2699,12 +2714,11 @@ 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;
}
}
@ -2714,6 +2728,11 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
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);

View file

@ -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);
}

View file

@ -7740,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];

View file

@ -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

View file

@ -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

View file

@ -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));

View file

@ -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);
}

View file

@ -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;

View file

@ -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];

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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"

View file

@ -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];

View file

@ -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)

View file

@ -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>

View file

@ -11,8 +11,13 @@
#include <stdint.h>
#include <string.h>
#ifndef WIN32
#include <arpa/inet.h>
#include <sys/socket.h>
#else
#include "vc_compat.h"
#include "Ws2tcpip.h"
#endif
#include "lsquic_byteswap.h"
#include "lsquic_int_types.h"

View file

@ -141,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.
@ -157,10 +157,10 @@ 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 *buf, size_t bufsz);
unsigned char *const buf, size_t bufsz);
int
lsquic_tp_decode_27 (const unsigned char *buf, size_t bufsz,
lsquic_tp_decode_27 (const unsigned char *const buf, size_t bufsz,
int is_server,
struct transport_params *);

View file

@ -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>

View file

@ -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] =
{

View file

@ -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)

View file

@ -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"

View file

@ -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"

View file

@ -5,6 +5,8 @@
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#else
#include "vc_compat.h"
#endif
#include "lsquic_types.h"

View file

@ -5,6 +5,8 @@
#include <string.h>
#ifndef WIN32
#include <sys/time.h>
#else
#include "vc_compat.h"
#endif
#include "lsquic_types.h"

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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,

View file

@ -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

View file

@ -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;

View file

@ -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] =

View file

@ -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]),

View file

@ -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);

View file

@ -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)
{

View file

@ -6,7 +6,7 @@
#ifndef WIN32
#include <unistd.h>
#else
#include <getopt.h>
#include "getopt.h"
#endif
#include "lsquic_malo.h"

View file

@ -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);

View file

@ -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>

View file

@ -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);

View file

@ -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"

View file

@ -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)
{

View file

@ -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"

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -1,3 +1,4 @@
/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */
/*-
* SPDX-License-Identifier: BSD-3-Clause
*

View file

@ -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)