summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/vquic/vquic.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/vquic/vquic.c')
-rw-r--r--libs/libcurl/src/vquic/vquic.c141
1 files changed, 65 insertions, 76 deletions
diff --git a/libs/libcurl/src/vquic/vquic.c b/libs/libcurl/src/vquic/vquic.c
index 960c710170..4b7ab97c5b 100644
--- a/libs/libcurl/src/vquic/vquic.c
+++ b/libs/libcurl/src/vquic/vquic.c
@@ -22,7 +22,7 @@
*
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef HAVE_NETINET_UDP_H
#include <netinet/udp.h>
@@ -30,39 +30,44 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#include "urldata.h"
-#include "bufq.h"
-#include "dynbuf.h"
-#include "cfilters.h"
-#include "curl_trc.h"
+#include "../urldata.h"
+#include "../bufq.h"
+#include "../curlx/dynbuf.h"
+#include "../cfilters.h"
+#include "../curl_trc.h"
#include "curl_msh3.h"
#include "curl_ngtcp2.h"
#include "curl_osslq.h"
#include "curl_quiche.h"
-#include "multiif.h"
-#include "rand.h"
+#include "../multiif.h"
+#include "../rand.h"
#include "vquic.h"
#include "vquic_int.h"
-#include "strerror.h"
+#include "../strerror.h"
+#include "../curlx/strparse.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#ifdef USE_HTTP3
-#ifdef O_BINARY
-#define QLOGMODE O_WRONLY|O_CREAT|O_BINARY
-#else
-#define QLOGMODE O_WRONLY|O_CREAT
-#endif
-
#define NW_CHUNK_SIZE (64 * 1024)
#define NW_SEND_CHUNKS 2
+int Curl_vquic_init(void)
+{
+#if defined(USE_NGTCP2) && defined(OPENSSL_QUIC_API2)
+ if(ngtcp2_crypto_ossl_init())
+ return 0;
+#endif
+
+ return 1;
+}
+
void Curl_quic_ver(char *p, size_t len)
{
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
@@ -87,10 +92,10 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx)
#endif
#ifdef DEBUGBUILD
{
- char *p = getenv("CURL_DBG_QUIC_WBLOCK");
+ const char *p = getenv("CURL_DBG_QUIC_WBLOCK");
if(p) {
- long l = strtol(p, NULL, 10);
- if(l >= 0 && l <= 100)
+ curl_off_t l;
+ if(!curlx_str_number(&p, &l, 100))
qctx->wblock_percent = (int)l;
}
}
@@ -107,7 +112,7 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx)
void vquic_ctx_update_time(struct cf_quic_ctx *qctx)
{
- qctx->last_op = Curl_now();
+ qctx->last_op = curlx_now();
}
static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
@@ -132,7 +137,7 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf,
#endif
*psent = 0;
- msg_iov.iov_base = (uint8_t *)pkt;
+ msg_iov.iov_base = (uint8_t *)CURL_UNCONST(pkt);
msg_iov.iov_len = pktlen;
msg.msg_iov = &msg_iov;
msg.msg_iovlen = 1;
@@ -153,23 +158,24 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf,
#endif
- while((sent = sendmsg(qctx->sockfd, &msg, 0)) == -1 && SOCKERRNO == EINTR)
+ while((sent = sendmsg(qctx->sockfd, &msg, 0)) == -1 &&
+ SOCKERRNO == SOCKEINTR)
;
if(sent == -1) {
switch(SOCKERRNO) {
case EAGAIN:
-#if EAGAIN != EWOULDBLOCK
- case EWOULDBLOCK:
+#if EAGAIN != SOCKEWOULDBLOCK
+ case SOCKEWOULDBLOCK:
#endif
return CURLE_AGAIN;
- case EMSGSIZE:
+ case SOCKEMSGSIZE:
/* UDP datagram is too large; caused by PMTUD. Just let it be lost. */
break;
case EIO:
if(pktlen > gsolen) {
/* GSO failure */
- failf(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
+ infof(data, "sendmsg() returned %zd (errno %d); disable GSO", sent,
SOCKERRNO);
qctx->no_gso = TRUE;
return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent);
@@ -191,16 +197,16 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf,
while((sent = send(qctx->sockfd,
(const char *)pkt, (SEND_TYPE_ARG3)pktlen, 0)) == -1 &&
- SOCKERRNO == EINTR)
+ SOCKERRNO == SOCKEINTR)
;
if(sent == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == SOCKEWOULDBLOCK) {
return CURLE_AGAIN;
}
else {
failf(data, "send() returned %zd (errno %d)", sent, SOCKERRNO);
- if(SOCKERRNO != EMSGSIZE) {
+ if(SOCKERRNO != SOCKEMSGSIZE) {
return CURLE_SEND_ERROR;
}
/* UDP datagram is too large; caused by PMTUD. Just let it be
@@ -248,6 +254,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
/* simulate network blocking/partial writes */
if(qctx->wblock_percent > 0) {
unsigned char c;
+ *psent = 0;
Curl_rand(data, &c, 1);
if(c >= ((100-qctx->wblock_percent)*256/100)) {
CURL_TRC_CF(data, cf, "vquic_flush() simulate EWOULDBLOCK");
@@ -363,7 +370,7 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
struct mmsghdr mmsg[MMSG_NUM];
uint8_t msg_ctrl[MMSG_NUM * CMSG_SPACE(sizeof(int))];
struct sockaddr_storage remote_addr[MMSG_NUM];
- size_t total_nread = 0, pkts;
+ size_t total_nread = 0, pkts = 0;
int mcount, i, n;
char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
@@ -380,10 +387,9 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
goto out;
bufs = (uint8_t (*)[64*1024])sockbuf;
- pkts = 0;
total_nread = 0;
while(pkts < max_pkts) {
- n = (int)CURLMIN(MMSG_NUM, max_pkts);
+ n = (int)CURLMIN(CURLMIN(MMSG_NUM, IOV_MAX), max_pkts);
memset(&mmsg, 0, sizeof(mmsg));
for(i = 0; i < n; ++i) {
msg_iov[i].iov_base = bufs[i];
@@ -397,14 +403,14 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
}
while((mcount = recvmmsg(qctx->sockfd, mmsg, n, 0, NULL)) == -1 &&
- SOCKERRNO == EINTR)
+ SOCKERRNO == SOCKEINTR)
;
if(mcount == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == SOCKEWOULDBLOCK) {
CURL_TRC_CF(data, cf, "ingress, recvmmsg -> EAGAIN");
goto out;
}
- if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
+ if(!cf->connected && SOCKERRNO == SOCKECONNREFUSED) {
struct ip_quadruple ip;
Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
failf(data, "QUIC: connection to %s port %u refused",
@@ -475,27 +481,28 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
size_t pktlen;
size_t offset, to;
- msg_iov.iov_base = buf;
- msg_iov.iov_len = (int)sizeof(buf);
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = &msg_iov;
- msg.msg_iovlen = 1;
- msg.msg_control = msg_ctrl;
-
DEBUGASSERT(max_pkts > 0);
for(pkts = 0, total_nread = 0; pkts < max_pkts;) {
+ /* fully initialise this on each call to `recvmsg()`. There seem to
+ * operating systems out there that mess with `msg_iov.iov_len`. */
+ memset(&msg, 0, sizeof(msg));
+ msg_iov.iov_base = buf;
+ msg_iov.iov_len = (int)sizeof(buf);
+ msg.msg_iov = &msg_iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = msg_ctrl;
msg.msg_name = &remote_addr;
msg.msg_namelen = sizeof(remote_addr);
msg.msg_controllen = sizeof(msg_ctrl);
+
while((nread = recvmsg(qctx->sockfd, &msg, 0)) == -1 &&
- SOCKERRNO == EINTR)
+ SOCKERRNO == SOCKEINTR)
;
if(nread == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == SOCKEWOULDBLOCK) {
goto out;
}
- if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
+ if(!cf->connected && SOCKERRNO == SOCKECONNREFUSED) {
struct ip_quadruple ip;
Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
failf(data, "QUIC: connection to %s port %u refused",
@@ -563,14 +570,14 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
while((nread = recvfrom(qctx->sockfd, (char *)buf, bufsize, 0,
(struct sockaddr *)&remote_addr,
&remote_addrlen)) == -1 &&
- SOCKERRNO == EINTR)
+ SOCKERRNO == SOCKEINTR)
;
if(nread == -1) {
- if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
+ if(SOCKERRNO == EAGAIN || SOCKERRNO == SOCKEWOULDBLOCK) {
CURL_TRC_CF(data, cf, "ingress, recvfrom -> EAGAIN");
goto out;
}
- if(!cf->connected && SOCKERRNO == ECONNREFUSED) {
+ if(!cf->connected && SOCKERRNO == SOCKECONNREFUSED) {
struct ip_quadruple ip;
Curl_cf_socket_peek(cf->next, data, NULL, NULL, &ip);
failf(data, "QUIC: connection to %s port %u refused",
@@ -644,25 +651,25 @@ CURLcode Curl_qlogdir(struct Curl_easy *data,
struct dynbuf fname;
CURLcode result;
unsigned int i;
- Curl_dyn_init(&fname, DYN_QLOG_NAME);
- result = Curl_dyn_add(&fname, qlog_dir);
+ curlx_dyn_init(&fname, DYN_QLOG_NAME);
+ result = curlx_dyn_add(&fname, qlog_dir);
if(!result)
- result = Curl_dyn_add(&fname, "/");
+ result = curlx_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);
+ result = curlx_dyn_add(&fname, hex);
}
if(!result)
- result = Curl_dyn_add(&fname, ".sqlog");
+ result = curlx_dyn_add(&fname, ".sqlog");
if(!result) {
- int qlogfd = open(Curl_dyn_ptr(&fname), QLOGMODE,
+ int qlogfd = open(curlx_dyn_ptr(&fname), O_WRONLY|O_CREAT|CURL_O_BINARY,
data->set.new_file_perms);
if(qlogfd != -1)
*qlogfdp = qlogfd;
}
- Curl_dyn_free(&fname);
+ curlx_dyn_free(&fname);
if(result)
return result;
}
@@ -695,24 +702,6 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
#endif
}
-bool Curl_conn_is_http3(const struct Curl_easy *data,
- const struct connectdata *conn,
- int sockindex)
-{
-#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
- return Curl_conn_is_ngtcp2(data, conn, sockindex);
-#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
- return Curl_conn_is_osslq(data, conn, sockindex);
-#elif defined(USE_QUICHE)
- return Curl_conn_is_quiche(data, conn, sockindex);
-#elif defined(USE_MSH3)
- return Curl_conn_is_msh3(data, conn, sockindex);
-#else
- return ((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
- (conn->httpversion == 30));
-#endif
-}
-
CURLcode Curl_conn_may_http3(struct Curl_easy *data,
const struct connectdata *conn)
{