vmsplice instead of sendfile

This commit is contained in:
ruti 2024-09-06 21:07:11 +03:00
parent 2e244fd1b8
commit bb675e7ad4

View file

@ -1,3 +1,5 @@
#define _GNU_SOURCE
#include "desync.h" #include "desync.h"
#include <stdio.h> #include <stdio.h>
@ -16,11 +18,7 @@
#include <netinet/tcp.h> #include <netinet/tcp.h>
#else #else
#include <linux/tcp.h> #include <linux/tcp.h>
#include <sys/sendfile.h>
#include <linux/filter.h> #include <linux/filter.h>
#include <sys/syscall.h>
#define memfd_create(name, flags) syscall(__NR_memfd_create, name, flags)
#endif #endif
#else #else
#include <winsock2.h> #include <winsock2.h>
@ -143,14 +141,12 @@ void wait_send(int sfd)
#define wait_send_if_support(sfd) // :( #define wait_send_if_support(sfd) // :(
#endif #endif
#ifdef FAKE_SUPPORT #ifdef __linux__
#ifndef _WIN32
ssize_t send_fake(int sfd, char *buffer, ssize_t send_fake(int sfd, char *buffer,
int cnt, long pos, int fa, struct desync_params *opt) int cnt, long pos, int fa, struct desync_params *opt)
{ {
struct sockaddr_in6 addr = {}; struct sockaddr_in6 addr = {};
socklen_t addr_size = sizeof(addr); socklen_t addr_size = sizeof(addr);
#ifdef __linux__
if (opt->md5sig) { if (opt->md5sig) {
if (getpeername(sfd, if (getpeername(sfd,
(struct sockaddr *)&addr, &addr_size) < 0) { (struct sockaddr *)&addr, &addr_size) < 0) {
@ -158,7 +154,6 @@ ssize_t send_fake(int sfd, char *buffer,
return -1; return -1;
} }
} }
#endif
struct packet pkt; struct packet pkt;
if (opt->fake_data.data) { if (opt->fake_data.data) {
pkt = opt->fake_data; pkt = opt->fake_data;
@ -173,21 +168,16 @@ ssize_t send_fake(int sfd, char *buffer,
} }
else pkt.size = 0; else pkt.size = 0;
} }
int fds[2];
int ffd = memfd_create("name", 0); if (pipe(fds) < 0) {
if (ffd < 0) { uniperror("pipe");
uniperror("memfd_create");
return -1; return -1;
} }
char *p = 0; char *p = 0;
ssize_t len = -1; ssize_t len = -1;
while (1) { while (1) {
if (ftruncate(ffd, pos) < 0) { p = mmap(0, pos, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
uniperror("ftruncate");
break;
}
p = mmap(0, pos, PROT_WRITE, MAP_SHARED, ffd, 0);
if (p == MAP_FAILED) { if (p == MAP_FAILED) {
uniperror("mmap"); uniperror("mmap");
p = 0; p = 0;
@ -198,8 +188,6 @@ ssize_t send_fake(int sfd, char *buffer,
if (setttl(sfd, opt->ttl ? opt->ttl : 8, fa) < 0) { if (setttl(sfd, opt->ttl ? opt->ttl : 8, fa) < 0) {
break; break;
} }
#ifdef __linux__
if (opt->md5sig) { if (opt->md5sig) {
struct tcp_md5sig md5 = { struct tcp_md5sig md5 = {
.tcpm_keylen = 5 .tcpm_keylen = 5
@ -212,17 +200,22 @@ ssize_t send_fake(int sfd, char *buffer,
break; break;
} }
} }
#endif
if (opt->ip_options && fa == AF_INET if (opt->ip_options && fa == AF_INET
&& setsockopt(sfd, IPPROTO_IP, IP_OPTIONS, && setsockopt(sfd, IPPROTO_IP, IP_OPTIONS,
opt->ip_options, opt->ip_options_len) < 0) { opt->ip_options, opt->ip_options_len) < 0) {
uniperror("setsockopt IP_OPTIONS"); uniperror("setsockopt IP_OPTIONS");
break; break;
} }
struct iovec vec = { .iov_base = p, .iov_len = pos };
len = sendfile(sfd, ffd, 0, pos); len = vmsplice(fds[1], &vec, 1, SPLICE_F_GIFT);
if (len < 0) { if (len < 0) {
uniperror("sendfile"); uniperror("vmsplice");
break;
}
len = splice(fds[0], 0, sfd, 0, len, 0);
if (len < 0) {
uniperror("splice");
break; break;
} }
wait_send(sfd); wait_send(sfd);
@ -237,7 +230,6 @@ ssize_t send_fake(int sfd, char *buffer,
uniperror("setsockopt IP_OPTIONS"); uniperror("setsockopt IP_OPTIONS");
break; break;
} }
#ifdef __linux__
if (opt->md5sig) { if (opt->md5sig) {
struct tcp_md5sig md5 = { struct tcp_md5sig md5 = {
.tcpm_keylen = 0 .tcpm_keylen = 0
@ -250,11 +242,11 @@ ssize_t send_fake(int sfd, char *buffer,
break; break;
} }
} }
#endif
break; break;
} }
if (p) munmap(p, pos); if (p) munmap(p, pos);
close(ffd); close(fds[0]);
close(fds[1]);
return len; return len;
} }
#else #else
@ -359,7 +351,6 @@ ssize_t send_fake(int sfd, char *buffer,
return len; return len;
} }
#endif #endif
#endif
ssize_t send_oob(int sfd, char *buffer, ssize_t send_oob(int sfd, char *buffer,
ssize_t n, long pos, char *c) ssize_t n, long pos, char *c)