mirror of
https://github.com/moparisthebest/curl
synced 2024-11-15 05:55:04 -05:00
alt-svc: add protocol version selection masking
So that users can mask in/out specific HTTP versions when Alt-Svc is used. - Removed "h2c" and updated test case accordingly - Changed how the altsvc struct is laid out - Added ifdefs to make the unittest run even in a quiche-tree Closes #4201
This commit is contained in:
parent
a93b43cde8
commit
69b3ff5118
57
lib/altsvc.c
57
lib/altsvc.c
@ -54,9 +54,7 @@ static enum alpnid alpn2alpnid(char *name)
|
||||
return ALPN_h1;
|
||||
if(strcasecompare(name, "h2"))
|
||||
return ALPN_h2;
|
||||
if(strcasecompare(name, "h2c"))
|
||||
return ALPN_h2c;
|
||||
#ifdef USE_QUICHE
|
||||
#if defined(USE_QUICHE) && !defined(UNITTESTS)
|
||||
if(strcasecompare(name, "h3-22"))
|
||||
return ALPN_h3;
|
||||
#else
|
||||
@ -74,10 +72,8 @@ const char *Curl_alpnid2str(enum alpnid id)
|
||||
return "h1";
|
||||
case ALPN_h2:
|
||||
return "h2";
|
||||
case ALPN_h2c:
|
||||
return "h2c";
|
||||
case ALPN_h3:
|
||||
#ifdef USE_QUICHE
|
||||
#if defined(USE_QUICHE) && !defined(UNITTESTS)
|
||||
return "h3-22";
|
||||
#else
|
||||
return "h3";
|
||||
@ -90,8 +86,8 @@ const char *Curl_alpnid2str(enum alpnid id)
|
||||
|
||||
static void altsvc_free(struct altsvc *as)
|
||||
{
|
||||
free(as->srchost);
|
||||
free(as->dsthost);
|
||||
free(as->src.host);
|
||||
free(as->dst.host);
|
||||
free(as);
|
||||
}
|
||||
|
||||
@ -106,17 +102,17 @@ static struct altsvc *altsvc_createid(const char *srchost,
|
||||
if(!as)
|
||||
return NULL;
|
||||
|
||||
as->srchost = strdup(srchost);
|
||||
if(!as->srchost)
|
||||
as->src.host = strdup(srchost);
|
||||
if(!as->src.host)
|
||||
goto error;
|
||||
as->dsthost = strdup(dsthost);
|
||||
if(!as->dsthost)
|
||||
as->dst.host = strdup(dsthost);
|
||||
if(!as->dst.host)
|
||||
goto error;
|
||||
|
||||
as->srcalpnid = srcalpnid;
|
||||
as->dstalpnid = dstalpnid;
|
||||
as->srcport = curlx_ultous(srcport);
|
||||
as->dstport = curlx_ultous(dstport);
|
||||
as->src.alpnid = srcalpnid;
|
||||
as->dst.alpnid = dstalpnid;
|
||||
as->src.port = curlx_ultous(srcport);
|
||||
as->dst.port = curlx_ultous(dstport);
|
||||
|
||||
return as;
|
||||
error:
|
||||
@ -235,8 +231,8 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp)
|
||||
"\"%d%02d%02d "
|
||||
"%02d:%02d:%02d\" "
|
||||
"%u %d\n",
|
||||
Curl_alpnid2str(as->srcalpnid), as->srchost, as->srcport,
|
||||
Curl_alpnid2str(as->dstalpnid), as->dsthost, as->dstport,
|
||||
Curl_alpnid2str(as->src.alpnid), as->src.host, as->src.port,
|
||||
Curl_alpnid2str(as->dst.alpnid), as->dst.host, as->dst.port,
|
||||
stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
|
||||
stamp.tm_hour, stamp.tm_min, stamp.tm_sec,
|
||||
as->persist, as->prio);
|
||||
@ -261,7 +257,7 @@ struct altsvcinfo *Curl_altsvc_init(void)
|
||||
#ifdef USE_NGHTTP2
|
||||
| CURLALTSVC_H2
|
||||
#endif
|
||||
#ifdef USE_HTTP3
|
||||
#ifdef ENABLE_QUIC
|
||||
| CURLALTSVC_H3
|
||||
#endif
|
||||
;
|
||||
@ -374,9 +370,9 @@ static void altsvc_flush(struct altsvcinfo *asi, enum alpnid srcalpnid,
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
n = e->next;
|
||||
if((srcalpnid == as->srcalpnid) &&
|
||||
(srcport == as->srcport) &&
|
||||
strcasecompare(srchost, as->srchost)) {
|
||||
if((srcalpnid == as->src.alpnid) &&
|
||||
(srcport == as->src.port) &&
|
||||
strcasecompare(srchost, as->src.host)) {
|
||||
Curl_llist_remove(&asi->list, e, NULL);
|
||||
altsvc_free(as);
|
||||
asi->num--;
|
||||
@ -544,15 +540,15 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
bool Curl_altsvc_lookup(struct altsvcinfo *asi,
|
||||
enum alpnid srcalpnid, const char *srchost,
|
||||
int srcport,
|
||||
enum alpnid *dstalpnid, const char **dsthost,
|
||||
int *dstport)
|
||||
struct altsvc **dstentry,
|
||||
const int versions) /* one or more bits */
|
||||
{
|
||||
struct curl_llist_element *e;
|
||||
struct curl_llist_element *n;
|
||||
time_t now = time(NULL);
|
||||
DEBUGASSERT(asi);
|
||||
DEBUGASSERT(srchost);
|
||||
DEBUGASSERT(dsthost);
|
||||
DEBUGASSERT(dstentry);
|
||||
|
||||
for(e = asi->list.head; e; e = n) {
|
||||
struct altsvc *as = e->ptr;
|
||||
@ -563,13 +559,12 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi,
|
||||
altsvc_free(as);
|
||||
continue;
|
||||
}
|
||||
if((as->srcalpnid == srcalpnid) &&
|
||||
strcasecompare(as->srchost, srchost) &&
|
||||
as->srcport == srcport) {
|
||||
if((as->src.alpnid == srcalpnid) &&
|
||||
strcasecompare(as->src.host, srchost) &&
|
||||
(as->src.port == srcport) &&
|
||||
(versions & as->dst.alpnid)) {
|
||||
/* match */
|
||||
*dstalpnid = as->dstalpnid;
|
||||
*dsthost = as->dsthost;
|
||||
*dstport = as->dstport;
|
||||
*dstentry = as;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
27
lib/altsvc.h
27
lib/altsvc.h
@ -28,20 +28,21 @@
|
||||
#include "llist.h"
|
||||
|
||||
enum alpnid {
|
||||
ALPN_none,
|
||||
ALPN_h1,
|
||||
ALPN_h2,
|
||||
ALPN_h2c,
|
||||
ALPN_h3
|
||||
ALPN_none = 0,
|
||||
ALPN_h1 = CURLALTSVC_H1,
|
||||
ALPN_h2 = CURLALTSVC_H2,
|
||||
ALPN_h3 = CURLALTSVC_H3
|
||||
};
|
||||
|
||||
struct althost {
|
||||
char *host;
|
||||
unsigned short port;
|
||||
enum alpnid alpnid;
|
||||
};
|
||||
|
||||
struct altsvc {
|
||||
char *srchost;
|
||||
char *dsthost;
|
||||
unsigned short srcport;
|
||||
unsigned short dstport;
|
||||
enum alpnid srcalpnid;
|
||||
enum alpnid dstalpnid;
|
||||
struct althost src;
|
||||
struct althost dst;
|
||||
time_t expires;
|
||||
bool persist;
|
||||
int prio;
|
||||
@ -68,8 +69,8 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data,
|
||||
bool Curl_altsvc_lookup(struct altsvcinfo *asi,
|
||||
enum alpnid srcalpnid, const char *srchost,
|
||||
int srcport,
|
||||
enum alpnid *dstalpnid, const char **dsthost,
|
||||
int *dstport);
|
||||
struct altsvc **dstentry,
|
||||
int versions); /* one or more CURLALTSVC_H* bits */
|
||||
#else
|
||||
/* disabled */
|
||||
#define Curl_altsvc_save(a,b)
|
||||
|
41
lib/url.c
41
lib/url.c
@ -3158,42 +3158,51 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data,
|
||||
if(data->asi && !host && (port == -1) &&
|
||||
(conn->handler->protocol == CURLPROTO_HTTPS)) {
|
||||
/* no connect_to match, try alt-svc! */
|
||||
const char *nhost;
|
||||
int nport;
|
||||
enum alpnid nalpnid;
|
||||
enum alpnid salpnid;
|
||||
enum alpnid srcalpnid;
|
||||
bool hit;
|
||||
struct altsvc *as;
|
||||
const int allowed_versions = ( ALPN_h1
|
||||
#ifdef USE_NGHTTP2
|
||||
| ALPN_h2
|
||||
#endif
|
||||
#ifdef ENABLE_QUIC
|
||||
| ALPN_h3
|
||||
#endif
|
||||
) & data->asi->flags;
|
||||
|
||||
host = conn->host.rawalloc;
|
||||
#ifdef USE_NGHTTP2
|
||||
/* with h2 support, check that first */
|
||||
salpnid = ALPN_h2;
|
||||
srcalpnid = ALPN_h2;
|
||||
hit = Curl_altsvc_lookup(data->asi,
|
||||
salpnid, host, conn->remote_port, /* from */
|
||||
&nalpnid, &nhost, &nport /* to */);
|
||||
srcalpnid, host, conn->remote_port, /* from */
|
||||
&as /* to */,
|
||||
allowed_versions);
|
||||
if(!hit)
|
||||
#endif
|
||||
{
|
||||
salpnid = ALPN_h1;
|
||||
srcalpnid = ALPN_h1;
|
||||
hit = Curl_altsvc_lookup(data->asi,
|
||||
salpnid, host, conn->remote_port, /* from */
|
||||
&nalpnid, &nhost, &nport /* to */);
|
||||
srcalpnid, host, conn->remote_port, /* from */
|
||||
&as /* to */,
|
||||
allowed_versions);
|
||||
}
|
||||
if(hit) {
|
||||
char *hostd = strdup((char *)nhost);
|
||||
char *hostd = strdup((char *)as->dst.host);
|
||||
if(!hostd)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
conn->conn_to_host.rawalloc = hostd;
|
||||
conn->conn_to_host.name = hostd;
|
||||
conn->bits.conn_to_host = TRUE;
|
||||
conn->conn_to_port = nport;
|
||||
conn->conn_to_port = as->dst.port;
|
||||
conn->bits.conn_to_port = TRUE;
|
||||
conn->bits.altused = TRUE;
|
||||
infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n",
|
||||
Curl_alpnid2str(salpnid), host, conn->remote_port,
|
||||
Curl_alpnid2str(nalpnid), hostd, nport);
|
||||
if(salpnid != nalpnid) {
|
||||
Curl_alpnid2str(srcalpnid), host, conn->remote_port,
|
||||
Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
|
||||
if(srcalpnid != as->dst.alpnid) {
|
||||
/* protocol version switch */
|
||||
switch(nalpnid) {
|
||||
switch(as->dst.alpnid) {
|
||||
case ALPN_h1:
|
||||
conn->httpversion = 11;
|
||||
break;
|
||||
|
@ -32,7 +32,7 @@ unit1654
|
||||
<file name="log/1654" mode="text">
|
||||
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
|
||||
# a comment
|
||||
h2c example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 1
|
||||
h2 foo.example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 1
|
||||
h1 example.com 443 h3 shiny.example.com 8443 "20121231 00:00:01" 0 1
|
||||
h3 example.com 443 h3 shiny.example.com 8443 "20131231 00:00:00" 0 1
|
||||
# also a comment
|
||||
@ -45,14 +45,14 @@ rubbish
|
||||
# Your alt-svc cache. https://curl.haxx.se/docs/alt-svc.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
|
||||
h2c example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 1
|
||||
h2 foo.example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 1
|
||||
h1 example.com 443 h3 shiny.example.com 8443 "20121231 00:00:01" 0 1
|
||||
h3 example.com 443 h3 shiny.example.com 8443 "20131231 00:00:00" 0 1
|
||||
h1 example.org 8080 h2 example.com 8080 "20190125 22:34:21" 0 0
|
||||
h1 2.example.org 8080 h3 2.example.org 8080 "20190125 22:34:21" 0 0
|
||||
h1 3.example.org 8080 h2 example.com 8080 "20190125 22:34:21" 0 0
|
||||
h1 3.example.org 8080 h3 yesyes.com 8080 "20190125 22:34:21" 0 0
|
||||
h2c example.org 80 h2 example.com 443 "20190124 22:36:21" 0 0
|
||||
h2 example.org 80 h2 example.com 443 "20190124 22:36:21" 0 0
|
||||
</file>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
@ -90,7 +90,7 @@ UNITTEST_START
|
||||
fail_unless(asi->num == 8, "wrong number of entries");
|
||||
|
||||
result = Curl_altsvc_parse(curl, asi, "h2=\"example.com:443\"; ma = 120;",
|
||||
ALPN_h2c, "example.org", 80);
|
||||
ALPN_h2, "example.org", 80);
|
||||
if(result) {
|
||||
fprintf(stderr, "Curl_altsvc_parse(4) failed!\n");
|
||||
unitfail++;
|
||||
|
Loading…
Reference in New Issue
Block a user