mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
Release 2.28.0
- [API] lsquic_ssl_sess_to_resume_info() is the new way to get session info. - [API] Add user pointer to ea_generate_scid callback. - [API] Add lsquic_dcid_from_packet() -- a fast function to parse out DCID. - [API] Add es_max_batch_size to control outgoing packet batch size. - [BUGFIX] Disallow sending of header while promise is being written. - [BUGFIX] Flush stream when buffered bytes exhaust stream cap. - [BUGFIX] Deactivate HQ frame if writing push promise fails. - Perform sanity check on peer transport parameters and fail the handshake if some flow control limits are too low. This can be turned off, see es_check_tp_sanity. - http_server: fix how requests are read in "hq" mode.
This commit is contained in:
parent
9a7f663e1a
commit
c2faf03244
19 changed files with 440 additions and 54 deletions
|
@ -426,6 +426,7 @@ http_client_on_hsk_done (lsquic_conn_t *conn, enum lsquic_hsk_status status)
|
|||
}
|
||||
|
||||
|
||||
/* Now only used for gQUIC and will be going away after that */
|
||||
static void
|
||||
http_client_on_sess_resume_info (lsquic_conn_t *conn, const unsigned char *buf,
|
||||
size_t bufsz)
|
||||
|
@ -1011,7 +1012,6 @@ usage (const char *prog)
|
|||
" -I Abort on incomplete reponse from server\n"
|
||||
" -4 Prefer IPv4 when resolving hostname\n"
|
||||
" -6 Prefer IPv6 when resolving hostname\n"
|
||||
" -0 FILE Provide RTT info file (reading or writing)\n"
|
||||
#ifndef WIN32
|
||||
" -C DIR Certificate store. If specified, server certificate will\n"
|
||||
" be verified.\n"
|
||||
|
@ -1736,7 +1736,7 @@ main (int argc, char **argv)
|
|||
case '0':
|
||||
http_client_if.on_sess_resume_info = http_client_on_sess_resume_info;
|
||||
client_ctx.hcc_sess_resume_file_name = optarg;
|
||||
break;
|
||||
goto common_opts;
|
||||
case '3':
|
||||
s_abandon_early = strtol(optarg, NULL, 10);
|
||||
break;
|
||||
|
@ -1788,6 +1788,7 @@ main (int argc, char **argv)
|
|||
prog.prog_api.ea_alpn = optarg;
|
||||
prog.prog_api.ea_stream_if = &hq_client_if;
|
||||
break;
|
||||
common_opts:
|
||||
default:
|
||||
if (0 != prog_set_opt(&prog, opt, optarg))
|
||||
exit(1);
|
||||
|
|
|
@ -1066,30 +1066,36 @@ const struct lsquic_stream_if http_server_if = {
|
|||
};
|
||||
|
||||
|
||||
/* XXX Assume we can always read the request in one shot. This is not a
|
||||
* good assumption to make in a real product.
|
||||
*/
|
||||
#if HAVE_OPEN_MEMSTREAM
|
||||
static void
|
||||
hq_server_on_read (struct lsquic_stream *stream, lsquic_stream_ctx_t *st_h)
|
||||
{
|
||||
char buf[0x400];
|
||||
char tbuf[0x100], *buf;
|
||||
ssize_t nread;
|
||||
char *path, *end, *filename;
|
||||
|
||||
nread = lsquic_stream_read(stream, buf, sizeof(buf));
|
||||
if (nread >= (ssize_t) sizeof(buf))
|
||||
if (!st_h->req_fh)
|
||||
st_h->req_fh = open_memstream(&st_h->req_buf, &st_h->req_sz);
|
||||
|
||||
nread = lsquic_stream_read(stream, tbuf, sizeof(tbuf));
|
||||
if (nread > 0)
|
||||
{
|
||||
LSQ_WARN("request too large, at least %zd bytes", sizeof(buf));
|
||||
lsquic_stream_close(stream);
|
||||
fwrite(tbuf, 1, nread, st_h->req_fh);
|
||||
return;
|
||||
}
|
||||
else if (nread < 0)
|
||||
|
||||
if (nread < 0)
|
||||
{
|
||||
LSQ_WARN("error reading request from stream: %s", strerror(errno));
|
||||
lsquic_stream_close(stream);
|
||||
return;
|
||||
}
|
||||
buf[nread] = '\0';
|
||||
|
||||
fwrite("", 1, 1, st_h->req_fh);
|
||||
fclose(st_h->req_fh);
|
||||
LSQ_INFO("got request: `%.*s'", (int) st_h->req_sz, st_h->req_buf);
|
||||
|
||||
buf = st_h->req_buf;
|
||||
path = strchr(buf, ' ');
|
||||
if (!path)
|
||||
{
|
||||
|
@ -1104,8 +1110,8 @@ hq_server_on_read (struct lsquic_stream *stream, lsquic_stream_ctx_t *st_h)
|
|||
return;
|
||||
}
|
||||
++path;
|
||||
for (end = path + nread - 5; end > path
|
||||
&& (*end == '\r' || *end == '\n'); --end)
|
||||
for (end = buf + st_h->req_sz - 1; end > path
|
||||
&& (*end == '\0' || *end == '\r' || *end == '\n'); --end)
|
||||
*end = '\0';
|
||||
LSQ_NOTICE("parsed out request path: %s", path);
|
||||
|
||||
|
@ -1174,6 +1180,7 @@ const struct lsquic_stream_if hq_server_if = {
|
|||
.on_write = hq_server_on_write,
|
||||
.on_close = http_server_on_close,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#if HAVE_REGEX
|
||||
|
@ -1922,7 +1929,11 @@ main (int argc, char **argv)
|
|||
prog_init(&prog, LSENG_SERVER|LSENG_HTTP, &server_ctx.sports,
|
||||
&http_server_if, &server_ctx);
|
||||
|
||||
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "y:Y:n:p:r:w:P:hQ:")))
|
||||
while (-1 != (opt = getopt(argc, argv, PROG_OPTS "y:Y:n:p:r:w:P:h"
|
||||
#if HAVE_OPEN_MEMSTREAM
|
||||
"Q:"
|
||||
#endif
|
||||
)))
|
||||
{
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
|
@ -1965,12 +1976,14 @@ main (int argc, char **argv)
|
|||
usage(argv[0]);
|
||||
prog_print_common_options(&prog, stdout);
|
||||
exit(0);
|
||||
#if HAVE_OPEN_MEMSTREAM
|
||||
case 'Q':
|
||||
/* XXX A bit hacky, as `prog' has already been initialized... */
|
||||
prog.prog_engine_flags &= ~LSENG_HTTP;
|
||||
prog.prog_api.ea_stream_if = &hq_server_if;
|
||||
add_alpn(optarg);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (0 != prog_set_opt(&prog, opt, optarg))
|
||||
exit(1);
|
||||
|
|
60
bin/prog.c
60
bin/prog.c
|
@ -39,6 +39,7 @@
|
|||
|
||||
static int prog_stopped;
|
||||
static const char *s_keylog_dir;
|
||||
static const char *s_sess_resume_file;
|
||||
|
||||
static SSL_CTX * get_ssl_ctx (void *, const struct sockaddr *);
|
||||
static void keylog_log_line (const SSL *, const char *);
|
||||
|
@ -118,6 +119,7 @@ void
|
|||
prog_print_common_options (const struct prog *prog, FILE *out)
|
||||
{
|
||||
fprintf(out,
|
||||
" -0 FILE Provide session resumption file (reading or writing)\n"
|
||||
#if HAVE_REGEX
|
||||
" -s SVCPORT Service port. Takes on the form of host:port, host,\n"
|
||||
" or port. If host is not an IPv4 or IPv6 address, it is\n"
|
||||
|
@ -338,6 +340,9 @@ prog_set_opt (struct prog *prog, int opt, const char *arg)
|
|||
sport->sp_flags |= SPORT_CONNECT;
|
||||
}
|
||||
return 0;
|
||||
case '0':
|
||||
s_sess_resume_file = optarg;
|
||||
return 0;
|
||||
case 'G':
|
||||
#ifndef WIN32
|
||||
if (0 == stat(optarg, &st))
|
||||
|
@ -426,6 +431,53 @@ get_ssl_ctx (void *peer_ctx, const struct sockaddr *unused)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
prog_new_session_cb (SSL *ssl, SSL_SESSION *session)
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t bufsz, nw;
|
||||
FILE *file;
|
||||
|
||||
/* Our client is rather limited: only one file and only one ticket
|
||||
* can be saved. A more flexible client implementation would call
|
||||
* lsquic_ssl_to_conn() and maybe save more tickets based on its
|
||||
* own configuration.
|
||||
*/
|
||||
if (!s_sess_resume_file)
|
||||
return 0;
|
||||
|
||||
if (0 != lsquic_ssl_sess_to_resume_info(ssl, session, &buf, &bufsz))
|
||||
{
|
||||
LSQ_NOTICE("lsquic_ssl_sess_to_resume_info failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = fopen(s_sess_resume_file, "wb");
|
||||
if (!file)
|
||||
{
|
||||
LSQ_WARN("cannot open %s for writing: %s",
|
||||
s_sess_resume_file, strerror(errno));
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nw = fwrite(buf, 1, bufsz, file);
|
||||
if (nw == bufsz)
|
||||
{
|
||||
LSQ_INFO("wrote %zd bytes of session resumption information to %s",
|
||||
nw, s_sess_resume_file);
|
||||
s_sess_resume_file = NULL; /* Save just one ticket */
|
||||
}
|
||||
else
|
||||
LSQ_WARN("error: fwrite(%s) returns %zd instead of %zd: %s",
|
||||
s_sess_resume_file, nw, bufsz, strerror(errno));
|
||||
|
||||
fclose(file);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
prog_init_ssl_ctx (struct prog *prog)
|
||||
{
|
||||
|
@ -454,6 +506,14 @@ prog_init_ssl_ctx (struct prog *prog)
|
|||
if (s_keylog_dir)
|
||||
SSL_CTX_set_keylog_callback(prog->prog_ssl_ctx, keylog_log_line);
|
||||
|
||||
if (s_sess_resume_file)
|
||||
{
|
||||
SSL_CTX_set_session_cache_mode(prog->prog_ssl_ctx,
|
||||
SSL_SESS_CACHE_CLIENT);
|
||||
SSL_CTX_set_early_data_enabled(prog->prog_ssl_ctx, 1);
|
||||
SSL_CTX_sess_set_new_cb(prog->prog_ssl_ctx, prog_new_session_cb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,8 @@ static void getExtensionPtrs()
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
static struct packets_in *
|
||||
allocate_packets_in (SOCKET_TYPE fd)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue