From 14c17a2b6e0c377c16db43d0e963a31db597ece5 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 7 May 2020 14:17:42 +0200 Subject: ngtcp2: introduce qlog support 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 | 4 +-- lib/vquic/ngtcp2.c | 32 ++++++++++++++++++-- lib/vquic/ngtcp2.h | 1 + lib/vquic/quiche.c | 42 ++++----------------------- lib/vquic/vquic.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/vquic/vquic.h | 34 ++++++++++++++++++++++ 6 files changed, 157 insertions(+), 41 deletions(-) create mode 100644 lib/vquic/vquic.c create mode 100644 lib/vquic/vquic.h (limited to 'lib') diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 12b2d7aa6..08b0f73a3 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -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 diff --git a/lib/vquic/ngtcp2.c b/lib/vquic/ngtcp2.c index 8cec432a4..66c5002b2 100644 --- a/lib/vquic/ngtcp2.c +++ b/lib/vquic/ngtcp2.c @@ -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); diff --git a/lib/vquic/ngtcp2.h b/lib/vquic/ngtcp2.h index 06337f6f9..e2f8b5600 100644 --- a/lib/vquic/ngtcp2.h +++ b/lib/vquic/ngtcp2.h @@ -63,6 +63,7 @@ struct quicsocket { nghttp3_conn *h3conn; nghttp3_conn_settings h3settings; + int qlogfd; }; #include "urldata.h" diff --git a/lib/vquic/quiche.c b/lib/vquic/quiche.c index 38c0a0a3f..45c39925f 100644 --- a/lib/vquic/quiche.c +++ b/lib/vquic/quiche.c @@ -34,10 +34,7 @@ #include "multiif.h" #include "connect.h" #include "strerror.h" -#include "dynbuf.h" -#ifdef HAVE_FCNTL_H -#include -#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 index 000000000..aae8e0951 --- /dev/null +++ b/lib/vquic/vquic.c @@ -0,0 +1,85 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , 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 +#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 index 000000000..ecff0edf4 --- /dev/null +++ b/lib/vquic/vquic.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_VQUIC_QUIC_H +#define HEADER_CURL_VQUIC_QUIC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2020, Daniel Stenberg, , 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 */ -- cgit v1.2.3