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.c102
1 files changed, 90 insertions, 12 deletions
diff --git a/libs/libcurl/src/vquic/vquic.c b/libs/libcurl/src/vquic/vquic.c
index feff3395cc..13d9929ee2 100644
--- a/libs/libcurl/src/vquic/vquic.c
+++ b/libs/libcurl/src/vquic/vquic.c
@@ -36,6 +36,9 @@
#include "curl_setup.h"
+#ifdef HAVE_NETINET_UDP_H
+#include <netinet/udp.h>
+#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -329,6 +332,36 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
return vquic_flush(cf, data, qctx);
}
+#if defined(HAVE_SENDMMSG) || defined(HAVE_SENDMSG)
+static size_t msghdr_get_udp_gro(struct msghdr *msg)
+{
+ int gso_size = 0;
+#if defined(__linux__) && defined(UDP_GRO)
+ struct cmsghdr *cmsg;
+
+ /* Workaround musl CMSG_NXTHDR issue */
+#ifndef __GLIBC__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wsign-compare"
+#pragma clang diagnostic ignored "-Wcast-align"
+#endif
+ for(cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+#ifndef __GLIBC__
+#pragma clang diagnostic pop
+#endif
+ if(cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_GRO) {
+ memcpy(&gso_size, CMSG_DATA(cmsg), sizeof(gso_size));
+
+ break;
+ }
+ }
+#endif
+ (void)msg;
+
+ return (size_t)gso_size;
+}
+#endif
+
#ifdef HAVE_SENDMMSG
static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
struct Curl_easy *data,
@@ -339,12 +372,16 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
#define MMSG_NUM 64
struct iovec msg_iov[MMSG_NUM];
struct mmsghdr mmsg[MMSG_NUM];
+ uint8_t msg_ctrl[MMSG_NUM * CMSG_SPACE(sizeof(uint16_t))];
uint8_t bufs[MMSG_NUM][2*1024];
struct sockaddr_storage remote_addr[MMSG_NUM];
size_t total_nread, pkts;
int mcount, i, n;
char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
+ size_t gso_size;
+ size_t pktlen;
+ size_t offset, to;
DEBUGASSERT(max_pkts > 0);
pkts = 0;
@@ -359,6 +396,8 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
mmsg[i].msg_hdr.msg_iovlen = 1;
mmsg[i].msg_hdr.msg_name = &remote_addr[i];
mmsg[i].msg_hdr.msg_namelen = sizeof(remote_addr[i]);
+ mmsg[i].msg_hdr.msg_control = &msg_ctrl[i];
+ mmsg[i].msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t));
}
while((mcount = recvmmsg(qctx->sockfd, mmsg, n, 0, NULL)) == -1 &&
@@ -385,14 +424,30 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
}
CURL_TRC_CF(data, cf, "recvmmsg() -> %d packets", mcount);
- pkts += mcount;
for(i = 0; i < mcount; ++i) {
total_nread += mmsg[i].msg_len;
- result = recv_cb(bufs[i], mmsg[i].msg_len,
- mmsg[i].msg_hdr.msg_name, mmsg[i].msg_hdr.msg_namelen,
- 0, userp);
- if(result)
- goto out;
+
+ gso_size = msghdr_get_udp_gro(&mmsg[i].msg_hdr);
+ if(gso_size == 0) {
+ gso_size = mmsg[i].msg_len;
+ }
+
+ for(offset = 0; offset < mmsg[i].msg_len; offset = to) {
+ ++pkts;
+
+ to = offset + gso_size;
+ if(to > mmsg[i].msg_len) {
+ pktlen = mmsg[i].msg_len - offset;
+ }
+ else {
+ pktlen = gso_size;
+ }
+
+ result = recv_cb(bufs[i] + offset, pktlen, mmsg[i].msg_hdr.msg_name,
+ mmsg[i].msg_hdr.msg_namelen, 0, userp);
+ if(result)
+ goto out;
+ }
}
}
@@ -418,6 +473,10 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
ssize_t nread;
char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
+ uint8_t msg_ctrl[CMSG_SPACE(sizeof(uint16_t))];
+ size_t gso_size;
+ size_t pktlen;
+ size_t offset, to;
msg_iov.iov_base = buf;
msg_iov.iov_len = (int)sizeof(buf);
@@ -425,11 +484,13 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
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;) {
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)
;
@@ -452,12 +513,29 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
goto out;
}
- ++pkts;
total_nread += (size_t)nread;
- result = recv_cb(buf, (size_t)nread, msg.msg_name, msg.msg_namelen,
- 0, userp);
- if(result)
- goto out;
+
+ gso_size = msghdr_get_udp_gro(&msg);
+ if(gso_size == 0) {
+ gso_size = (size_t)nread;
+ }
+
+ for(offset = 0; offset < (size_t)nread; offset = to) {
+ ++pkts;
+
+ to = offset + gso_size;
+ if(to > (size_t)nread) {
+ pktlen = (size_t)nread - offset;
+ }
+ else {
+ pktlen = gso_size;
+ }
+
+ result =
+ recv_cb(buf + offset, pktlen, msg.msg_name, msg.msg_namelen, 0, userp);
+ if(result)
+ goto out;
+ }
}
out:
@@ -655,7 +733,7 @@ CURLcode Curl_conn_may_http3(struct Curl_easy *data,
return CURLE_URL_MALFORMAT;
}
if(conn->bits.httpproxy && conn->bits.tunnel_proxy) {
- failf(data, "HTTP/3 is not supported over a HTTP proxy");
+ failf(data, "HTTP/3 is not supported over an HTTP proxy");
return CURLE_URL_MALFORMAT;
}
#endif