[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [gnurl] 95/220: http3: make connection reuse work
From: |
gnunet |
Subject: |
[GNUnet-SVN] [gnurl] 95/220: http3: make connection reuse work |
Date: |
Thu, 12 Sep 2019 17:27:35 +0200 |
This is an automated email from the git hooks/post-receive script.
ng0 pushed a commit to branch master
in repository gnurl.
commit db061571ef4b7a925da1c189b60c08b39e6b2dbf
Author: Daniel Stenberg <address@hidden>
AuthorDate: Thu Aug 8 23:13:57 2019 +0200
http3: make connection reuse work
Closes #4204
---
lib/connect.c | 18 ++++------
lib/connect.h | 2 ++
lib/http.h | 1 +
lib/vquic/quiche.c | 95 ++++++++++++++++++++++++++++++++++++++-------------
tests/unit/unit1607.c | 8 ++---
tests/unit/unit1609.c | 10 ++----
6 files changed, 87 insertions(+), 47 deletions(-)
diff --git a/lib/connect.c b/lib/connect.c
index be9fcba66..7d823d23b 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -626,13 +626,9 @@ void Curl_persistconninfo(struct connectdata *conn)
conn->data->info.conn_local_port = conn->local_port;
}
-UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
- long *port);
-
/* retrieves ip address and port from a sockaddr structure.
note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-UNITTEST bool getaddressinfo(struct sockaddr *sa, char *addr,
- long *port)
+bool Curl_addr2string(struct sockaddr *sa, char *addr, long *port)
{
struct sockaddr_in *si = NULL;
#ifdef ENABLE_IPV6
@@ -715,8 +711,8 @@ void Curl_updateconninfo(struct connectdata *conn,
curl_socket_t sockfd)
}
#endif
#ifdef HAVE_GETPEERNAME
- if(!getaddressinfo((struct sockaddr*)&ssrem,
- conn->primary_ip, &conn->primary_port)) {
+ if(!Curl_addr2string((struct sockaddr*)&ssrem,
+ conn->primary_ip, &conn->primary_port)) {
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return;
@@ -724,8 +720,8 @@ void Curl_updateconninfo(struct connectdata *conn,
curl_socket_t sockfd)
memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
#endif
#ifdef HAVE_GETSOCKNAME
- if(!getaddressinfo((struct sockaddr*)&ssloc,
- conn->local_ip, &conn->local_port)) {
+ if(!Curl_addr2string((struct sockaddr*)&ssloc,
+ conn->local_ip, &conn->local_port)) {
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return;
@@ -1032,8 +1028,8 @@ static CURLcode singleipconnect(struct connectdata *conn,
return CURLE_OK;
/* store remote address and port used in this connection attempt */
- if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
- ipaddress, &port)) {
+ if(!Curl_addr2string((struct sockaddr*)&addr.sa_addr,
+ ipaddress, &port)) {
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
diff --git a/lib/connect.h b/lib/connect.h
index 6a5c755cc..e44c4a701 100644
--- a/lib/connect.h
+++ b/lib/connect.h
@@ -51,6 +51,8 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
struct connectdata **connp);
+bool Curl_addr2string(struct sockaddr *sa, char *addr, long *port);
+
/*
* Check if a connection seems to be alive.
*/
diff --git a/lib/http.h b/lib/http.h
index f6f5d4fd5..c27725d2a 100644
--- a/lib/http.h
+++ b/lib/http.h
@@ -193,6 +193,7 @@ struct HTTP {
/*********** for HTTP/3 we store stream-local data here *************/
int64_t stream3_id; /* stream we are interested in */
bool firstbody; /* FALSE until body arrives */
+ bool h3req; /* FALSE until request is issued */
#endif
};
diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c
index 369d819f6..386d83352 100644
--- a/lib/vquic/quiche.c
+++ b/lib/vquic/quiche.c
@@ -32,13 +32,15 @@
#include "quic.h"
#include "strcase.h"
#include "multiif.h"
+#include "connect.h"
+#include "strerror.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
-/* #define DEBUG_HTTP3 */
+#define DEBUG_HTTP3
/* #define DEBUG_QUICHE */
#ifdef DEBUG_HTTP3
#define H3BUGF(x) x
@@ -105,10 +107,17 @@ static unsigned int quiche_conncheck(struct connectdata
*conn,
return CONNRESULT_NONE;
}
+static CURLcode quiche_do(struct connectdata *conn, bool *done)
+{
+ struct HTTP *stream = conn->data->req.protop;
+ stream->h3req = FALSE; /* not sent */
+ return Curl_http(conn, done);
+}
+
static const struct Curl_handler Curl_handler_h3_quiche = {
"HTTPS", /* scheme */
ZERO_NULL, /* setup_connection */
- Curl_http, /* do_it */
+ quiche_do, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
@@ -131,12 +140,13 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
curl_socket_t sockfd,
{
CURLcode result;
struct quicsocket *qs = &conn->quic;
+ struct Curl_easy *data = conn->data;
(void)addr;
(void)addrlen;
qs->cfg = quiche_config_new(QUICHE_PROTOCOL_VERSION);
if(!qs->cfg) {
- failf(conn->data, "can't create quiche config");
+ failf(data, "can't create quiche config");
return CURLE_FAILED_INIT;
}
@@ -154,7 +164,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
curl_socket_t sockfd,
sizeof(QUICHE_H3_APPLICATION_PROTOCOL)
- 1);
- result = Curl_rand(conn->data, qs->scid, sizeof(qs->scid));
+ result = Curl_rand(data, qs->scid, sizeof(qs->scid));
if(result)
return result;
@@ -164,7 +174,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
curl_socket_t sockfd,
qs->conn = quiche_connect(conn->host.name, (const uint8_t *) qs->scid,
sizeof(qs->scid), qs->cfg);
if(!qs->conn) {
- failf(conn->data, "can't create quiche connection");
+ failf(data, "can't create quiche connection");
return CURLE_OUT_OF_MEMORY;
}
@@ -172,12 +182,56 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
curl_socket_t sockfd,
if(result)
return result;
- infof(conn->data, "Sent QUIC client Initial, ALPN: %s\n",
+ /* store the used address as a string */
+ if(!Curl_addr2string((struct sockaddr*)addr,
+ conn->primary_ip, &conn->primary_port)) {
+ char buffer[STRERROR_LEN];
+ failf(data, "ssrem inet_ntop() failed with errno %d: %s",
+ errno, Curl_strerror(errno, buffer, sizeof(buffer)));
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ }
+ memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
+
+ /* for connection reuse purposes: */
+ conn->ssl[FIRSTSOCKET].state = ssl_connection_complete;
+
+ infof(data, "Sent QUIC client Initial, ALPN: %s\n",
QUICHE_H3_APPLICATION_PROTOCOL + 1);
return CURLE_OK;
}
+static CURLcode quiche_has_connected(struct connectdata *conn,
+ int sockindex)
+{
+ CURLcode result;
+ struct quicsocket *qs = &conn->quic;
+
+ conn->recv[sockindex] = h3_stream_recv;
+ conn->send[sockindex] = h3_stream_send;
+ conn->handler = &Curl_handler_h3_quiche;
+ conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
+ conn->httpversion = 30;
+ conn->bundle->multiuse = BUNDLE_MULTIPLEX;
+
+ qs->h3config = quiche_h3_config_new(0, 1024, 0, 0);
+ if(!qs->h3config)
+ return CURLE_OUT_OF_MEMORY;
+
+ /* Create a new HTTP/3 connection on the QUIC connection. */
+ qs->h3c = quiche_h3_conn_new_with_transport(qs->conn, qs->h3config);
+ if(!qs->h3c) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
+ return CURLE_OK;
+ fail:
+ quiche_h3_config_free(qs->h3config);
+ quiche_h3_conn_free(qs->h3c);
+ return result;
+}
+
+
CURLcode Curl_quic_is_connected(struct connectdata *conn, int sockindex,
bool *done)
{
@@ -194,14 +248,12 @@ CURLcode Curl_quic_is_connected(struct connectdata *conn,
int sockindex,
return result;
if(quiche_conn_is_established(qs->conn)) {
- conn->recv[sockindex] = h3_stream_recv;
- conn->send[sockindex] = h3_stream_send;
*done = TRUE;
- conn->handler = &Curl_handler_h3_quiche;
+ result = quiche_has_connected(conn, sockindex);
DEBUGF(infof(conn->data, "quiche established connection!\n"));
}
- return CURLE_OK;
+ return result;
}
static CURLcode process_ingress(struct connectdata *conn, int sockfd)
@@ -336,6 +388,13 @@ static ssize_t h3_stream_recv(struct connectdata *conn,
/* nothing more to do */
break;
+ if(s != stream->stream3_id) {
+ /* another transfer, ignore for now */
+ infof(conn->data, "Got h3 for stream %u, expects %u\n",
+ s, stream->stream3_id);
+ continue;
+ }
+
switch(quiche_h3_event_type(ev)) {
case QUICHE_H3_EVENT_HEADERS:
H3BUGF(infof(conn->data, "quiche says HEADERS\n"));
@@ -399,8 +458,9 @@ static ssize_t h3_stream_send(struct connectdata *conn,
ssize_t sent;
struct quicsocket *qs = &conn->quic;
curl_socket_t sockfd = conn->sock[sockindex];
+ struct HTTP *stream = conn->data->req.protop;
- if(!qs->h3c) {
+ if(!stream->h3req) {
CURLcode result = http_request(conn, mem, len);
if(result) {
*curlcode = CURLE_SEND_ERROR;
@@ -467,16 +527,7 @@ static CURLcode http_request(struct connectdata *conn,
const void *mem,
quiche_enable_debug_logging(debug_log, NULL);
#endif
- qs->h3config = quiche_h3_config_new(0, 1024, 0, 0);
- if(!qs->h3config)
- return CURLE_OUT_OF_MEMORY;
-
- /* Create a new HTTP/3 connection on the QUIC connection. */
- qs->h3c = quiche_h3_conn_new_with_transport(qs->conn, qs->h3config);
- if(!qs->h3c) {
- result = CURLE_OUT_OF_MEMORY;
- goto fail;
- }
+ stream->h3req = TRUE; /* senf off! */
/* Calculate number of headers contained in [mem, mem + len). Assumes a
correctly generated HTTP header field block. */
@@ -678,8 +729,6 @@ static CURLcode http_request(struct connectdata *conn,
const void *mem,
return CURLE_OK;
fail:
- quiche_h3_config_free(qs->h3config);
- quiche_h3_conn_free(qs->h3c);
free(nva);
return result;
}
diff --git a/tests/unit/unit1607.c b/tests/unit/unit1607.c
index 6e40be707..458604229 100644
--- a/tests/unit/unit1607.c
+++ b/tests/unit/unit1607.c
@@ -25,10 +25,6 @@
#include "connect.h"
#include "share.h"
-/* retrieves ip address and port from a sockaddr structure.
- note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-bool getaddressinfo(struct sockaddr *sa, char *addr, long *port);
-
#include "memdebug.h" /* LAST include file */
static void unit_stop(void)
@@ -154,8 +150,8 @@ UNITTEST_START
if(tests[i].address[j] == &skip)
continue;
- if(addr && !getaddressinfo(addr->ai_addr,
- ipaddress, &port)) {
+ if(addr && !Curl_addr2string(addr->ai_addr,
+ ipaddress, &port)) {
fprintf(stderr, "%s:%d tests[%d] failed. getaddressinfo failed.\n",
__FILE__, __LINE__, i);
problem = true;
diff --git a/tests/unit/unit1609.c b/tests/unit/unit1609.c
index 8d9bc6526..d919c9ea9 100644
--- a/tests/unit/unit1609.c
+++ b/tests/unit/unit1609.c
@@ -25,10 +25,6 @@
#include "connect.h"
#include "share.h"
-/* retrieves ip address and port from a sockaddr structure.
- note it calls Curl_inet_ntop which sets errno on fail, not SOCKERRNO. */
-bool getaddressinfo(struct sockaddr *sa, char *addr, long *port);
-
#include "memdebug.h" /* LAST include file */
static void unit_stop(void)
@@ -154,9 +150,9 @@ UNITTEST_START
if(!addr && !tests[i].address[j])
break;
- if(addr && !getaddressinfo(addr->ai_addr,
- ipaddress, &port)) {
- fprintf(stderr, "%s:%d tests[%d] failed. getaddressinfo failed.\n",
+ if(addr && !Curl_addr2string(addr->ai_addr,
+ ipaddress, &port)) {
+ fprintf(stderr, "%s:%d tests[%d] failed. Curl_addr2string failed.\n",
__FILE__, __LINE__, i);
problem = true;
break;
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [GNUnet-SVN] [gnurl] 69/220: docs/HTTP3: refreshed as it is now in master and HTTP/3 can be tested, (continued)
- [GNUnet-SVN] [gnurl] 69/220: docs/HTTP3: refreshed as it is now in master and HTTP/3 can be tested, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 78/220: quiche: make POSTFIELDS posts work, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 77/220: quiche: improved error handling and memory cleanups, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 67/220: curl_multi_poll: a sister to curl_multi_wait() that waits more, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 70/220: sasl: Implement SASL authorisation identity via CURLOPT_SASL_AUTHZID, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 71/220: curl: --sasl-authzid added to support CURLOPT_SASL_AUTHZID from the tool, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 99/220: curl_global_init_mem.3: mention it was added in 7.12.0, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 93/220: cleanup: s/curl_debug/curl_dbg_debug in comments and docs, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 94/220: quiche: add SSLKEYLOGFILE support, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 103/220: asyn-thread: issue CURL_POLL_REMOVE before closing socket, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 95/220: http3: make connection reuse work,
gnunet <=
- [GNUnet-SVN] [gnurl] 105/220: nghttp3: initial h3 template code added, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 109/220: HTTP3: use ngtcp2's draft-22 branch, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 112/220: altsvc: make it use h3-22 with ngtcp2 as well, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 115/220: lib/quic.c: unused - removed, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 123/220: curl_version: bump string buffer size to 250, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 117/220: quic.h: remove unused proto, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 81/220: curl: have -w's 'http_version' show '3' for HTTP/3, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 118/220: nss: use TLSv1.3 as default if supported, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 100/220: ngtcp2: use ngtcp2_settings_default and specify initial_ts, gnunet, 2019/09/12
- [GNUnet-SVN] [gnurl] 101/220: ngtcp2: Send ALPN h3-22, gnunet, 2019/09/12