gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]