mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-16 08:35:48 +08:00
Make the automatic splice() mode's heuristics a service option
-s[N]:MIN,STREAK,SMALL sets where the automatic mode splices, as -g does for grace delay: a direction is spliced after STREAK reads in a row of MIN bytes or more (SMALL from a TLS socket), copied again after more than STREAK splices in a row of less than SMALL, and a body of known length is spliced if MIN or more of it is left. The defaults, 16384,2,4096, are what was built in; a value left out or 0 keeps its default. The man page describes it, and its HTML copy, which still said splice() was not built by default, now has the current text. A test case relays answers of every size, chunked ones and a 3 MB upload through every mode, two of them with heuristics set, and compares them byte for byte. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cfe52878d0
commit
61041ebe7d
@ -218,12 +218,33 @@ second. Useful to minimize polling <b><br>
|
|||||||
-s</b> <br>
|
-s</b> <br>
|
||||||
(for admin) secure, allow only secure operations, currently
|
(for admin) secure, allow only secure operations, currently
|
||||||
only traffic counters view without ability to reset. <br>
|
only traffic counters view without ability to reset. <br>
|
||||||
(for TCP services, Linux) enable splice(). splice() is not
|
(for TCP services, Linux) use splice() to pass data between
|
||||||
built by default and is disabled even when built, because
|
the client and the server without copying it through 3proxy.
|
||||||
current Linux does not implement SPLICE_F_MOVE, so no real
|
<b>-s</b> alone splices both directions where it pays: a body
|
||||||
zero-copy takes place and the read/write path is faster for
|
of known length if at least 16K of it is left to read, a
|
||||||
most traffic. Rebuild with -DWITHSPLICE to make -s
|
stream once it carries large reads, back to copying when they
|
||||||
available, -s0 disables it explicitly. <b><br>
|
turn small. <b>-s1</b> always splices what the server sends
|
||||||
|
to the client (downloads), <b>-s2</b> what the client sends
|
||||||
|
(uploads), <b>-s3</b> both; adding 4 (<b>-s5</b>, <b>-s6</b>,
|
||||||
|
<b>-s7</b>, the last the same as <b>-s</b>, and the default)
|
||||||
|
splices those directions only where it pays. <b>-s0</b> turns
|
||||||
|
it off. Where it pays can be tuned with
|
||||||
|
<b>:</b><i>MIN</i><b>,</b><i>STREAK</i><b>,</b><i>SMALL</i>
|
||||||
|
after the mode, e.g. <b>-s:16384,2,4096</b> (the default) or
|
||||||
|
<b>-s6:65536,3,8192</b>: a direction is spliced after
|
||||||
|
<i>STREAK</i> reads in a row of <i>MIN</i> bytes or more
|
||||||
|
(<i>SMALL</i> from a TLS socket, which hands out a record at a
|
||||||
|
time) and copied again after more than <i>STREAK</i> splices
|
||||||
|
in a row of less than <i>SMALL</i>; a body of known length is
|
||||||
|
spliced if at least <i>MIN</i> of it is left to read. splice()
|
||||||
|
suits large transfers: they go faster and use less CPU. A
|
||||||
|
spliced direction needs a pipe (two file descriptors), made
|
||||||
|
when first needed and kept for the connection, and more kernel
|
||||||
|
memory. A service with data filters does not splice, so that
|
||||||
|
the filters see all of the data, nor does one ending or
|
||||||
|
beginning TLS, unless the kernel does TLS for it both ways
|
||||||
|
(<b>ssl_ktls</b>). Available in builds with WITHSPLICE, the
|
||||||
|
default on Linux. <b><br>
|
||||||
-C</b> <br>
|
-C</b> <br>
|
||||||
(for TCP services) a connection closed by any of the sides
|
(for TCP services) a connection closed by any of the sides
|
||||||
terminates the session, buffered data is delivered before
|
terminates the session, buffered data is delivered before
|
||||||
|
|||||||
@ -209,11 +209,18 @@ once it carries large reads, back to copying when they turn small. \fB-s1\fR alw
|
|||||||
splices what the server sends to the client (downloads), \fB-s2\fR what the client
|
splices what the server sends to the client (downloads), \fB-s2\fR what the client
|
||||||
sends (uploads), \fB-s3\fR both; adding 4 (\fB-s5\fR, \fB-s6\fR, \fB-s7\fR, the last the same as
|
sends (uploads), \fB-s3\fR both; adding 4 (\fB-s5\fR, \fB-s6\fR, \fB-s7\fR, the last the same as
|
||||||
\fB-s\fR, and the default) splices those directions only where it pays. \fB-s0\fR turns it
|
\fB-s\fR, and the default) splices those directions only where it pays. \fB-s0\fR turns it
|
||||||
off. splice() suits large transfers: they go faster and use less CPU; small
|
off. Where it pays can be tuned with \fB:\fIMIN\fB,\fISTREAK\fB,\fISMALL\fR after the
|
||||||
requests go slower with it. A spliced direction needs a pipe (two file
|
mode, e.g. \fB-s:16384,2,4096\fR (the default) or \fB-s6:65536,3,8192\fR: a direction is
|
||||||
descriptors), made when first needed and kept for the connection, and more
|
spliced after \fISTREAK\fR reads in a row of \fIMIN\fR bytes or more (\fISMALL\fR from a
|
||||||
kernel memory. A service with data filters does not splice, so that the filters
|
TLS socket, which hands out a record at a time) and copied again after more
|
||||||
see all of the data. Available in builds with WITHSPLICE, the default on Linux.
|
than \fISTREAK\fR splices in a row of less than \fISMALL\fR; a body of known length is
|
||||||
|
spliced if at least \fIMIN\fR of it is left to read. splice() suits large
|
||||||
|
transfers: they go faster and use less CPU. A spliced direction needs a pipe
|
||||||
|
(two file descriptors), made when first needed and kept for the connection,
|
||||||
|
and more kernel memory. A service with data filters does not splice, so that
|
||||||
|
the filters see all of the data, nor does one ending or beginning TLS, unless
|
||||||
|
the kernel does TLS for it both ways (\fBssl_ktls\fR). Available in builds with
|
||||||
|
WITHSPLICE, the default on Linux.
|
||||||
.br
|
.br
|
||||||
.B -C
|
.B -C
|
||||||
(for TCP services) a connection closed by any of the sides terminates the
|
(for TCP services) a connection closed by any of the sides terminates the
|
||||||
|
|||||||
@ -235,6 +235,11 @@ extern struct extparam confboot;
|
|||||||
#define SPLICE_DOWNLOAD 1
|
#define SPLICE_DOWNLOAD 1
|
||||||
#define SPLICE_UPLOAD 2
|
#define SPLICE_UPLOAD 2
|
||||||
#define SPLICE_AUTO 4
|
#define SPLICE_AUTO 4
|
||||||
|
/* where SPLICE_AUTO splices, by default (-s[N]:MIN,STREAK,SMALL): see
|
||||||
|
sockmap.c */
|
||||||
|
#define SPLICE_MIN 16384
|
||||||
|
#define SPLICE_STREAK 2
|
||||||
|
#define SPLICE_SMALL 4096
|
||||||
int sockmap(struct clientparam * param, int timeo, int usesplice);
|
int sockmap(struct clientparam * param, int timeo, int usesplice);
|
||||||
int udpsockmap(struct clientparam * param, int timeo);
|
int udpsockmap(struct clientparam * param, int timeo);
|
||||||
int udpbind(struct clientparam * param);
|
int udpbind(struct clientparam * param);
|
||||||
|
|||||||
@ -436,6 +436,10 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
|
|||||||
" -s[N] Use splice(): -s1 server to client, -s2 client to server, -s3 both\n"
|
" -s[N] Use splice(): -s1 server to client, -s2 client to server, -s3 both\n"
|
||||||
" directions; -s (-s7, the default) both, -s5 or -s6 one, only where it\n"
|
" directions; -s (-s7, the default) both, -s5 or -s6 one, only where it\n"
|
||||||
" pays (large transfers); -s0 never. Not with data filters\n"
|
" pays (large transfers); -s0 never. Not with data filters\n"
|
||||||
|
" :MIN,STREAK,SMALL tune where it pays (-s:16384,2,4096): splice after\n"
|
||||||
|
" STREAK reads in a row of MIN bytes or more (SMALL from a TLS socket),\n"
|
||||||
|
" copy again after more than STREAK splices of less than SMALL; a body of\n"
|
||||||
|
" known length is spliced if MIN or more of it is left\n"
|
||||||
" -C connection closed by any of the sides terminates the session, by default\n"
|
" -C connection closed by any of the sides terminates the session, by default\n"
|
||||||
" the session is kept until both sides close it (TCP half-close)\n"
|
" the session is kept until both sides close it (TCP half-close)\n"
|
||||||
" -U(0-3) (for socks) what to do when the destination changes within an UDP\n"
|
" -U(0-3) (for socks) what to do when the destination changes within an UDP\n"
|
||||||
@ -716,10 +720,22 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
|
|||||||
#endif
|
#endif
|
||||||
srv->s_option = 1 + atoi(argv[i]+2);
|
srv->s_option = 1 + atoi(argv[i]+2);
|
||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
else
|
else {
|
||||||
srv->usesplice = (*(argv[i]+2)? atoi(argv[i]+2) :
|
/* -s[N][:MIN,STREAK,SMALL] */
|
||||||
|
char *heur = strchr(argv[i]+2, ':');
|
||||||
|
|
||||||
|
srv->usesplice = ((argv[i][2] && argv[i][2] != ':')? atoi(argv[i]+2) :
|
||||||
SPLICE_DOWNLOAD|SPLICE_UPLOAD|SPLICE_AUTO) &
|
SPLICE_DOWNLOAD|SPLICE_UPLOAD|SPLICE_AUTO) &
|
||||||
(SPLICE_DOWNLOAD|SPLICE_UPLOAD|SPLICE_AUTO);
|
(SPLICE_DOWNLOAD|SPLICE_UPLOAD|SPLICE_AUTO);
|
||||||
|
if(heur){
|
||||||
|
int min = 0, streak = 0, small = 0;
|
||||||
|
|
||||||
|
sscanf(heur+1, "%d,%d,%d", &min, &streak, &small);
|
||||||
|
if(min > 0) srv->splicemin = min;
|
||||||
|
if(streak > 0) srv->splicestreak = streak;
|
||||||
|
if(small > 0) srv->splicesmall = small;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
@ -1498,6 +1514,9 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
|||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
/* where it pays: large transfers, -s0 to never */
|
/* where it pays: large transfers, -s0 to never */
|
||||||
srv->usesplice = SPLICE_DOWNLOAD|SPLICE_UPLOAD|SPLICE_AUTO;
|
srv->usesplice = SPLICE_DOWNLOAD|SPLICE_UPLOAD|SPLICE_AUTO;
|
||||||
|
srv->splicemin = SPLICE_MIN;
|
||||||
|
srv->splicestreak = SPLICE_STREAK;
|
||||||
|
srv->splicesmall = SPLICE_SMALL;
|
||||||
#endif
|
#endif
|
||||||
srv->halfclose = 1;
|
srv->halfclose = 1;
|
||||||
srv->udpauth = 3;
|
srv->udpauth = 3;
|
||||||
|
|||||||
@ -44,18 +44,16 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le
|
|||||||
|
|
||||||
/* With SPLICE_AUTO, when a direction allowed to splice actually does
|
/* With SPLICE_AUTO, when a direction allowed to splice actually does
|
||||||
(without it, an allowed direction always does).
|
(without it, an allowed direction always does).
|
||||||
A body of known length is spliced if at least SPLICE_MIN of it is left
|
A body of known length is spliced if at least splicemin of it is left
|
||||||
to read once what is already buffered is counted: a smaller one, or one
|
to read once what is already buffered is counted: a smaller one, or one
|
||||||
read whole with its headers, is cheaper to copy.
|
read whole with its headers, is cheaper to copy.
|
||||||
A stream of unknown length starts copied and is spliced after
|
A stream of unknown length starts copied and is spliced after
|
||||||
SPLICE_STREAK reads in a row of at least SPLICE_MIN each, and goes back to
|
splicestreak reads in a row of at least splicemin each, and goes back to
|
||||||
copying after SPLICE_STREAK+1 splices in a row of less than SPLICE_SMALL. */
|
copying after splicestreak+1 splices in a row of less than splicesmall.
|
||||||
#define SPLICE_MIN 16384
|
From a TLS socket a read of splicesmall counts as large: TLS hands out a
|
||||||
#define SPLICE_SMALL 4096
|
record at a time, at most 16K and often less. The service sets the three
|
||||||
#define SPLICE_STREAK 2
|
(-s[N]:MIN,STREAK,SMALL), SPLICE_MIN, SPLICE_STREAK and SPLICE_SMALL by
|
||||||
/* a large read from a TLS socket: TLS hands out a record at a time, at most
|
default. */
|
||||||
16K and often less */
|
|
||||||
#define SPLICE_TLSMIN SPLICE_SMALL
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -149,6 +147,8 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
into the buffer first (drain), once the pipe is empty, so as to keep the
|
into the buffer first (drain), once the pipe is empty, so as to keep the
|
||||||
order; tail: the last read left some, the next only collects it */
|
order; tail: the last read left some, the next only collects it */
|
||||||
int draincli = 0, drainsrv = 0, tailcli = 0, tailsrv = 0;
|
int draincli = 0, drainsrv = 0, tailcli = 0, tailsrv = 0;
|
||||||
|
int splicemin = param->srv->splicemin, splicestreak = param->srv->splicestreak,
|
||||||
|
splicesmall = param->srv->splicesmall;
|
||||||
|
|
||||||
if((!param->nolongdatfilter && (param->ndatfilterscli > 0 || param->ndatfilterssrv)) || param->nosplice) usesplice = 0;
|
if((!param->nolongdatfilter && (param->ndatfilterscli > 0 || param->ndatfilterssrv)) || param->nosplice) usesplice = 0;
|
||||||
allowcli = (usesplice & SPLICE_UPLOAD) != 0;
|
allowcli = (usesplice & SPLICE_UPLOAD) != 0;
|
||||||
@ -190,8 +190,8 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
if(inclientbuf >= fromclient) FROMCLIENT = 0;
|
if(inclientbuf >= fromclient) FROMCLIENT = 0;
|
||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
/* a body of known length large enough is spliced from the start */
|
/* a body of known length large enough is spliced from the start */
|
||||||
if(autosplice && allowsrv && param->waitserver64 && fromserver > inserverbuf && fromserver - inserverbuf >= SPLICE_MIN) splicesrv = 1;
|
if(autosplice && allowsrv && param->waitserver64 && fromserver > inserverbuf && fromserver - inserverbuf >= (uint64_t)splicemin) splicesrv = 1;
|
||||||
if(autosplice && allowcli && param->waitclient64 && fromclient > inclientbuf && fromclient - inclientbuf >= SPLICE_MIN) splicecli = 1;
|
if(autosplice && allowcli && param->waitclient64 && fromclient > inclientbuf && fromclient - inclientbuf >= (uint64_t)splicemin) splicecli = 1;
|
||||||
#endif
|
#endif
|
||||||
if(param->srvinbuf == param->srvoffset) param->srvinbuf =param->srvoffset = 0;
|
if(param->srvinbuf == param->srvoffset) param->srvinbuf =param->srvoffset = 0;
|
||||||
if(param->cliinbuf == param->clioffset) param->cliinbuf =param->clioffset = 0;
|
if(param->cliinbuf == param->clioffset) param->cliinbuf =param->clioffset = 0;
|
||||||
@ -504,8 +504,8 @@ log("done read from client to pipe");
|
|||||||
graceclitraf += res;
|
graceclitraf += res;
|
||||||
gracesrvnum = gracesrvtraf = 0;
|
gracesrvnum = gracesrvtraf = 0;
|
||||||
if(autosplice && !param->waitclient64){
|
if(autosplice && !param->waitclient64){
|
||||||
if(res >= SPLICE_SMALL) streakcli = 0;
|
if(res >= splicesmall) streakcli = 0;
|
||||||
else if(++streakcli > SPLICE_STREAK) wantbufcli = 1;
|
else if(++streakcli > splicestreak) wantbufcli = 1;
|
||||||
}
|
}
|
||||||
inclientpipe += res;
|
inclientpipe += res;
|
||||||
if(inclientpipe >= MAXSPLICE) TOCLIENTPIPE = 0;
|
if(inclientpipe >= MAXSPLICE) TOCLIENTPIPE = 0;
|
||||||
@ -567,8 +567,8 @@ log("done read from server to pipe\n");
|
|||||||
gracesrvtraf += res;
|
gracesrvtraf += res;
|
||||||
graceclinum = graceclitraf = 0;
|
graceclinum = graceclitraf = 0;
|
||||||
if(autosplice && !param->waitserver64){
|
if(autosplice && !param->waitserver64){
|
||||||
if(res >= SPLICE_SMALL) streaksrv = 0;
|
if(res >= splicesmall) streaksrv = 0;
|
||||||
else if(++streaksrv > SPLICE_STREAK) wantbufsrv = 1;
|
else if(++streaksrv > splicestreak) wantbufsrv = 1;
|
||||||
}
|
}
|
||||||
param->nreads++;
|
param->nreads++;
|
||||||
param->statssrv64 += res;
|
param->statssrv64 += res;
|
||||||
@ -620,8 +620,8 @@ log("done read from client to buf");
|
|||||||
else if(autosplice && allowcli && !param->waitclient64){
|
else if(autosplice && allowcli && !param->waitclient64){
|
||||||
int tls = splicetls? splicetls(param, param->clisock) : 0;
|
int tls = splicetls? splicetls(param, param->clisock) : 0;
|
||||||
|
|
||||||
if(res >= (tls? SPLICE_TLSMIN : SPLICE_MIN)){
|
if(res >= (tls? splicesmall : splicemin)){
|
||||||
if(++streakcli >= SPLICE_STREAK){
|
if(++streakcli >= splicestreak){
|
||||||
/* a stream: splice from now on, after what is
|
/* a stream: splice from now on, after what is
|
||||||
buffered has been sent */
|
buffered has been sent */
|
||||||
splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 1;
|
splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 1;
|
||||||
@ -675,8 +675,8 @@ log("done read from server to buf");
|
|||||||
else if(autosplice && allowsrv && !param->waitserver64){
|
else if(autosplice && allowsrv && !param->waitserver64){
|
||||||
int tls = splicetls? splicetls(param, param->remsock) : 0;
|
int tls = splicetls? splicetls(param, param->remsock) : 0;
|
||||||
|
|
||||||
if(res >= (tls? SPLICE_TLSMIN : SPLICE_MIN)){
|
if(res >= (tls? splicesmall : splicemin)){
|
||||||
if(++streaksrv >= SPLICE_STREAK){
|
if(++streaksrv >= splicestreak){
|
||||||
splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 1;
|
splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 1;
|
||||||
streaksrv = 0;
|
streaksrv = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -653,6 +653,8 @@ struct srvparam {
|
|||||||
unsigned char fakeip6[16];
|
unsigned char fakeip6[16];
|
||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
int usesplice;
|
int usesplice;
|
||||||
|
/* the automatic mode's heuristics, -s[N]:MIN,STREAK,SMALL */
|
||||||
|
int splicemin, splicestreak, splicesmall;
|
||||||
#endif
|
#endif
|
||||||
int halfclose;
|
int halfclose;
|
||||||
int udpauth;
|
int udpauth;
|
||||||
|
|||||||
121
tests/cases/splice.py
Normal file
121
tests/cases/splice.py
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
"""splice(): every mode relays what it is given unchanged, small and large,
|
||||||
|
both ways, the automatic mode's heuristics set or not (-s[N]:MIN,STREAK,SMALL).
|
||||||
|
|
||||||
|
Where splice() is not built (anything but Linux) -s is accepted and ignored,
|
||||||
|
so the same checks then cover copying.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
import threading
|
||||||
|
|
||||||
|
MODES = ["-s0", "-s", "-s3", "-s:65536,3,8192", "-s2:32768,2,4096"]
|
||||||
|
|
||||||
|
|
||||||
|
def echo_origin(listener):
|
||||||
|
"""Sends back whatever each connection sends, until it shuts down its
|
||||||
|
side."""
|
||||||
|
def serve(c):
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
b = c.recv(65536)
|
||||||
|
if not b:
|
||||||
|
break
|
||||||
|
c.sendall(b)
|
||||||
|
c.shutdown(socket.SHUT_WR)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
c.close()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
c, _ = listener.accept()
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
threading.Thread(target=serve, args=(c,), daemon=True).start()
|
||||||
|
|
||||||
|
|
||||||
|
def echo_through(port, data):
|
||||||
|
"""data sent through the mapped port while what comes back is read; the
|
||||||
|
sending side is shut down once all is sent."""
|
||||||
|
s = socket.create_connection(("127.0.0.1", port), timeout=20)
|
||||||
|
got = []
|
||||||
|
|
||||||
|
def reader():
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
b = s.recv(65536)
|
||||||
|
except OSError:
|
||||||
|
return
|
||||||
|
if not b:
|
||||||
|
return
|
||||||
|
got.append(b)
|
||||||
|
|
||||||
|
th = threading.Thread(target=reader, daemon=True)
|
||||||
|
th.start()
|
||||||
|
s.sendall(data)
|
||||||
|
s.shutdown(socket.SHUT_WR)
|
||||||
|
th.join(30)
|
||||||
|
s.close()
|
||||||
|
return b"".join(got)
|
||||||
|
|
||||||
|
|
||||||
|
def run(t):
|
||||||
|
origin = t.free_port()
|
||||||
|
listener = socket.socket()
|
||||||
|
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
listener.bind(("127.0.0.1", 0))
|
||||||
|
listener.listen(64)
|
||||||
|
echo = listener.getsockname()[1]
|
||||||
|
threading.Thread(target=echo_origin, args=(listener,), daemon=True).start()
|
||||||
|
|
||||||
|
proxies, mapped = [], []
|
||||||
|
conf = f"""
|
||||||
|
log
|
||||||
|
auth iponly
|
||||||
|
allow *
|
||||||
|
http data * /data
|
||||||
|
httpsrv -p{origin}
|
||||||
|
|
||||||
|
flush
|
||||||
|
auth iponly
|
||||||
|
allow *
|
||||||
|
"""
|
||||||
|
for mode in MODES:
|
||||||
|
p, m = t.free_port(), t.free_port()
|
||||||
|
proxies.append(p)
|
||||||
|
mapped.append(m)
|
||||||
|
conf += f" proxy {mode} -p{p}\n tcppm {mode} {m} 127.0.0.1 {echo}\n"
|
||||||
|
t.start("splice", conf, ports=[origin] + proxies + mapped)
|
||||||
|
|
||||||
|
direct = {size: t.http(f"http://127.0.0.1:{origin}/data?size={size}").body
|
||||||
|
for size in (1000, 100000, 5000000)}
|
||||||
|
chunked = t.http(f"http://127.0.0.1:{origin}/data?size=1000000&chunked=1").body
|
||||||
|
up = os.urandom(3000000)
|
||||||
|
|
||||||
|
try:
|
||||||
|
for mode, p, m in zip(MODES, proxies, mapped):
|
||||||
|
proxy = f"127.0.0.1:{p}"
|
||||||
|
for size, body in direct.items():
|
||||||
|
got = t.http(f"http://127.0.0.1:{origin}/data?size={size}", proxy=proxy)
|
||||||
|
if got.body == body:
|
||||||
|
t.ok(f"{mode}: a {size} byte answer arrives unchanged")
|
||||||
|
else:
|
||||||
|
t.fail(f"{mode}: a {size} byte answer arrives unchanged",
|
||||||
|
f"{size} bytes", f"{got.length} different bytes")
|
||||||
|
got = t.http(f"http://127.0.0.1:{origin}/data?size=1000000&chunked=1", proxy=proxy)
|
||||||
|
if got.body == chunked:
|
||||||
|
t.ok(f"{mode}: a chunked answer arrives unchanged")
|
||||||
|
else:
|
||||||
|
t.fail(f"{mode}: a chunked answer arrives unchanged",
|
||||||
|
f"{len(chunked)} bytes", f"{got.length} different bytes")
|
||||||
|
back = echo_through(m, up)
|
||||||
|
if back == up:
|
||||||
|
t.ok(f"{mode}: 3 MB sent through tcppm come back unchanged")
|
||||||
|
else:
|
||||||
|
t.fail(f"{mode}: 3 MB sent through tcppm come back unchanged",
|
||||||
|
f"{len(up)} bytes", f"{len(back)} bytes, different")
|
||||||
|
small = echo_through(m, b"hello")
|
||||||
|
t.eq(b"hello", small, f"{mode}: a few bytes through tcppm come back")
|
||||||
|
finally:
|
||||||
|
listener.close()
|
||||||
Loading…
Reference in New Issue
Block a user