aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2019-08-07 20:10:27 +0200
committerDaniel Stenberg <daniel@haxx.se>2019-08-08 09:10:29 +0200
commit69b3ff5118be4eb6fdd9ef645b955cac7d2fe0ba (patch)
treeb4bf92f3a9437194236f19cbc1eaeb80ba82fe22
parenta93b43cde82d7a48014990d6a31dc917c1b5f93c (diff)
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
-rw-r--r--lib/altsvc.c57
-rw-r--r--lib/altsvc.h27
-rw-r--r--lib/url.c41
-rw-r--r--tests/data/test16546
-rw-r--r--tests/unit/unit1654.c2
5 files changed, 69 insertions, 64 deletions
diff --git a/lib/altsvc.c b/lib/altsvc.c
index b20ec13ae..abea66c69 100644
--- a/lib/altsvc.c
+++ b/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;
}
}
diff --git a/lib/altsvc.h b/lib/altsvc.h
index eefb45bf6..99d0499af 100644
--- a/lib/altsvc.h
+++ b/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)
diff --git a/lib/url.c b/lib/url.c
index 0b681803d..30263258f 100644
--- a/lib/url.c
+++ b/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;
diff --git a/tests/data/test1654 b/tests/data/test1654
index 175076c8a..5b32cb419 100644
--- a/tests/data/test1654
+++ b/tests/data/test1654
@@ -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>
diff --git a/tests/unit/unit1654.c b/tests/unit/unit1654.c
index 9d1a3e211..51fc5d16f 100644
--- a/tests/unit/unit1654.c
+++ b/tests/unit/unit1654.c
@@ -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++;