Skip to content

Commit

Permalink
Release 2.28.0
Browse files Browse the repository at this point in the history
- [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.
  • Loading branch information
Dmitri Tikhonov committed Feb 3, 2021
1 parent 9a7f663 commit c2faf03
Show file tree
Hide file tree
Showing 19 changed files with 440 additions and 54 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
2021-02-03
- 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.

2021-01-27
- 2.27.6
- [BUGFIX] Replace dispatch read/write events assertion with a check.
Expand Down
5 changes: 3 additions & 2 deletions bin/http_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
39 changes: 26 additions & 13 deletions bin/http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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':
Expand Down Expand Up @@ -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);
Expand Down
60 changes: 60 additions & 0 deletions bin/prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions bin/test_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ static void getExtensionPtrs()
#endif




static struct packets_in *
allocate_packets_in (SOCKET_TYPE fd)
{
Expand Down
17 changes: 17 additions & 0 deletions docs/apiref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,14 @@ settings structure:

Default value is :macro:`LSQUIC_DF_MAX_BATCH_SIZE`

.. member:: int es_check_tp_sanity

When true, sanity checks are performed on peer's transport parameter
values. If some limits are set suspiciously low, the connection won't
be established.

Default value is :macro:`LSQUIC_DF_CHECK_TP_SANITY`

To initialize the settings structure to library defaults, use the following
convenience function:

Expand Down Expand Up @@ -1115,6 +1123,10 @@ out of date. Please check your :file:`lsquic.h` for actual values.*
By default, maximum batch size is not specified, leaving it up to the
library.

.. macro:: LSQUIC_DF_CHECK_TP_SANITY

Transport parameter sanity checks are performed by default.

Receiving Packets
-----------------

Expand Down Expand Up @@ -1337,6 +1349,11 @@ the engine to communicate with the user code:
This callback lets client record information needed to
perform session resumption next time around.

For IETF QUIC, this is called only if :member:`lsquic_engine_api.ea_get_ssl_ctx_st`
is *not* set, in which case the library creates its own SSL_CTX.

Note: this callback will be deprecated when gQUIC support is removed.

This callback is optional.

.. member:: ssize_t (*on_dg_write)(lsquic_conn_t *c, void *buf, size_t buf_sz)
Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
author = u'LiteSpeed Technologies'

# The short X.Y version
version = u'2.27'
version = u'2.28'
# The full version, including alpha/beta/rc tags
release = u'2.27.6'
release = u'2.28.0'


# -- General configuration ---------------------------------------------------
Expand Down
Loading

0 comments on commit c2faf03

Please sign in to comment.