mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.29.3
- [BUGFIX] Do not send RESET_STREAM if writing to stream is already finished. - perf_client: wait for all ACKs before exiting. - Improve how generated RESET_STREAM is logged. - Fix compilation in different combos of adv_tick/conn_stats flags. - Move qpack warning disablement into src/liblsquic/CMakeLists.txt.
This commit is contained in:
parent
f1d5a1a4de
commit
99a1ad0f24
20 changed files with 209 additions and 302 deletions
|
@ -1,3 +1,12 @@
|
|||
2021-03-03
|
||||
- 2.29.3
|
||||
- [BUGFIX] Do not send RESET_STREAM if writing to stream is already
|
||||
finished.
|
||||
- perf_client: wait for all ACKs before exiting.
|
||||
- Improve how generated RESET_STREAM is logged.
|
||||
- Fix compilation in different combos of adv_tick/conn_stats flags.
|
||||
- Move qpack warning disablement into src/liblsquic/CMakeLists.txt.
|
||||
|
||||
2021-02-23
|
||||
- 2.29.2
|
||||
- Fix regression in gQUIC server: bug #234.
|
||||
|
|
|
@ -45,11 +45,6 @@ IF (NOT MSVC)
|
|||
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Wall -Wextra -Wno-unused-parameter")
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -fno-omit-frame-pointer")
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
CHECK_C_COMPILER_FLAG(-Wno-implicit-fallthrough HAS_NO_IMPLICIT_FALLTHROUGH)
|
||||
IF (HAS_NO_IMPLICIT_FALLTHROUGH)
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Wno-implicit-fallthrough")
|
||||
ENDIF()
|
||||
|
||||
IF(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.3)
|
||||
SET(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Wno-missing-field-initializers")
|
||||
|
|
|
@ -785,7 +785,7 @@ http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
|
|||
if (client_ctx->hcc_reset_after_nbytes &&
|
||||
s_stat_downloaded_bytes > client_ctx->hcc_reset_after_nbytes)
|
||||
{
|
||||
lsquic_stream_reset(stream, 0x1);
|
||||
lsquic_stream_maybe_reset(stream, 0x1, 1);
|
||||
break;
|
||||
}
|
||||
/* test retire_cid after some number of read bytes */
|
||||
|
|
|
@ -273,7 +273,9 @@ client_file_on_write_buf (lsquic_stream_ctx_t *st_h)
|
|||
if (g_reset_stream.stream_id == lsquic_stream_id(st_h->stream) &&
|
||||
lseek(st_h->file->fd, 0, SEEK_CUR) >= g_reset_stream.offset)
|
||||
{
|
||||
lsquic_stream_reset(st_h->stream, 0x01 /* QUIC_INTERNAL_ERROR */);
|
||||
/* Note: this is an internal function */
|
||||
lsquic_stream_maybe_reset(st_h->stream,
|
||||
0x01 /* QUIC_INTERNAL_ERROR */, 1);
|
||||
g_reset_stream.stream_id = 0; /* Reset only once */
|
||||
}
|
||||
|
||||
|
|
|
@ -335,6 +335,7 @@ main (int argc, char **argv)
|
|||
TAILQ_INIT(&sports);
|
||||
prog_init(&s_prog, 0, &sports, &perf_stream_if, NULL);
|
||||
s_prog.prog_api.ea_alpn = "perf";
|
||||
s_prog.prog_settings.es_delay_onclose = 1;
|
||||
|
||||
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "hp:T:")))
|
||||
{
|
||||
|
|
|
@ -26,7 +26,7 @@ author = u'LiteSpeed Technologies'
|
|||
# The short X.Y version
|
||||
version = u'2.29'
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u'2.29.2'
|
||||
release = u'2.29.3'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
|
37
docs/devel.rst
Normal file
37
docs/devel.rst
Normal file
|
@ -0,0 +1,37 @@
|
|||
Developing lsquic
|
||||
=================
|
||||
|
||||
Generating Tags
|
||||
---------------
|
||||
|
||||
Over the years, we have developed a wrapper around `Universal Ctags`_
|
||||
to generate convenient tags so that, for example, ``ci_packet_in`` will
|
||||
be able to take you to any of its implementations such as
|
||||
``full_conn_ci_packet_in()``, ``evanescent_conn_ci_packet_in()``, and
|
||||
others.
|
||||
|
||||
_Exuberant_ Ctags will work, too, but the more recent and maintained fork
|
||||
of it, the _Universal_ Ctags, is preferred. (If you are on Ubuntu, you
|
||||
should clone Universal Ctags from GitHub and compiled it yourself. The
|
||||
version that comes in the Ubuntu package -- at the time of this writing
|
||||
-- is so slow as to be considered broken).
|
||||
|
||||
The wrapper is ``tools/gen-tags.pl``. Run it in the source directory:
|
||||
|
||||
.. highlight:: bash
|
||||
|
||||
::
|
||||
|
||||
sh$ cd lsquic
|
||||
sh$ ./tools/gen-tags.pl
|
||||
|
||||
Maintaining Documentation
|
||||
-------------------------
|
||||
|
||||
Documentation -- the ``*.rst`` files under ``docs/`` should be kept up-to-date
|
||||
with changes in the API in ``include/lsquic.h``.
|
||||
|
||||
For convenience, tags for the documentation files can be generated by passing
|
||||
the ``--docs`` argument to ``tools/gen-tags.pl``.
|
||||
|
||||
.. _`Universal Ctags`: https://ctags.io/
|
|
@ -66,6 +66,7 @@ Contents
|
|||
tutorial
|
||||
apiref
|
||||
internals
|
||||
devel
|
||||
faq
|
||||
|
||||
Indices and tables
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
|
||||
#define LSQUIC_MAJOR_VERSION 2
|
||||
#define LSQUIC_MINOR_VERSION 29
|
||||
#define LSQUIC_PATCH_VERSION 2
|
||||
#define LSQUIC_PATCH_VERSION 3
|
||||
|
||||
/**
|
||||
* Engine flags:
|
||||
|
|
|
@ -85,7 +85,13 @@ SET(lsquic_STAT_SRCS
|
|||
)
|
||||
|
||||
IF(NOT MSVC)
|
||||
set_source_files_properties(ls-qpack/lsqpack.c PROPERTIES COMPILE_FLAGS -Wno-uninitialized)
|
||||
SET(QPACK_FLAGS "-Wno-uninitialized")
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
CHECK_C_COMPILER_FLAG(-Wno-implicit-fallthrough HAS_NO_IMPLICIT_FALLTHROUGH)
|
||||
IF (HAS_NO_IMPLICIT_FALLTHROUGH)
|
||||
SET(QPACK_FLAGS "${QPACK_FLAGS} -Wno-implicit-fallthrough")
|
||||
ENDIF()
|
||||
set_source_files_properties(ls-qpack/lsqpack.c PROPERTIES COMPILE_FLAGS ${QPACK_FLAGS})
|
||||
ENDIF()
|
||||
|
||||
include_directories(ls-qpack)
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
#define LSQUIC_DEBUG_NEXT_ADV_TICK 1
|
||||
#endif
|
||||
|
||||
#if LSQUIC_DEBUG_NEXT_ADV_TICK
|
||||
#if LSQUIC_DEBUG_NEXT_ADV_TICK || LSQUIC_CONN_STATS
|
||||
#include "lsquic_alarmset.h"
|
||||
#endif
|
||||
|
||||
|
@ -3161,6 +3161,8 @@ lsquic_engine_earliest_adv_tick (lsquic_engine_t *engine, int *diff)
|
|||
lsquic_time_t now, next_time;
|
||||
#if LSQUIC_DEBUG_NEXT_ADV_TICK || LSQUIC_CONN_STATS
|
||||
struct lsquic_conn *conn;
|
||||
#endif
|
||||
#if LSQUIC_DEBUG_NEXT_ADV_TICK
|
||||
const enum lsq_log_level L = LSQ_LOG_DEBUG; /* Easy toggle */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3807,7 +3807,7 @@ full_conn_ci_close (struct lsquic_conn *lconn)
|
|||
{
|
||||
stream = lsquic_hashelem_getdata(el);
|
||||
if (!lsquic_stream_is_critical(stream))
|
||||
lsquic_stream_reset(stream, 0);
|
||||
lsquic_stream_maybe_reset(stream, 0, 1);
|
||||
}
|
||||
conn->fc_flags |= FC_CLOSING;
|
||||
if (!(conn->fc_flags & FC_GOAWAY_SENT))
|
||||
|
@ -3933,7 +3933,7 @@ headers_stream_on_stream_error (void *ctx, lsquic_stream_id_t stream_id)
|
|||
* errors. There does not seem to be a good reason to figure out
|
||||
* and send more specific error codes.
|
||||
*/
|
||||
lsquic_stream_reset_ext(stream, 1, 0);
|
||||
lsquic_stream_maybe_reset(stream, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2581,8 +2581,11 @@ generate_rst_stream_frame (struct ietf_full_conn *conn,
|
|||
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, sz);
|
||||
packet_out->po_frame_types |= 1 << QUIC_FRAME_RST_STREAM;
|
||||
lsquic_stream_rst_frame_sent(stream);
|
||||
LSQ_DEBUG("wrote RST: stream %"PRIu64"; offset 0x%"PRIX64"; error code "
|
||||
LSQ_DEBUG("wrote RST: stream %"PRIu64"; offset %"PRIu64"; error code "
|
||||
"%"PRIu64, stream->id, stream->tosend_off, stream->error_code);
|
||||
EV_LOG_CONN_EVENT(LSQUIC_LOG_CONN_ID, "generated RESET_STREAM: stream "
|
||||
"%"PRIu64"; offset %"PRIu64"; error code %"PRIu64, stream->id,
|
||||
stream->tosend_off, stream->error_code);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -2919,7 +2922,7 @@ ietf_full_conn_ci_close (struct lsquic_conn *lconn)
|
|||
stream = lsquic_hashelem_getdata(el);
|
||||
sd = (stream->id >> SD_SHIFT) & 1;
|
||||
if (SD_BIDI == sd)
|
||||
lsquic_stream_reset(stream, 0);
|
||||
lsquic_stream_maybe_reset(stream, 0, 1);
|
||||
}
|
||||
conn->ifc_flags |= IFC_CLOSING;
|
||||
conn->ifc_send_flags |= SF_SEND_CONN_CLOSE;
|
||||
|
|
|
@ -144,6 +144,9 @@ stream_readable_http_ietf (struct lsquic_stream *stream);
|
|||
static ssize_t
|
||||
stream_write_buf (struct lsquic_stream *stream, const void *buf, size_t sz);
|
||||
|
||||
static void
|
||||
stream_reset (struct lsquic_stream *, uint64_t error_code, int do_close);
|
||||
|
||||
static size_t
|
||||
active_hq_frame_sizes (const struct lsquic_stream *);
|
||||
|
||||
|
@ -1284,7 +1287,7 @@ lsquic_stream_rst_in (lsquic_stream_t *stream, uint64_t offset,
|
|||
(STREAM_RST_SENT|STREAM_SS_SENT|STREAM_FIN_SENT))
|
||||
&& !(stream->sm_bflags & SMBF_IETF)
|
||||
&& !(stream->sm_qflags & SMQF_SEND_RST))
|
||||
lsquic_stream_reset_ext(stream, 7 /* QUIC_RST_ACKNOWLEDGEMENT */, 0);
|
||||
stream_reset(stream, 7 /* QUIC_RST_ACKNOWLEDGEMENT */, 0);
|
||||
|
||||
stream->stream_flags |= STREAM_RST_RECVD;
|
||||
|
||||
|
@ -1324,7 +1327,7 @@ lsquic_stream_stop_sending_in (struct lsquic_stream *stream,
|
|||
|
||||
if (!(stream->stream_flags & (STREAM_RST_SENT|STREAM_FIN_SENT))
|
||||
&& !(stream->sm_qflags & SMQF_SEND_RST))
|
||||
lsquic_stream_reset_ext(stream, 0, 0);
|
||||
stream_reset(stream, 0, 0);
|
||||
|
||||
maybe_finish_stream(stream);
|
||||
maybe_schedule_call_on_close(stream);
|
||||
|
@ -1767,7 +1770,7 @@ handle_early_read_shutdown_gquic (struct lsquic_stream *stream)
|
|||
{
|
||||
if (!(stream->stream_flags & STREAM_RST_SENT))
|
||||
{
|
||||
lsquic_stream_reset_ext(stream, 7 /* QUIC_STREAM_CANCELLED */, 0);
|
||||
stream_reset(stream, 7 /* QUIC_STREAM_CANCELLED */, 0);
|
||||
stream->sm_qflags |= SMQF_WAIT_FIN_OFF;
|
||||
}
|
||||
}
|
||||
|
@ -1848,7 +1851,7 @@ stream_shutdown_write (lsquic_stream_t *stream)
|
|||
&& !(stream->stream_flags & STREAM_HEADERS_SENT))
|
||||
{
|
||||
LSQ_DEBUG("headers not sent, send a reset");
|
||||
lsquic_stream_reset(stream, 0);
|
||||
stream_reset(stream, 0, 1);
|
||||
}
|
||||
else if (stream->sm_n_buffered == 0)
|
||||
{
|
||||
|
@ -4244,15 +4247,22 @@ lsquic_stream_set_max_send_off (lsquic_stream_t *stream, uint64_t offset)
|
|||
|
||||
|
||||
void
|
||||
lsquic_stream_reset (lsquic_stream_t *stream, uint64_t error_code)
|
||||
lsquic_stream_maybe_reset (struct lsquic_stream *stream, uint64_t error_code,
|
||||
int do_close)
|
||||
{
|
||||
lsquic_stream_reset_ext(stream, error_code, 1);
|
||||
if (!((stream->stream_flags
|
||||
& (STREAM_RST_SENT|STREAM_FIN_SENT|STREAM_U_WRITE_DONE))
|
||||
|| (stream->sm_qflags & SMQF_SEND_RST)))
|
||||
{
|
||||
stream_reset(stream, error_code, do_close);
|
||||
}
|
||||
else if (do_close)
|
||||
stream_shutdown_read(stream);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsquic_stream_reset_ext (lsquic_stream_t *stream, uint64_t error_code,
|
||||
int do_close)
|
||||
static void
|
||||
stream_reset (struct lsquic_stream *stream, uint64_t error_code, int do_close)
|
||||
{
|
||||
if ((stream->stream_flags & STREAM_RST_SENT)
|
||||
|| (stream->sm_qflags & SMQF_SEND_RST))
|
||||
|
@ -4599,7 +4609,7 @@ lsquic_stream_refuse_push (lsquic_stream_t *stream)
|
|||
&& !(stream->stream_flags & STREAM_RST_SENT))
|
||||
{
|
||||
LSQ_DEBUG("refusing pushed stream: send reset");
|
||||
lsquic_stream_reset_ext(stream, 8 /* QUIC_REFUSED_STREAM */, 1);
|
||||
stream_reset(stream, 8 /* QUIC_REFUSED_STREAM */, 1);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -510,10 +510,7 @@ void
|
|||
lsquic_stream_stream_frame_sent (lsquic_stream_t *);
|
||||
|
||||
void
|
||||
lsquic_stream_reset (lsquic_stream_t *, uint64_t error_code);
|
||||
|
||||
void
|
||||
lsquic_stream_reset_ext (lsquic_stream_t *, uint64_t error_code, int close);
|
||||
lsquic_stream_maybe_reset (struct lsquic_stream *, uint64_t error_code, int);
|
||||
|
||||
void
|
||||
lsquic_stream_call_on_close (lsquic_stream_t *);
|
||||
|
|
|
@ -1242,7 +1242,7 @@ test_loc_RST_rem_FIN (struct test_objs *tobjs)
|
|||
sss = lsquic_stream_sending_state(stream);
|
||||
assert(SSS_SEND == sss);
|
||||
|
||||
lsquic_stream_reset(stream, 0);
|
||||
lsquic_stream_maybe_reset(stream, 0, 1);
|
||||
++stream->n_unacked; /* Fake sending of packet with RST_STREAM */
|
||||
assert(!TAILQ_EMPTY(&tobjs->conn_pub.sending_streams));
|
||||
assert((stream->sm_qflags & SMQF_SENDING_FLAGS) == SMQF_SEND_RST);
|
||||
|
@ -1535,7 +1535,7 @@ test_unlimited_stream_flush_data (struct test_objs *tobjs)
|
|||
lsquic_stream_flush(stream);
|
||||
assert(0x4000 == lsquic_conn_cap_avail(cap));
|
||||
|
||||
lsquic_stream_reset(stream, 0xF00DF00D);
|
||||
lsquic_stream_maybe_reset(stream, 0xF00DF00D, 1);
|
||||
assert(0x4000 == lsquic_conn_cap_avail(cap)); /* Still unchanged */
|
||||
|
||||
lsquic_stream_destroy(stream);
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Benchmark QUIC using LSQUIC http_client and other HTTP Benchmark tools.
|
||||
|
||||
# Variables
|
||||
CLIENT_TYPE=''
|
||||
CLIENT_PATH='http_client'
|
||||
CLIENTS='1'
|
||||
TRIALS='1'
|
||||
HOST='www.example.com'
|
||||
IP='192.168.0.1'
|
||||
IP_PORT='192.168.0.1:8000'
|
||||
REQ_PATH='/'
|
||||
QUIC_VERSION='Q043'
|
||||
CLIENT_OPTIONS='none'
|
||||
IGNORE_OUT=''
|
||||
REQUESTS='1'
|
||||
CONNS='1'
|
||||
MAXREQS='1'
|
||||
|
||||
function usage() {
|
||||
cat <<EOF
|
||||
|
||||
Usage: lsqb-master.sh [-hTtCHSPpqlKrcmw]
|
||||
|
||||
Benchmark QUIC using LSQUIC http_client and other HTTP Benchmark tools.
|
||||
|
||||
Arguments:
|
||||
-h, --help Show this help message and exit
|
||||
-T, --trials Number of trials. (Default: 1)
|
||||
-t, --client_type Type of client.
|
||||
Supported QUIC options: http_client.
|
||||
Supported HTTP options: curl, curl-caddy, ab, h2load.
|
||||
(Default: http_client)
|
||||
-a, --client_path Path to http_client. (Default: http_client)
|
||||
-C, --clients Number of concurrent clients. (Default: 1)
|
||||
-H --host Name of server. (Default: www.example.com)
|
||||
-S, --ip_port IP:PORT of domain. (Default: 192.168.0.1:8000)
|
||||
-P, --ip IP of domain for curl-caddy. (Default: 192.168.0.1)
|
||||
-p, --path Path of file. (Default: /)
|
||||
-q, --quic_version QUIC version. (Default: Q043)
|
||||
-l, --options Options for http_client. (Default: none)
|
||||
-K, --ignore_out Ignore output for http_client. (Default: off)
|
||||
-r, --requests Number of requests. (Default: 1)
|
||||
-c, --conns Number of concurrent connections. (Default: 1)
|
||||
-m, --maxreqs Maximum number of requests per connection. (Default: 1)
|
||||
-w, --concur Maximum number of concurrent streams
|
||||
within a single connection. (Default: 1)
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
function check_input() {
|
||||
while [[ "$1" != '' ]]; do
|
||||
case $1 in
|
||||
-T | --trials ) shift
|
||||
TRIALS="$1"
|
||||
;;
|
||||
-t | --client_type) shift
|
||||
CLIENT_TYPE="$1"
|
||||
;;
|
||||
-a | --client_path) shift
|
||||
CLIENT_PATH="$1"
|
||||
;;
|
||||
-C | --clients ) shift
|
||||
CLIENTS="$1"
|
||||
;;
|
||||
-H | --host ) shift
|
||||
HOST="$1"
|
||||
;;
|
||||
-S | --ip_port ) shift
|
||||
IP_PORT="$1"
|
||||
;;
|
||||
-P | --ip ) shift
|
||||
IP="$1"
|
||||
;;
|
||||
-p | --path ) shift
|
||||
PATH_STRING="$1"
|
||||
REQ_PATH="${PATH_STRING//,/ }"
|
||||
;;
|
||||
-q | --quic_version ) shift
|
||||
QUIC_VERSION="$1"
|
||||
;;
|
||||
-l | --options ) shift
|
||||
CLIENT_OPTIONS="$1"
|
||||
;;
|
||||
-K | --ignore_out)
|
||||
IGNORE_OUT="-K"
|
||||
;;
|
||||
-r | --requests ) shift
|
||||
REQUESTS="$1"
|
||||
;;
|
||||
-c | --conns ) shift
|
||||
CONNS="$1"
|
||||
;;
|
||||
-m | --maxreqs ) shift
|
||||
MAXREQS="$1"
|
||||
;;
|
||||
-w | --concur ) shift
|
||||
CONCUR="$1"
|
||||
;;
|
||||
* ) usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
function run_curl() {
|
||||
for (( i = 0; i < ${REQUESTS}; i++ )); do
|
||||
curl --header 'Host:$HOST' \
|
||||
-k https://${IP_PORT}/${REQ_PATH} \
|
||||
--output /dev/null --silent
|
||||
done
|
||||
}
|
||||
|
||||
function run_curl_caddy() {
|
||||
for (( i = 0; i < ${REQUESTS}; i++ )); do
|
||||
curl --resolve ${HOST}:443:${IP} \
|
||||
-k https://${HOST}/${REQ_PATH} --output \
|
||||
/dev/null --silent
|
||||
done
|
||||
}
|
||||
|
||||
function run_ab() {
|
||||
ab -n ${REQUESTS} -c ${CONNS} -k -X ${IP_PORT} \
|
||||
https://${HOST}/${REQ_PATH} &> /dev/null
|
||||
}
|
||||
|
||||
function run_h2load() {
|
||||
h2load -n ${REQUESTS} -c ${CONNS} -m ${CONNS} \
|
||||
https://${IP_PORT}/${REQ_PATH} > /dev/null
|
||||
}
|
||||
|
||||
function run_client() {
|
||||
if [[ "${CLIENT_OPTIONS}" == 'none' ]]; then
|
||||
CLIENT_OPTIONS=''
|
||||
fi
|
||||
${CLIENT_PATH} ${IGNORE_OUT} \
|
||||
-H ${HOST} -s ${IP_PORT} \
|
||||
-p ${REQ_PATH} \
|
||||
-S rcvbuf=$[2000 * 2048] \
|
||||
-o support_tcid0=0 \
|
||||
-o version=${QUIC_VERSION} \
|
||||
${CLIENT_OPTIONS} \
|
||||
-n ${CONNS} -r ${REQUESTS} -R ${MAXREQS} -w ${CONCUR}
|
||||
}
|
||||
|
||||
function run_trials() {
|
||||
printf '\n'
|
||||
for (( i = 0; i < ${TRIALS}; i++ )); do
|
||||
START_TIME=$(date +%s.%3N)
|
||||
if [[ "${CLIENT_TYPE}" == 'curl' ]]; then
|
||||
for (( j = 0; j < ${CLIENTS}; j++ )); do
|
||||
run_curl &
|
||||
done
|
||||
elif [[ "${CLIENT_TYPE}" == 'curl-caddy' ]]; then
|
||||
for (( j = 0; j < ${CLIENTS}; j++ )); do
|
||||
run_curl_caddy &
|
||||
done
|
||||
elif [[ "${CLIENT_TYPE}" == 'ab' ]]; then
|
||||
for (( j = 0; j < ${CLIENTS}; j++ )); do
|
||||
run_ab &
|
||||
done
|
||||
elif [[ "${CLIENT_TYPE}" == 'h2load' ]]; then
|
||||
for (( j = 0; j < ${CLIENTS}; j++ )); do
|
||||
run_h2load &
|
||||
done
|
||||
else
|
||||
for (( j = 0; j < ${CLIENTS}; j++ )); do
|
||||
run_client &
|
||||
done
|
||||
fi
|
||||
wait
|
||||
END_TIME=$(date +%s.%3N)
|
||||
ELAPSED_TIME=$(awk "BEGIN {print ${END_TIME}-${START_TIME}}")
|
||||
printf ' %s, ' "${ELAPSED_TIME}"
|
||||
done
|
||||
printf '\n\n'
|
||||
}
|
||||
|
||||
function main() {
|
||||
check_input "$@"
|
||||
run_trials
|
||||
}
|
||||
|
||||
main "$@"
|
48
tools/gen-rst-tags.pl
Normal file
48
tools/gen-rst-tags.pl
Normal file
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# Parse .rst files and generate tags.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $id = '[a-zA-Z_0-9]';
|
||||
my @tags;
|
||||
for my $file (@ARGV) {
|
||||
open my $fh, '<', $file
|
||||
or die "Cannot open $file for reading: $!";
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
if (m/^(\.\. function:: )(.+)/) {
|
||||
my ($pfx, $val) = ($1, $2);
|
||||
if ($val =~ m/($id+) \(/o) {
|
||||
push @tags, "$1\t$file\t/^$pfx$val/\n";
|
||||
} else {
|
||||
warn "unknown pattern in $file:$.: $_\n";
|
||||
}
|
||||
} elsif (m/^(\s*\.\. (?:type|member):: )(.+)/) {
|
||||
my ($pfx, $val) = ($1, $2);
|
||||
if ($val =~ m/\(\*([^\)]+)\)/) {
|
||||
push @tags, "$1\t$file\t/^$pfx$val/\n";
|
||||
} elsif ($val =~ m/($id+)(?::\d+)?\s*$/o) {
|
||||
push @tags, "$1\t$file\t/^$pfx$val/\n";
|
||||
} else {
|
||||
warn "unknown pattern in $file:$.: $_\n";
|
||||
}
|
||||
} elsif (m/^(\s*\.\. var:: )(.+)/) {
|
||||
my ($pfx, $val) = ($1, $2);
|
||||
if ($val =~ m/($id+)(?:\[[^\]]*\])?\s*$/o) {
|
||||
push @tags, "$1\t$file\t/^$pfx$val/\n";
|
||||
} else {
|
||||
warn "unknown pattern in $file:$.: $_\n";
|
||||
}
|
||||
} elsif (m/^(\s*\.\. macro::\s+)(\S+)\s*$/) {
|
||||
push @tags, "$2\t$file\t/^$1$2/\n";
|
||||
} elsif (m/^\s*\.\. (?:toctree|image|highlight|code-block)::/) {
|
||||
# Skip
|
||||
} elsif (m/^\s*\.\.\s*\S+::/) {
|
||||
warn "unknown pattern in $file:$.: $_\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print sort @tags;
|
67
tools/gen-tags.pl
Executable file
67
tools/gen-tags.pl
Executable file
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env perl
|
||||
#
|
||||
# Generate tags for lsquic project
|
||||
#
|
||||
# If your `ctags' is not Universal Ctags, set UCTAGS environment variable to
|
||||
# point to it.
|
||||
|
||||
use warnings;
|
||||
|
||||
use Getopt::Long;
|
||||
|
||||
GetOptions("docs!" => \my $do_docs);
|
||||
|
||||
$tmpfile = '.tags.' . $$ . rand;
|
||||
$ctags = $ENV{UCTAGS} || 'ctags';
|
||||
$queue_h = '/usr/include/sys/queue.h';
|
||||
|
||||
@dirs = qw(include bin tests src/lshpack src/liblsquic);
|
||||
|
||||
system($ctags, '-f', $tmpfile,
|
||||
('--kinds-c=+p') x !!$do_docs, # Index function prototypes
|
||||
qw(-R -I SLIST_ENTRY+=void -I LIST_ENTRY+=void
|
||||
-I STAILQ_ENTRY+=void -I TAILQ_ENTRY+=void -I CIRCLEQ_ENTRY+=void
|
||||
-I TAILQ_ENTRY+=void -I SLIST_HEAD+=void -I LIST_HEAD+=void
|
||||
-I STAILQ_HEAD+=void -I TAILQ_HEAD+=void -I CIRCLEQ_HEAD+=void
|
||||
-I TAILQ_HEAD+=void), @dirs)
|
||||
and die "ctags failed";
|
||||
|
||||
-f $queue_h
|
||||
and system($ctags, '-f', $tmpfile, '-a', $queue_h)
|
||||
and die "ctags $queue_h failed";
|
||||
|
||||
if ($do_docs) {
|
||||
@rst = glob("docs/*.rst");
|
||||
if (@rst) {
|
||||
system("$^X tools/gen-rst-tags.pl @rst >> $tmpfile")
|
||||
and die "cannot run tools/gen-rst-tags.pl";
|
||||
}
|
||||
}
|
||||
|
||||
END { unlink $tmpfile }
|
||||
|
||||
open TMPFILE, "<", $tmpfile
|
||||
or die "cannot open $tmpfile for reading: $!";
|
||||
while (<TMPFILE>)
|
||||
{
|
||||
push @lines, $_;
|
||||
if (
|
||||
s/^(mini|full|ietf_full|ietf_mini|evanescent)_conn_ci_/ci_/
|
||||
or s/^(nocopy|hash|error)_di_/di_/
|
||||
or s/^(gquic)_(be|Q046|Q050)_/pf_/
|
||||
or s/^ietf_v[0-9][0-9]*_/pf_/
|
||||
or s/^stock_shi_/shi_/
|
||||
or s/^iquic_esf_/esf_/
|
||||
or s/^gquic[0-9]?_esf_/esf_/
|
||||
or s/^iquic_esfi_/esfi_/
|
||||
or s/^(lsquic_cubic|lsquic_bbr)_/cci_/
|
||||
)
|
||||
{
|
||||
push @lines, $_;
|
||||
}
|
||||
}
|
||||
open TMPFILE, ">", $tmpfile
|
||||
or die "cannot open $tmpfile for writing: $!";
|
||||
print TMPFILE sort @lines;
|
||||
close TMPFILE;
|
||||
rename $tmpfile, 'tags';
|
|
@ -1,83 +0,0 @@
|
|||
import time
|
||||
import json
|
||||
import re
|
||||
import argparse
|
||||
|
||||
_ev_time = 0
|
||||
_ev_cate = 1
|
||||
_ev_type = 2
|
||||
_ev_trig = 3
|
||||
_ev_data = 4
|
||||
_conn_base = {
|
||||
'qlog_version': '0.1',
|
||||
'vantagepoint': 'NETWORK',
|
||||
'connectionid': '0',
|
||||
'starttime': '0',
|
||||
'fields': [
|
||||
'time',
|
||||
'category',
|
||||
'type',
|
||||
'trigger',
|
||||
'data',
|
||||
],
|
||||
'events': [],
|
||||
}
|
||||
|
||||
arg_parser = argparse.ArgumentParser(description='Test the ExploreParser.')
|
||||
arg_parser.add_argument('qlog_path', type=str, help='path to QLog file')
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
try:
|
||||
with open(args.qlog_path, 'r') as file:
|
||||
text = file.read()
|
||||
except IOError:
|
||||
print('ERROR: QLog not found at given path.')
|
||||
|
||||
events = {}
|
||||
event_times = {}
|
||||
start_time = {}
|
||||
|
||||
qlog = {
|
||||
'qlog_version': '0.1',
|
||||
'description': 'test with local log file',
|
||||
'connections': [],
|
||||
}
|
||||
|
||||
lines = text.split('\n')
|
||||
for line in lines:
|
||||
if 'qlog' in line:
|
||||
i = line.find('[QUIC:')
|
||||
j = line.find(']', i)
|
||||
k = line.find('qlog: ')
|
||||
|
||||
cid = line[i+6:j]
|
||||
try:
|
||||
event = json.loads(line[k+6:])
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
if not cid in events:
|
||||
events[cid] = [event]
|
||||
event_times[cid] = [event[_ev_time]]
|
||||
else:
|
||||
events[cid].append(event)
|
||||
event_times[cid].append(event[_ev_time])
|
||||
|
||||
for cid, times in event_times.items():
|
||||
new_events = []
|
||||
start_time[cid] = min(times)
|
||||
times = [t - min(times) for t in times]
|
||||
for t, i in sorted(((t, i) for i, t in enumerate(times))):
|
||||
events[cid][i][0] = t
|
||||
new_events.append(events[cid][i])
|
||||
events[cid] = new_events
|
||||
|
||||
for cid, event_list in events.items():
|
||||
conn = _conn_base.copy()
|
||||
conn['connectionid'] = cid
|
||||
conn['starttime'] = start_time[cid]
|
||||
conn['events'] = event_list
|
||||
qlog['connections'].append(conn)
|
||||
|
||||
print(json.dumps(qlog, indent=2))
|
||||
|
Loading…
Reference in a new issue