Mercurial > hg > nginx
view src/http/v3/ngx_http_v3_encode.c @ 9196:6c8595b77e66
QUIC: path aware in-flight bytes accounting.
On-packet acknowledgement is made path aware, as per RFC 9000, Section 9.4:
Packets sent on the old path MUST NOT contribute to congestion control
or RTT estimation for the new path.
To make this possible in a single congestion control context, the first packet
to be sent after the new path has been validated, which includes resetting the
congestion controller and RTT estimator, is now remembered in the connection.
Packets sent previously, such as on the old path, are not taken into account.
Note that although the packet number is saved per-connection, the added checks
affect application level packets only. For non-application level packets,
which are only processed prior to the handshake is complete, the remembered
packet number remains set to zero.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Tue, 12 Dec 2023 20:21:12 +0400 |
parents | 5c86189a1c1b |
children |
line wrap: on
line source
/* * Copyright (C) Roman Arutyunyan * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_http.h> uintptr_t ngx_http_v3_encode_varlen_int(u_char *p, uint64_t value) { if (value <= 63) { if (p == NULL) { return 1; } *p++ = value; return (uintptr_t) p; } if (value <= 16383) { if (p == NULL) { return 2; } *p++ = 0x40 | (value >> 8); *p++ = value; return (uintptr_t) p; } if (value <= 1073741823) { if (p == NULL) { return 4; } *p++ = 0x80 | (value >> 24); *p++ = (value >> 16); *p++ = (value >> 8); *p++ = value; return (uintptr_t) p; } if (p == NULL) { return 8; } *p++ = 0xc0 | (value >> 56); *p++ = (value >> 48); *p++ = (value >> 40); *p++ = (value >> 32); *p++ = (value >> 24); *p++ = (value >> 16); *p++ = (value >> 8); *p++ = value; return (uintptr_t) p; } uintptr_t ngx_http_v3_encode_prefix_int(u_char *p, uint64_t value, ngx_uint_t prefix) { ngx_uint_t thresh, n; thresh = (1 << prefix) - 1; if (value < thresh) { if (p == NULL) { return 1; } *p++ |= value; return (uintptr_t) p; } value -= thresh; if (p == NULL) { for (n = 2; value >= 128; n++) { value >>= 7; } return n; } *p++ |= thresh; while (value >= 128) { *p++ = 0x80 | value; value >>= 7; } *p++ = value; return (uintptr_t) p; } uintptr_t ngx_http_v3_encode_field_section_prefix(u_char *p, ngx_uint_t insert_count, ngx_uint_t sign, ngx_uint_t delta_base) { if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, insert_count, 8) + ngx_http_v3_encode_prefix_int(NULL, delta_base, 7); } *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, insert_count, 8); *p = sign ? 0x80 : 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, delta_base, 7); return (uintptr_t) p; } uintptr_t ngx_http_v3_encode_field_ri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index) { /* Indexed Field Line */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 6); } *p = dynamic ? 0x80 : 0xc0; return ngx_http_v3_encode_prefix_int(p, index, 6); } uintptr_t ngx_http_v3_encode_field_lri(u_char *p, ngx_uint_t dynamic, ngx_uint_t index, u_char *data, size_t len) { size_t hlen; u_char *p1, *p2; /* Literal Field Line With Name Reference */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 4) + ngx_http_v3_encode_prefix_int(NULL, len, 7) + len; } *p = dynamic ? 0x40 : 0x50; p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 4); p1 = p; *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, len, 7); if (data) { p2 = p; hlen = ngx_http_huff_encode(data, len, p, 0); if (hlen) { p = p1; *p = 0x80; p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 7); if (p != p2) { ngx_memmove(p, p2, hlen); } p += hlen; } else { p = ngx_cpymem(p, data, len); } } return (uintptr_t) p; } uintptr_t ngx_http_v3_encode_field_l(u_char *p, ngx_str_t *name, ngx_str_t *value) { size_t hlen; u_char *p1, *p2; /* Literal Field Line With Literal Name */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, name->len, 3) + name->len + ngx_http_v3_encode_prefix_int(NULL, value->len, 7) + value->len; } p1 = p; *p = 0x20; p = (u_char *) ngx_http_v3_encode_prefix_int(p, name->len, 3); p2 = p; hlen = ngx_http_huff_encode(name->data, name->len, p, 1); if (hlen) { p = p1; *p = 0x28; p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 3); if (p != p2) { ngx_memmove(p, p2, hlen); } p += hlen; } else { ngx_strlow(p, name->data, name->len); p += name->len; } p1 = p; *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7); p2 = p; hlen = ngx_http_huff_encode(value->data, value->len, p, 0); if (hlen) { p = p1; *p = 0x80; p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 7); if (p != p2) { ngx_memmove(p, p2, hlen); } p += hlen; } else { p = ngx_cpymem(p, value->data, value->len); } return (uintptr_t) p; } uintptr_t ngx_http_v3_encode_field_pbi(u_char *p, ngx_uint_t index) { /* Indexed Field Line With Post-Base Index */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 4); } *p = 0x10; return ngx_http_v3_encode_prefix_int(p, index, 4); } uintptr_t ngx_http_v3_encode_field_lpbi(u_char *p, ngx_uint_t index, u_char *data, size_t len) { size_t hlen; u_char *p1, *p2; /* Literal Field Line With Post-Base Name Reference */ if (p == NULL) { return ngx_http_v3_encode_prefix_int(NULL, index, 3) + ngx_http_v3_encode_prefix_int(NULL, len, 7) + len; } *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 3); p1 = p; *p = 0; p = (u_char *) ngx_http_v3_encode_prefix_int(p, len, 7); if (data) { p2 = p; hlen = ngx_http_huff_encode(data, len, p, 0); if (hlen) { p = p1; *p = 0x80; p = (u_char *) ngx_http_v3_encode_prefix_int(p, hlen, 7); if (p != p2) { ngx_memmove(p, p2, hlen); } p += hlen; } else { p = ngx_cpymem(p, data, len); } } return (uintptr_t) p; }