mirror of
				https://gitea.invidious.io/iv-org/litespeed-quic.git
				synced 2024-08-15 00:53:43 +00:00 
			
		
		
		
	Release 2.22.0
- [FEATURE] Extensible HTTP Priorities (HTTP/3 only). - [FEATURE] Add conn context to packet-out memory interface (PR #175). - [BUGFIX] gQUIC proof generation: allocate buffer big enough for signature (issue #173). - [BUGFIX] Make library thread-safe: drop use of global variables (issue #133, issue #167). - [BUGFIX] Deactivate only *recent* HQ frame, not any HQ frame. - [BUGFIX] gQUIC server: associate compressed cert with SSL_CTX, instead of keeping them in a separate hash, potentially leading to mismatches. - [BUGFIX] Stream data discard infinite loop: break on FIN. - cmake: add install target via -DCMAKE_INSTALL_PREFIX (PR #171). - Support randomized packet number to begin a connection. - Mini and full IETF connection size optimization. - http_client: specify HTTP priorities based on stream conditions.
This commit is contained in:
		
							parent
							
								
									cb1e8c1022
								
							
						
					
					
						commit
						fbc6cc0413
					
				
					 55 changed files with 6557 additions and 391 deletions
				
			
		| 
						 | 
				
			
			@ -161,6 +161,24 @@ strndup(const char *s, size_t n)
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* When more than `nread' bytes are read from stream `stream_id', apply
 | 
			
		||||
 * priority in `ehp'.
 | 
			
		||||
 */
 | 
			
		||||
struct priority_spec
 | 
			
		||||
{
 | 
			
		||||
    enum {
 | 
			
		||||
        PRIORITY_SPEC_ACTIVE    = 1 << 0,
 | 
			
		||||
    }                                       flags;
 | 
			
		||||
    lsquic_stream_id_t                      stream_id;
 | 
			
		||||
    size_t                                  nread;
 | 
			
		||||
    struct lsquic_ext_http_prio             ehp;
 | 
			
		||||
};
 | 
			
		||||
static struct priority_spec *s_priority_specs;
 | 
			
		||||
static unsigned s_n_prio_specs;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
maybe_perform_priority_actions (struct lsquic_stream *, lsquic_stream_ctx_t *);
 | 
			
		||||
 | 
			
		||||
struct lsquic_conn_ctx;
 | 
			
		||||
 | 
			
		||||
struct path_elem {
 | 
			
		||||
| 
						 | 
				
			
			@ -531,7 +549,20 @@ http_client_on_new_stream (void *stream_if_ctx, lsquic_stream_t *stream)
 | 
			
		|||
    LSQ_INFO("created new stream, path: %s", st_h->path);
 | 
			
		||||
    lsquic_stream_wantwrite(stream, 1);
 | 
			
		||||
    if (randomly_reprioritize_streams)
 | 
			
		||||
        lsquic_stream_set_priority(stream, 1 + (random() & 0xFF));
 | 
			
		||||
    {
 | 
			
		||||
        if ((1 << lsquic_conn_quic_version(lsquic_stream_conn(stream)))
 | 
			
		||||
                                                    & LSQUIC_IETF_VERSIONS)
 | 
			
		||||
            lsquic_stream_set_http_prio(stream,
 | 
			
		||||
                &(struct lsquic_ext_http_prio){
 | 
			
		||||
                    .urgency = random() & 7,
 | 
			
		||||
                    .incremental = random() & 1,
 | 
			
		||||
                }
 | 
			
		||||
            );
 | 
			
		||||
        else
 | 
			
		||||
            lsquic_stream_set_priority(stream, 1 + (random() & 0xFF));
 | 
			
		||||
    }
 | 
			
		||||
    if (s_priority_specs)
 | 
			
		||||
        maybe_perform_priority_actions(stream, st_h);
 | 
			
		||||
    if (s_abandon_early)
 | 
			
		||||
    {
 | 
			
		||||
        st_h->sh_stop = random() % (s_abandon_early + 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -547,25 +578,37 @@ send_headers (lsquic_stream_ctx_t *st_h)
 | 
			
		|||
{
 | 
			
		||||
    const char *hostname = st_h->client_ctx->hostname;
 | 
			
		||||
    struct header_buf hbuf;
 | 
			
		||||
    unsigned h_idx = 0;
 | 
			
		||||
    if (!hostname)
 | 
			
		||||
        hostname = st_h->client_ctx->prog->prog_hostname;
 | 
			
		||||
    hbuf.off = 0;
 | 
			
		||||
    struct lsxpack_header headers_arr[7];
 | 
			
		||||
    struct lsxpack_header headers_arr[9];
 | 
			
		||||
#define V(v) (v), strlen(v)
 | 
			
		||||
    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: */
 | 
			
		||||
    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));
 | 
			
		||||
    header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":method"), V(st_h->client_ctx->method));
 | 
			
		||||
    header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":scheme"), V("https"));
 | 
			
		||||
    header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":path"), V(st_h->path));
 | 
			
		||||
    header_set_ptr(&headers_arr[h_idx++], &hbuf, V(":authority"), V(hostname));
 | 
			
		||||
    header_set_ptr(&headers_arr[h_idx++], &hbuf, V("user-agent"), V(st_h->client_ctx->prog->prog_settings.es_ua));
 | 
			
		||||
    if (randomly_reprioritize_streams)
 | 
			
		||||
    {
 | 
			
		||||
        char pfv[10];
 | 
			
		||||
        sprintf(pfv, "u=%ld", random() & 7);
 | 
			
		||||
        header_set_ptr(&headers_arr[h_idx++], &hbuf, V("priority"), V(pfv));
 | 
			
		||||
        if (random() & 1)
 | 
			
		||||
            sprintf(pfv, "i");
 | 
			
		||||
        else
 | 
			
		||||
            sprintf(pfv, "i=?0");
 | 
			
		||||
        header_set_ptr(&headers_arr[h_idx++], &hbuf, V("priority"), V(pfv));
 | 
			
		||||
    }
 | 
			
		||||
    if (st_h->client_ctx->payload)
 | 
			
		||||
    {
 | 
			
		||||
        header_set_ptr(&headers_arr[h_idx++], &hbuf, V("content-type"), V("application/octet-stream"));
 | 
			
		||||
        header_set_ptr(&headers_arr[h_idx++], &hbuf, V("content-length"), V( st_h->client_ctx->payload_size));
 | 
			
		||||
    }
 | 
			
		||||
    lsquic_http_headers_t headers = {
 | 
			
		||||
        .count = sizeof(headers_arr) / sizeof(headers_arr[0]),
 | 
			
		||||
        .count = h_idx,
 | 
			
		||||
        .headers = headers_arr,
 | 
			
		||||
    };
 | 
			
		||||
    if (!st_h->client_ctx->payload)
 | 
			
		||||
        headers.count -= 2;
 | 
			
		||||
    if (0 != lsquic_stream_send_headers(st_h->stream, &headers,
 | 
			
		||||
                                    st_h->client_ctx->payload == NULL))
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -659,6 +702,40 @@ discard (void *ctx, const unsigned char *buf, size_t sz, int fin)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
maybe_perform_priority_actions (struct lsquic_stream *stream,
 | 
			
		||||
                                                lsquic_stream_ctx_t *st_h)
 | 
			
		||||
{
 | 
			
		||||
    const lsquic_stream_id_t stream_id = lsquic_stream_id(stream);
 | 
			
		||||
    struct priority_spec *spec;
 | 
			
		||||
    unsigned n_active;
 | 
			
		||||
    int s;
 | 
			
		||||
 | 
			
		||||
    n_active = 0;
 | 
			
		||||
    for (spec = s_priority_specs; spec < s_priority_specs + s_n_prio_specs;
 | 
			
		||||
                                                                        ++spec)
 | 
			
		||||
    {
 | 
			
		||||
        if ((spec->flags & PRIORITY_SPEC_ACTIVE)
 | 
			
		||||
            && spec->stream_id == stream_id
 | 
			
		||||
            && st_h->sh_nread >= spec->nread)
 | 
			
		||||
        {
 | 
			
		||||
            s = lsquic_stream_set_http_prio(stream, &spec->ehp);
 | 
			
		||||
            if (s != 0)
 | 
			
		||||
            {
 | 
			
		||||
                LSQ_ERROR("could not apply priorities to stream %"PRIu64,
 | 
			
		||||
                                                                    stream_id);
 | 
			
		||||
                exit(1);
 | 
			
		||||
            }
 | 
			
		||||
            spec->flags &= ~PRIORITY_SPEC_ACTIVE;
 | 
			
		||||
        }
 | 
			
		||||
        n_active += !!(spec->flags & PRIORITY_SPEC_ACTIVE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (n_active == 0)
 | 
			
		||||
        s_priority_specs = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -728,16 +805,36 @@ http_client_on_read (lsquic_stream_t *stream, lsquic_stream_ctx_t *st_h)
 | 
			
		|||
                fwrite(buf, 1, nread, stdout);
 | 
			
		||||
            if (randomly_reprioritize_streams && (st_h->count++ & 0x3F) == 0)
 | 
			
		||||
            {
 | 
			
		||||
                old_prio = lsquic_stream_priority(stream);
 | 
			
		||||
                new_prio = 1 + (random() & 0xFF);
 | 
			
		||||
                if ((1 << lsquic_conn_quic_version(lsquic_stream_conn(stream)))
 | 
			
		||||
                                                        & LSQUIC_IETF_VERSIONS)
 | 
			
		||||
                {
 | 
			
		||||
                    struct lsquic_ext_http_prio ehp;
 | 
			
		||||
                    if (0 == lsquic_stream_get_http_prio(stream, &ehp))
 | 
			
		||||
                    {
 | 
			
		||||
                        ehp.urgency = 7 & (ehp.urgency + 1);
 | 
			
		||||
                        ehp.incremental = !ehp.incremental;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
                const int s =
 | 
			
		||||
                        const int s =
 | 
			
		||||
#endif
 | 
			
		||||
                lsquic_stream_set_priority(stream, new_prio);
 | 
			
		||||
                assert(s == 0);
 | 
			
		||||
                LSQ_DEBUG("changed stream %"PRIu64" priority from %u to %u",
 | 
			
		||||
                        lsquic_stream_set_http_prio(stream, &ehp);
 | 
			
		||||
                        assert(s == 0);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    old_prio = lsquic_stream_priority(stream);
 | 
			
		||||
                    new_prio = 1 + (random() & 0xFF);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
                    const int s =
 | 
			
		||||
#endif
 | 
			
		||||
                    lsquic_stream_set_priority(stream, new_prio);
 | 
			
		||||
                    assert(s == 0);
 | 
			
		||||
                    LSQ_DEBUG("changed stream %"PRIu64" priority from %u to %u",
 | 
			
		||||
                                lsquic_stream_id(stream), old_prio, new_prio);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (s_priority_specs)
 | 
			
		||||
                maybe_perform_priority_actions(stream, st_h);
 | 
			
		||||
            if ((st_h->sh_flags & ABANDON) && st_h->sh_nread >= st_h->sh_stop)
 | 
			
		||||
            {
 | 
			
		||||
                LSQ_DEBUG("closing stream early having read %zd bytes",
 | 
			
		||||
| 
						 | 
				
			
			@ -864,6 +961,9 @@ usage (const char *prog)
 | 
			
		|||
"   -e TOKEN    Hexadecimal string representing resume token.\n"
 | 
			
		||||
"   -3 MAX      Close stream after reading at most MAX bytes.  The actual\n"
 | 
			
		||||
"                 number of bytes read is randominzed.\n"
 | 
			
		||||
"   -9 SPEC     Priority specification.  May be specified several times.\n"
 | 
			
		||||
"                 SPEC takes the form stream_id:nread:UI, where U is\n"
 | 
			
		||||
"                 urgency and I is incremental.  Matched \\d+:\\d+:[0-7][01]\n"
 | 
			
		||||
            , prog);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1432,6 +1532,7 @@ main (int argc, char **argv)
 | 
			
		|||
    struct sport_head sports;
 | 
			
		||||
    struct prog prog;
 | 
			
		||||
    const char *token = NULL;
 | 
			
		||||
    struct priority_spec *priority_specs = NULL;
 | 
			
		||||
 | 
			
		||||
    TAILQ_INIT(&sports);
 | 
			
		||||
    memset(&client_ctx, 0, sizeof(client_ctx));
 | 
			
		||||
| 
						 | 
				
			
			@ -1450,6 +1551,7 @@ main (int argc, char **argv)
 | 
			
		|||
    while (-1 != (opt = getopt(argc, argv, PROG_OPTS
 | 
			
		||||
                                    "46Br:R:IKu:EP:M:n:w:H:p:0:q:e:hatT:b:d:"
 | 
			
		||||
                            "3:"    /* 3 is 133+ for "e" ("e" for "early") */
 | 
			
		||||
                            "9:"    /* 9 sort of looks like P... */
 | 
			
		||||
#ifndef WIN32
 | 
			
		||||
                                                                      "C:"
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1486,6 +1588,7 @@ main (int argc, char **argv)
 | 
			
		|||
        case 'E':   /* E: randomly reprioritize str<E>ams.  Now, that's
 | 
			
		||||
                     * pretty random. :)
 | 
			
		||||
                     */
 | 
			
		||||
            srand((uintptr_t) argv);
 | 
			
		||||
            randomly_reprioritize_streams = 1;
 | 
			
		||||
            break;
 | 
			
		||||
        case 'n':
 | 
			
		||||
| 
						 | 
				
			
			@ -1569,6 +1672,45 @@ main (int argc, char **argv)
 | 
			
		|||
        case '3':
 | 
			
		||||
            s_abandon_early = strtol(optarg, NULL, 10);
 | 
			
		||||
            break;
 | 
			
		||||
        case '9':
 | 
			
		||||
        {
 | 
			
		||||
            /* Parse priority spec and tack it onto the end of the array */
 | 
			
		||||
            lsquic_stream_id_t stream_id;
 | 
			
		||||
            size_t nread;
 | 
			
		||||
            struct lsquic_ext_http_prio ehp;
 | 
			
		||||
            struct priority_spec *new_specs;
 | 
			
		||||
            stream_id = strtoull(optarg, &optarg, 10);
 | 
			
		||||
            if (*optarg != ':')
 | 
			
		||||
                exit(1);
 | 
			
		||||
            ++optarg;
 | 
			
		||||
            nread = strtoull(optarg, &optarg, 10);
 | 
			
		||||
            if (*optarg != ':')
 | 
			
		||||
                exit(1);
 | 
			
		||||
            ++optarg;
 | 
			
		||||
            if (!(*optarg >= '0' && *optarg <= '7'))
 | 
			
		||||
                exit(1);
 | 
			
		||||
            ehp.urgency = *optarg++ - '0';
 | 
			
		||||
            if (!(*optarg >= '0' && *optarg <= '1'))
 | 
			
		||||
                exit(1);
 | 
			
		||||
            ehp.incremental = *optarg++ - '0';
 | 
			
		||||
            ++s_n_prio_specs;
 | 
			
		||||
            new_specs = realloc(priority_specs,
 | 
			
		||||
                                sizeof(priority_specs[0]) * s_n_prio_specs);
 | 
			
		||||
            if (!new_specs)
 | 
			
		||||
            {
 | 
			
		||||
                perror("malloc");
 | 
			
		||||
                exit(1);
 | 
			
		||||
            }
 | 
			
		||||
            priority_specs = new_specs;
 | 
			
		||||
            priority_specs[s_n_prio_specs - 1] = (struct priority_spec) {
 | 
			
		||||
                .flags      = PRIORITY_SPEC_ACTIVE,
 | 
			
		||||
                .stream_id  = stream_id,
 | 
			
		||||
                .nread      = nread,
 | 
			
		||||
                .ehp        = ehp,
 | 
			
		||||
            };
 | 
			
		||||
            s_priority_specs = priority_specs;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default:
 | 
			
		||||
            if (0 != prog_set_opt(&prog, opt, optarg))
 | 
			
		||||
                exit(1);
 | 
			
		||||
| 
						 | 
				
			
			@ -1660,5 +1802,6 @@ main (int argc, char **argv)
 | 
			
		|||
    if (client_ctx.qif_fh)
 | 
			
		||||
        (void) fclose(client_ctx.qif_fh);
 | 
			
		||||
 | 
			
		||||
    free(priority_specs);
 | 
			
		||||
    exit(0 == s ? EXIT_SUCCESS : EXIT_FAILURE);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,8 +41,8 @@
 | 
			
		|||
 | 
			
		||||
#include <event2/event.h>
 | 
			
		||||
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "lsquic.h"
 | 
			
		||||
#include "test_common.h"
 | 
			
		||||
#include "prog.h"
 | 
			
		||||
#include "lsxpack_header.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1916,6 +1916,11 @@ set_engine_option (struct lsquic_engine_settings *settings,
 | 
			
		|||
            settings->es_scid_iss_rate = atoi(val);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (0 == strncmp(name, "ext_http_prio", 13))
 | 
			
		||||
        {
 | 
			
		||||
            settings->es_ext_http_prio = atoi(val);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case 14:
 | 
			
		||||
        if (0 == strncmp(name, "max_streams_in", 14))
 | 
			
		||||
| 
						 | 
				
			
			@ -2043,8 +2048,8 @@ pba_init (struct packout_buf_allocator *pba, unsigned max)
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
void *
 | 
			
		||||
pba_allocate (void *packout_buf_allocator, void *peer_ctx, void *conn_ctx, unsigned short size,
 | 
			
		||||
                                                                char is_ipv6)
 | 
			
		||||
pba_allocate (void *packout_buf_allocator, void *peer_ctx,
 | 
			
		||||
                lsquic_conn_ctx_t *conn_ctx, unsigned short size, char is_ipv6)
 | 
			
		||||
{
 | 
			
		||||
    struct packout_buf_allocator *const pba = packout_buf_allocator;
 | 
			
		||||
    struct packout_buf *pb;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ void
 | 
			
		|||
pba_init (struct packout_buf_allocator *, unsigned max);
 | 
			
		||||
 | 
			
		||||
void *
 | 
			
		||||
pba_allocate (void *packout_buf_allocator, void*, void *conn_ctx, unsigned short, char);
 | 
			
		||||
pba_allocate (void *packout_buf_allocator, void*, lsquic_conn_ctx_t *, unsigned short, char);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
pba_release (void *packout_buf_allocator, void *, void *obj, char);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue