]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
ngtcp2: introduce qlog support
authorDaniel Stenberg <daniel@haxx.se>
Thu, 7 May 2020 12:17:42 +0000 (14:17 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 7 May 2020 14:27:49 +0000 (16:27 +0200)
If the QLOGDIR environment variable is set, enable qlogging.

... and create Curl_qlogdir() in the new generic vquic/vquic.c file for
QUIC functions that are backend independent.

Closes #5353

lib/Makefile.inc
lib/vquic/ngtcp2.c
lib/vquic/ngtcp2.h
lib/vquic/quiche.c
lib/vquic/vquic.c [new file with mode: 0644]
lib/vquic/vquic.h [new file with mode: 0644]

index 12b2d7aa6044a28fcd5546eb595ed78cdc78d7b2..08b0f73a38aeadb7722c4ebc021423c015a44fe1 100644 (file)
@@ -36,9 +36,9 @@ LIB_VTLS_HFILES = vtls/bearssl.h vtls/gskit.h vtls/gtls.h vtls/mbedtls.h \
   vtls/mbedtls_threadlock.h vtls/mesalink.h vtls/nssg.h vtls/openssl.h   \
   vtls/schannel.h vtls/sectransp.h vtls/vtls.h vtls/wolfssl.h
 
-LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c
+LIB_VQUIC_CFILES = vquic/ngtcp2.c vquic/quiche.c vquic/vquic.c
 
-LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h
+LIB_VQUIC_HFILES = vquic/ngtcp2.h vquic/quiche.h vquic/vquic.h
 
 LIB_VSSH_CFILES = vssh/libssh.c vssh/libssh2.c vssh/wolfssh.c
 
index 8cec432a47a9097f152f92c1107dc5f9ab0bd639..66c5002b2297ef00b806a433ab207a4fc269903a 100644 (file)
@@ -39,6 +39,7 @@
 #include "connect.h"
 #include "strerror.h"
 #include "dynbuf.h"
+#include "vquic.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -160,9 +161,25 @@ static int setup_initial_crypto_context(struct quicsocket *qs)
   return 0;
 }
 
