mirror of
https://github.com/curl/curl.git
synced 2025-09-11 14:42:40 +03:00
parent
411af83010
commit
a571afc02e
|
@ -35,6 +35,9 @@
|
||||||
#elif defined(HAVE_NETINET_TCP_H)
|
#elif defined(HAVE_NETINET_TCP_H)
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_UDP_H
|
||||||
|
#include <netinet/udp.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_SYS_IOCTL_H
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1852,6 +1855,9 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||||
{
|
{
|
||||||
struct cf_socket_ctx *ctx = cf->ctx;
|
struct cf_socket_ctx *ctx = cf->ctx;
|
||||||
int rc;
|
int rc;
|
||||||
|
int one = 1;
|
||||||
|
|
||||||
|
(void)one;
|
||||||
|
|
||||||
/* QUIC needs a connected socket, nonblocking */
|
/* QUIC needs a connected socket, nonblocking */
|
||||||
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
|
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
|
||||||
|
@ -1892,6 +1898,13 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
|
|
||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_NETINET_UDP_H
|
||||||
|
#include <netinet/udp.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_FCNTL_H
|
#ifdef HAVE_FCNTL_H
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -329,6 +332,36 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||||
return vquic_flush(cf, data, qctx);
|
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
|
#ifdef HAVE_SENDMMSG
|
||||||
static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
|
static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
|
||||||
struct Curl_easy *data,
|
struct Curl_easy *data,
|
||||||
|
@ -339,12 +372,16 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
|
||||||
#define MMSG_NUM 64
|
#define MMSG_NUM 64
|
||||||
struct iovec msg_iov[MMSG_NUM];
|
struct iovec msg_iov[MMSG_NUM];
|
||||||
struct mmsghdr mmsg[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];
|
uint8_t bufs[MMSG_NUM][2*1024];
|
||||||
struct sockaddr_storage remote_addr[MMSG_NUM];
|
struct sockaddr_storage remote_addr[MMSG_NUM];
|
||||||
size_t total_nread, pkts;
|
size_t total_nread, pkts;
|
||||||
int mcount, i, n;
|
int mcount, i, n;
|
||||||
char errstr[STRERROR_LEN];
|
char errstr[STRERROR_LEN];
|
||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
|
size_t gso_size;
|
||||||
|
size_t pktlen;
|
||||||
|
size_t offset, to;
|
||||||
|
|
||||||
DEBUGASSERT(max_pkts > 0);
|
DEBUGASSERT(max_pkts > 0);
|
||||||
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_iovlen = 1;
|
||||||
mmsg[i].msg_hdr.msg_name = &remote_addr[i];
|
mmsg[i].msg_hdr.msg_name = &remote_addr[i];
|
||||||
mmsg[i].msg_hdr.msg_namelen = sizeof(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 &&
|
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);
|
CURL_TRC_CF(data, cf, "recvmmsg() -> %d packets", mcount);
|
||||||
pkts += mcount;
|
|
||||||
for(i = 0; i < mcount; ++i) {
|
for(i = 0; i < mcount; ++i) {
|
||||||
total_nread += mmsg[i].msg_len;
|
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,
|
gso_size = msghdr_get_udp_gro(&mmsg[i].msg_hdr);
|
||||||
0, userp);
|
if(gso_size == 0) {
|
||||||
if(result)
|
gso_size = mmsg[i].msg_len;
|
||||||
goto out;
|
}
|
||||||
|
|
||||||
|
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;
|
ssize_t nread;
|
||||||
char errstr[STRERROR_LEN];
|
char errstr[STRERROR_LEN];
|
||||||
CURLcode result = CURLE_OK;
|
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_base = buf;
|
||||||
msg_iov.iov_len = (int)sizeof(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));
|
memset(&msg, 0, sizeof(msg));
|
||||||
msg.msg_iov = &msg_iov;
|
msg.msg_iov = &msg_iov;
|
||||||
msg.msg_iovlen = 1;
|
msg.msg_iovlen = 1;
|
||||||
|
msg.msg_control = msg_ctrl;
|
||||||
|
|
||||||
DEBUGASSERT(max_pkts > 0);
|
DEBUGASSERT(max_pkts > 0);
|
||||||
for(pkts = 0, total_nread = 0; pkts < max_pkts;) {
|
for(pkts = 0, total_nread = 0; pkts < max_pkts;) {
|
||||||
msg.msg_name = &remote_addr;
|
msg.msg_name = &remote_addr;
|
||||||
msg.msg_namelen = sizeof(remote_addr);
|
msg.msg_namelen = sizeof(remote_addr);
|
||||||
|
msg.msg_controllen = sizeof(msg_ctrl);
|
||||||
while((nread = recvmsg(qctx->sockfd, &msg, 0)) == -1 &&
|
while((nread = recvmsg(qctx->sockfd, &msg, 0)) == -1 &&
|
||||||
SOCKERRNO == EINTR)
|
SOCKERRNO == EINTR)
|
||||||
;
|
;
|
||||||
|
@ -452,12 +513,29 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
++pkts;
|
|
||||||
total_nread += (size_t)nread;
|
total_nread += (size_t)nread;
|
||||||
result = recv_cb(buf, (size_t)nread, msg.msg_name, msg.msg_namelen,
|
|
||||||
0, userp);
|
gso_size = msghdr_get_udp_gro(&msg);
|
||||||
if(result)
|
if(gso_size == 0) {
|
||||||
goto out;
|
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:
|
out:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user