mirror of
https://github.com/3proxy/3proxy.git
synced 2026-11-07 02:05:49 +08:00
Relays: the size of a splice() pipe given to a service, -b,SIZE
-b, which made a service read less at once into a connection's buffer, takes the size of its pipes after a comma: -b,262144, -b8192,32768. From 4096 to 64M (MAXPIPESIZE); a pipe the system will not make so large (pipe-max-size for an unprivileged process) is not used, and the data is copied, as with -DPIPESIZE, which stays the default for a service given none. sockmap() and the callbacks' relay fill a pipe up to the service's size (SRVPIPESIZE()), and only a pipe of other than 64K costs an fcntl() as it is made. The man page tells of -b, which it did not before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
add40b1d85
commit
a6402010a4
@ -229,6 +229,17 @@ 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
|
||||
.B -b
|
||||
\fISIZE\fR[\fB,\fIPIPESIZE\fR] (for TCP services) read at most \fISIZE\fR bytes at
|
||||
once into a connection's buffer: less than the 16K it has, never more.
|
||||
\fIPIPESIZE\fR (Linux, with \fB-s\fR) makes the pipes of splice() hold that many
|
||||
bytes instead of 64K, from 4096 to 67108864, e.g. \fB-b,262144\fR: the
|
||||
system rounds it up to a power of 2 pages, and gives an unprivileged process
|
||||
no more than /proc/sys/fs/pipe-max-size (1M by default). A pipe that cannot
|
||||
be made so large is not used, and the data is copied. Larger pipes move more
|
||||
at once and take more kernel memory for each connection; 64K was as fast as
|
||||
larger ones in our tests.
|
||||
.br
|
||||
.B -C
|
||||
(for TCP services) a connection closed by any of the sides terminates the
|
||||
session, buffered data is delivered before the sockets are closed. By default
|
||||
|
||||
@ -400,7 +400,16 @@ static int srvprepare(struct srvstart *s, int argc, char **argv){
|
||||
srv->family = atoi(argv[i]+1);
|
||||
break;
|
||||
case 'b':
|
||||
/* -b[SIZE][,PIPESIZE] */
|
||||
srv->bufsize = atoi(argv[i]+2);
|
||||
#ifdef WITHSPLICE
|
||||
if(strchr(argv[i]+2, ',')){
|
||||
long n = atol(strchr(argv[i]+2, ',') + 1);
|
||||
|
||||
if(n < 4096 || n > MAXPIPESIZE) error = 1;
|
||||
else srv->pipesize = (unsigned)n;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#ifdef STDMAIN
|
||||
#ifndef _WIN32
|
||||
|
||||
@ -620,13 +620,13 @@ static int cbway(struct cbmap *m, struct cbway *w){
|
||||
|
||||
/* what was buffered goes first: the pipe is read once it is
|
||||
through */
|
||||
if(!inb && !w->wantbuf && w->left > w->inpipe && !m->term_r[w->src] && !end && w->inpipe < PIPESIZE &&
|
||||
if(!inb && !w->wantbuf && w->left > w->inpipe && !m->term_r[w->src] && !end && w->inpipe < SRVPIPESIZE(param->srv) &&
|
||||
(rs->ready & (POLLIN | POLLHUP | POLLERR))){
|
||||
if(pipe[0] < 0 && pipenew(pipe) < 0){
|
||||
if(pipe[0] < 0 && pipenew(pipe, SRVPIPESIZE(param->srv)) < 0){
|
||||
w->splice = 0;
|
||||
return 1;
|
||||
}
|
||||
n = splice(from, NULL, pipe[1], NULL, (size_t)CBMIN((uint64_t)PIPESIZE - w->inpipe,
|
||||
n = splice(from, NULL, pipe[1], NULL, (size_t)CBMIN((uint64_t)SRVPIPESIZE(param->srv) - w->inpipe,
|
||||
w->left - w->inpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
||||
if(n > 0){
|
||||
w->inpipe += n;
|
||||
|
||||
@ -614,11 +614,14 @@ extern struct commands commandhandlers[];
|
||||
#define SPLICE_TLSPENDING 2
|
||||
extern int (*splicetls)(struct clientparam *param, SOCKET s);
|
||||
/* what a pipe of splice() is given at most: 64K, what a pipe holds;
|
||||
built with -DPIPESIZE=<bytes>, pipes are made that large */
|
||||
built with -DPIPESIZE=<bytes>, or for a service given -b,<bytes>, pipes
|
||||
are made that large, up to MAXPIPESIZE */
|
||||
#ifndef PIPESIZE
|
||||
#define PIPESIZE 65536
|
||||
#endif
|
||||
int pipenew(int p[2]);
|
||||
#define MAXPIPESIZE (64 * 1024 * 1024)
|
||||
#define SRVPIPESIZE(srv) ((srv)->pipesize? (srv)->pipesize : (unsigned)PIPESIZE)
|
||||
int pipenew(int p[2], unsigned size);
|
||||
#define mapsocket(a,b) ((a->srv->usesplice && !a->nosplice && !a->ndatfilterssrv && !a->ndatfilterscli)?sockmap(a,b,a->srv->usesplice):sockmap(a,b,0))
|
||||
#else
|
||||
#define mapsocket(a,b) sockmap(a,b, 0)
|
||||
|
||||
@ -35,18 +35,16 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le
|
||||
and EBADMSG on some kernels */
|
||||
#define SPLICEREFUSED(e) ((e) == EINVAL || (e) == EIO || (e) == EBADMSG)
|
||||
|
||||
/* A pipe for splice(), nonblocking, of PIPESIZE: -1 if there is none to be
|
||||
had, or not of that size. */
|
||||
int pipenew(int p[2]){
|
||||
/* A pipe for splice(), nonblocking, holding size: -1 if there is none to
|
||||
be had, or not so large. A pipe holds 64K as it is made. */
|
||||
int pipenew(int p[2], unsigned size){
|
||||
if(pipe2(p, O_NONBLOCK) < 0) return -1;
|
||||
#if PIPESIZE != 65536
|
||||
if(fcntl(p[0], F_SETPIPE_SZ, PIPESIZE) < 0){
|
||||
if(size != 65536 && fcntl(p[0], F_SETPIPE_SZ, (int)size) < 0){
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
p[0] = p[1] = -1;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -140,6 +138,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
|
||||
#ifdef WITHSPLICE
|
||||
uint64_t inclientpipe = 0, inserverpipe = 0;
|
||||
unsigned pipesize = SRVPIPESIZE(param->srv);
|
||||
int TOCLIENTPIPE = 0, FROMCLIENTPIPE = 0, TOSERVERPIPE = 0, FROMSERVERPIPE = 0;
|
||||
/* The client's data goes through pipecli, the server's through pipesrv.
|
||||
They belong to the connection: made when first needed, kept for the
|
||||
@ -361,7 +360,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
/* each direction goes through its pipe if spliced, through its
|
||||
buffer otherwise; what was in the buffer before is sent first */
|
||||
if(splicecli && inclientpipe && !inclientbuf && FROMCLIENTPIPE && TOSERVER){
|
||||
res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(PIPESIZE, inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(pipesize, inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
/* from a pipe holding data: the socket is full */
|
||||
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->remsock, POLLOUT);
|
||||
if(res >0) {
|
||||
@ -388,7 +387,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
}
|
||||
}
|
||||
if(splicesrv && inserverpipe && !inserverbuf && FROMSERVERPIPE && TOCLIENT){
|
||||
res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(PIPESIZE, inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(pipesize, inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
/* from a pipe holding data: the socket is full */
|
||||
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->clisock, POLLOUT);
|
||||
if(res > 0) {
|
||||
@ -408,7 +407,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
}
|
||||
}
|
||||
if(splicecli && !wantbufcli && fromclient>inclientpipe && FROMCLIENT && TOCLIENTPIPE && !SESSIONEND){
|
||||
if(pipecli[0] < 0 && pipenew(pipecli) < 0){
|
||||
if(pipecli[0] < 0 && pipenew(pipecli, pipesize) < 0){
|
||||
/* no pipe to be had: copy instead */
|
||||
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
||||
if(param->cliinbuf < CLIROOM) TOCLIENTBUF = 1;
|
||||
@ -425,7 +424,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
continue;
|
||||
}
|
||||
errno = 0;
|
||||
res = splice(param->clisock, NULL, pipecli[1], NULL, (int)MIN((uint64_t)PIPESIZE - inclientpipe, (uint64_t)fromclient-inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
res = splice(param->clisock, NULL, pipecli[1], NULL, (int)MIN((uint64_t)pipesize - inclientpipe, (uint64_t)fromclient-inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
if(res <= 0) {
|
||||
FROMCLIENT = TOCLIENTPIPE = 0;
|
||||
if(res == 0 && !errno) {
|
||||
@ -455,13 +454,13 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
else if(++streakcli > splicestreak) wantbufcli = 1;
|
||||
}
|
||||
inclientpipe += res;
|
||||
if(inclientpipe >= PIPESIZE) TOCLIENTPIPE = 0;
|
||||
if(inclientpipe >= pipesize) TOCLIENTPIPE = 0;
|
||||
needaction = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(splicesrv && !wantbufsrv && fromserver > inserverpipe && FROMSERVER && TOSERVERPIPE && !SESSIONEND){
|
||||
if(pipesrv[0] < 0 && pipenew(pipesrv) < 0){
|
||||
if(pipesrv[0] < 0 && pipenew(pipesrv, pipesize) < 0){
|
||||
allowsrv = splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 0;
|
||||
if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1;
|
||||
continue;
|
||||
@ -475,7 +474,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
continue;
|
||||
}
|
||||
errno = 0;
|
||||
res = splice(param->remsock, NULL, pipesrv[1], NULL, MIN(PIPESIZE - inserverpipe, fromserver - inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
res = splice(param->remsock, NULL, pipesrv[1], NULL, MIN(pipesize - inserverpipe, fromserver - inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
||||
if(res <= 0) {
|
||||
FROMSERVER = TOSERVERPIPE = 0;
|
||||
if(res == 0 && !errno) {
|
||||
@ -505,7 +504,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
param->nreads++;
|
||||
param->statssrv64 += res;
|
||||
inserverpipe += res;
|
||||
if(inserverpipe >= PIPESIZE) TOSERVERPIPE = 0;
|
||||
if(inserverpipe >= pipesize) TOSERVERPIPE = 0;
|
||||
if(param->bandlimfunc) {
|
||||
int sl1;
|
||||
sl1 = (*param->bandlimfunc)(param, res, 0);
|
||||
@ -753,7 +752,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
// }
|
||||
#ifdef WITHSPLICE
|
||||
{
|
||||
if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < PIPESIZE){
|
||||
if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < pipesize){
|
||||
if(!after){
|
||||
fds[fdsc].fd = pipecli[1];
|
||||
fds[fdsc].events |= POLLOUT;
|
||||
@ -781,7 +780,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
||||
}
|
||||
fdsc++;
|
||||
}
|
||||
if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < PIPESIZE){
|
||||
if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < pipesize){
|
||||
if(!after){
|
||||
fds[fdsc].fd = pipesrv[1];
|
||||
fds[fdsc].events |= POLLOUT;
|
||||
|
||||
@ -723,6 +723,7 @@ struct srvparam {
|
||||
int usesplice;
|
||||
/* the automatic mode's heuristics, -s[N]:MIN,STREAK,SMALL */
|
||||
int splicemin, splicestreak, splicesmall;
|
||||
unsigned pipesize; /* -b,SIZE: what a pipe is made to hold, 0 PIPESIZE */
|
||||
#endif
|
||||
int halfclose;
|
||||
int udpauth;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user