-static void quic_settings(ngtcp2_settings *s,
-                          uint64_t stream_buffer_size)
+static void qlog_callback(void *user_data, const void *data, size_t datalen)
 {
+  struct quicsocket *qs = (struct quicsocket *)user_data;
+  if(qs->qlogfd != -1) {
+    ssize_t rc = write(qs->qlogfd, data, datalen);
+    if(rc == -1) {
+      /* on write error, stop further write attempts */
+      close(qs->qlogfd);
+      qs->qlogfd = -1;
+    }
+  }
+
+}
+
+static void quic_settings(struct quicsocket *qs,
+                          uint64_t stream_buffer_size,
+                          ngtcp2_cid *dcid)
+{
+  ngtcp2_settings *s = &qs->settings;
   ngtcp2_settings_default(s);
 #ifdef DEBUG_NGTCP2
   s->log_printf = quic_printf;
@@ -177,6 +194,10 @@ static void quic_settings(ngtcp2_settings *s,
   s->transport_params.initial_max_streams_bidi = 1;
   s->transport_params.initial_max_streams_uni = 3;
   s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT;
+  if(qs->qlogfd != -1) {
+    s->qlog.write = qlog_callback;
+    s->qlog.odcid = *dcid;
+  }
 }
 
 static FILE *keylog_file; /* not thread-safe */
@@ -825,6 +846,7 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
   struct quicsocket *qs = &conn->hequic[sockindex];
   char ipbuf[40];
   long port;
+  int qfd;
 #ifdef USE_OPENSSL
   uint8_t paramsbuf[64];
   ngtcp2_transport_params params;
@@ -864,7 +886,9 @@ CURLcode Curl_quic_connect(struct connectdata *conn,
   if(result)
     return result;
 
-  quic_settings(&qs->settings, data->set.buffer_size);
+  (void)Curl_qlogdir(data, qs->scid.data, NGTCP2_MAX_CIDLEN, &qfd);
+  qs->qlogfd = qfd; /* -1 if failure above */
+  quic_settings(qs, data->set.buffer_size, &qs->dcid);
 
   qs->local_addrlen = sizeof(qs->local_addr);
   rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr,
@@ -950,6 +974,8 @@ static CURLcode ng_disconnect(struct connectdata *conn,
   int i;
   struct quicsocket *qs = &conn->hequic[0];
   (void)dead_connection;
+  if(qs->qlogfd != -1)
+    close(qs->qlogfd);
   if(qs->ssl)
 #ifdef USE_OPENSSL
     SSL_free(qs->ssl);
index 06337f6f9fc7564845285555a2861a1ade9ed0c1..e2f8b56001602205336921e72adb257b6327a585 100644 (file)
@@ -63,6 +63,7 @@ struct quicsocket {
 
   nghttp3_conn *h3conn;
   nghttp3_conn_settings h3settings;
+  int qlogfd;
 };
 
 #include "urldata.h"
index 38c0a0a3f4cae63410d08edcea6c94e112234005..45c39925f511ef3f42d4113d766ce3faf77fd3e7 100644 (file)
 #include "multiif.h"
 #include "connect.h"
 #include "strerror.h"
-#include "dynbuf.h"
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
+#include "vquic.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
@@ -204,39 +201,12 @@ CURLcode Curl_quic_connect(struct connectdata *conn, curl_socket_t sockfd,
 
   /* Known to not work on Windows */
 #if !defined(WIN32) && defined(HAVE_QUICHE_CONN_SET_QLOG_FD)
-#ifdef O_BINARY
-#define QLOGMODE O_WRONLY|O_CREAT|O_BINARY
-#else
-#define QLOGMODE O_WRONLY|O_CREAT
-#endif
   {
-    const char *qlog_dir = getenv("QLOGDIR");
-    if(qlog_dir) {
-      struct dynbuf fname;
-      unsigned int i;
-      Curl_dyn_init(&fname, DYN_QLOG_NAME);
-      result = Curl_dyn_add(&fname, qlog_dir);
-      if(!result)
-        result = Curl_dyn_add(&fname, "/");
-      for(i = 0; (i < sizeof(qs->scid)) && !result; i++) {
-        char hex[3];
-        msnprintf(hex, 3, "%02x", qs->scid[i]);
-        result = Curl_dyn_add(&fname, hex);
-      }
-      if(!result)
-        result = Curl_dyn_add(&fname, ".qlog");
-
-      if(!result) {
-        int qlogfd = open(Curl_dyn_ptr(&fname), QLOGMODE,
-                          data->set.new_file_perms);
-        if(qlogfd != -1)
-          quiche_conn_set_qlog_fd(qs->conn, qlogfd,
-                                  "qlog title", "curl qlog");
-      }
-      Curl_dyn_free(&fname);
-      if(result)
-        return result;
-    }
+    int qfd;
+    (void)Curl_qlogdir(data, qs->scid, sizeof(qs->scid), &qfd);
+    if(qfd != -1)
+      quiche_conn_set_qlog_fd(qs->conn, qfd,
+                              "qlog title", "curl qlog");
   }
 #endif
 
diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c
new file mode 100644 (file)
index 0000000..aae8e09
--- /dev/null
@@ -0,0 +1,85 @@
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef ENABLE_QUIC
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include "urldata.h"
+#include "dynbuf.h"
+#include "curl_printf.h"
+#include "vquic.h"
+
+#ifdef O_BINARY
+#define QLOGMODE O_WRONLY|O_CREAT|O_BINARY
+#else
+#define QLOGMODE O_WRONLY|O_CREAT
+#endif
+
+/*
+ * If the QLOGDIR environment variable is set, open and return a file
+ * descriptor to write the log to.
+ *
+ * This function returns error if something failed outside of failing to
+ * create the file. Open file success is deemed by seeing if the returned fd
+ * is != -1.
+ */
+CURLcode Curl_qlogdir(struct Curl_easy *data,
+                      unsigned char *scid,
+                      size_t scidlen,
+                      int *qlogfdp)
+{
+  const char *qlog_dir = getenv("QLOGDIR");
+  *qlogfdp = -1;
+  if(qlog_dir) {
+    struct dynbuf fname;
+    CURLcode result;
+    unsigned int i;
+    Curl_dyn_init(&fname, DYN_QLOG_NAME);
+    result = Curl_dyn_add(&fname, qlog_dir);
+    if(!result)
+      result = Curl_dyn_add(&fname, "/");
+    for(i = 0; (i < scidlen) && !result; i++) {
+      char hex[3];
+      msnprintf(hex, 3, "%02x", scid[i]);
+      result = Curl_dyn_add(&fname, hex);
+    }
+    if(!result)
+      result = Curl_dyn_add(&fname, ".qlog");
+
+    if(!result) {
+      int qlogfd = open(Curl_dyn_ptr(&fname), QLOGMODE,
+                        data->set.new_file_perms);
+      if(qlogfd != -1)
+        *qlogfdp = qlogfd;
+    }
+    Curl_dyn_free(&fname);
+    if(result)
+      return result;
+  }
+
+  return CURLE_OK;
+}
+#endif
diff --git a/lib/vquic/vquic.h b/lib/vquic/vquic.h
new file mode 100644 (file)
index 0000000..ecff0ed
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef HEADER_CURL_VQUIC_QUIC_H
+#define HEADER_CURL_VQUIC_QUIC_H
+/***************************************************************************
+ *                                  _   _ ____  _
+ *  Project                     ___| | | |  _ \| |
+ *                             / __| | | | |_) | |
+ *                            | (__| |_| |  _ <| |___
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.haxx.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef ENABLE_QUIC
+CURLcode Curl_qlogdir(struct Curl_easy *data,
+                      unsigned char *scid,
+                      size_t scidlen,
+                      int *qlogfdp);
+#endif
+
+#endif /* HEADER_CURL_VQUIC_QUIC_H */