mirror of
https://github.com/curl/curl.git
synced 2025-01-30 14:22:33 +08:00
parent
411af83010
commit
a571afc02e
@ -35,6 +35,9 @@
|
||||
#elif defined(HAVE_NETINET_TCP_H)
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_UDP_H
|
||||
#include <netinet/udp.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
@ -1852,6 +1855,9 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
int rc;
|
||||
int one = 1;
|
||||
|
||||
(void)one;
|
||||
|
||||
/* QUIC needs a connected socket, nonblocking */
|
||||
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
|
||||
@ -1892,6 +1898,13 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(UDP_GRO) && (defined(HAVE_SENDMMSG) || defined(HAVE_SENDMSG)) && \
|
||||
((defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || defined(USE_QUICHE))
|
||||
(void)setsockopt(ctx->sock, IPPROTO_UDP, UDP_GRO, &one,
|
||||
(socklen_t)sizeof(one));
|
||||
#endif
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
uint16_t gso_size = 0;
|
||||
#ifdef 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 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:
|
||||
|
Loading…
Reference in New Issue
Block a user