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
|
the kernel does TLS for it both ways (\fBssl_ktls\fR). Available in builds with
|
||||||
WITHSPLICE, the default on Linux.
|
WITHSPLICE, the default on Linux.
|
||||||
.br
|
.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
|
.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
|
||||||
session, buffered data is delivered before the sockets are closed. By default
|
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);
|
srv->family = atoi(argv[i]+1);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
|
/* -b[SIZE][,PIPESIZE] */
|
||||||
srv->bufsize = atoi(argv[i]+2);
|
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;
|
break;
|
||||||
#ifdef STDMAIN
|
#ifdef STDMAIN
|
||||||
#ifndef _WIN32
|
#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
|
/* what was buffered goes first: the pipe is read once it is
|
||||||
through */
|
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))){
|
(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;
|
w->splice = 0;
|
||||||
return 1;
|
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);
|
w->left - w->inpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
||||||
if(n > 0){
|
if(n > 0){
|
||||||
w->inpipe += n;
|
w->inpipe += n;
|
||||||
|
|||||||
@ -614,11 +614,14 @@ extern struct commands commandhandlers[];
|
|||||||
#define SPLICE_TLSPENDING 2
|
#define SPLICE_TLSPENDING 2
|
||||||
extern int (*splicetls)(struct clientparam *param, SOCKET s);
|
extern int (*splicetls)(struct clientparam *param, SOCKET s);
|
||||||
/* what a pipe of splice() is given at most: 64K, what a pipe holds;
|
/* 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
|
#ifndef PIPESIZE
|
||||||
#define PIPESIZE 65536
|
#define PIPESIZE 65536
|
||||||
#endif
|
#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))
|
#define mapsocket(a,b) ((a->srv->usesplice && !a->nosplice && !a->ndatfilterssrv && !a->ndatfilterscli)?sockmap(a,b,a->srv->usesplice):sockmap(a,b,0))
|
||||||
#else
|
#else
|
||||||
#define mapsocket(a,b) sockmap(a,b, 0)
|
#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 */
|
and EBADMSG on some kernels */
|
||||||
#define SPLICEREFUSED(e) ((e) == EINVAL || (e) == EIO || (e) == EBADMSG)
|
#define SPLICEREFUSED(e) ((e) == EINVAL || (e) == EIO || (e) == EBADMSG)
|
||||||
|
|
||||||
/* A pipe for splice(), nonblocking, of PIPESIZE: -1 if there is none to be
|
/* A pipe for splice(), nonblocking, holding size: -1 if there is none to
|
||||||
had, or not of that size. */
|
be had, or not so large. A pipe holds 64K as it is made. */
|
||||||
int pipenew(int p[2]){
|
int pipenew(int p[2], unsigned size){
|
||||||
if(pipe2(p, O_NONBLOCK) < 0) return -1;
|
if(pipe2(p, O_NONBLOCK) < 0) return -1;
|
||||||
#if PIPESIZE != 65536
|
if(size != 65536 && fcntl(p[0], F_SETPIPE_SZ, (int)size) < 0){
|
||||||
if(fcntl(p[0], F_SETPIPE_SZ, PIPESIZE) < 0){
|
|
||||||
close(p[0]);
|
close(p[0]);
|
||||||
close(p[1]);
|
close(p[1]);
|
||||||
p[0] = p[1] = -1;
|
p[0] = p[1] = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +138,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
|
|
||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
uint64_t inclientpipe = 0, inserverpipe = 0;
|
uint64_t inclientpipe = 0, inserverpipe = 0;
|
||||||
|
unsigned pipesize = SRVPIPESIZE(param->srv);
|
||||||
int TOCLIENTPIPE = 0, FROMCLIENTPIPE = 0, TOSERVERPIPE = 0, FROMSERVERPIPE = 0;
|
int TOCLIENTPIPE = 0, FROMCLIENTPIPE = 0, TOSERVERPIPE = 0, FROMSERVERPIPE = 0;
|
||||||
/* The client's data goes through pipecli, the server's through pipesrv.
|
/* The client's data goes through pipecli, the server's through pipesrv.
|
||||||
They belong to the connection: made when first needed, kept for the
|
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
|
/* each direction goes through its pipe if spliced, through its
|
||||||
buffer otherwise; what was in the buffer before is sent first */
|
buffer otherwise; what was in the buffer before is sent first */
|
||||||
if(splicecli && inclientpipe && !inclientbuf && FROMCLIENTPIPE && TOSERVER){
|
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 */
|
/* from a pipe holding data: the socket is full */
|
||||||
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->remsock, POLLOUT);
|
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->remsock, POLLOUT);
|
||||||
if(res >0) {
|
if(res >0) {
|
||||||
@ -388,7 +387,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(splicesrv && inserverpipe && !inserverbuf && FROMSERVERPIPE && TOCLIENT){
|
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 */
|
/* from a pipe holding data: the socket is full */
|
||||||
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->clisock, POLLOUT);
|
if(res < 0 && errno == EAGAIN && fiberblockfunc) fiberblockfunc(param->clisock, POLLOUT);
|
||||||
if(res > 0) {
|
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(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 */
|
/* no pipe to be had: copy instead */
|
||||||
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0;
|
||||||
if(param->cliinbuf < CLIROOM) TOCLIENTBUF = 1;
|
if(param->cliinbuf < CLIROOM) TOCLIENTBUF = 1;
|
||||||
@ -425,7 +424,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
errno = 0;
|
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) {
|
if(res <= 0) {
|
||||||
FROMCLIENT = TOCLIENTPIPE = 0;
|
FROMCLIENT = TOCLIENTPIPE = 0;
|
||||||
if(res == 0 && !errno) {
|
if(res == 0 && !errno) {
|
||||||
@ -455,13 +454,13 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
else if(++streakcli > splicestreak) wantbufcli = 1;
|
else if(++streakcli > splicestreak) wantbufcli = 1;
|
||||||
}
|
}
|
||||||
inclientpipe += res;
|
inclientpipe += res;
|
||||||
if(inclientpipe >= PIPESIZE) TOCLIENTPIPE = 0;
|
if(inclientpipe >= pipesize) TOCLIENTPIPE = 0;
|
||||||
needaction = 0;
|
needaction = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(splicesrv && !wantbufsrv && fromserver > inserverpipe && FROMSERVER && TOSERVERPIPE && !SESSIONEND){
|
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;
|
allowsrv = splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 0;
|
||||||
if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1;
|
if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1;
|
||||||
continue;
|
continue;
|
||||||
@ -475,7 +474,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
errno = 0;
|
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) {
|
if(res <= 0) {
|
||||||
FROMSERVER = TOSERVERPIPE = 0;
|
FROMSERVER = TOSERVERPIPE = 0;
|
||||||
if(res == 0 && !errno) {
|
if(res == 0 && !errno) {
|
||||||
@ -505,7 +504,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
param->nreads++;
|
param->nreads++;
|
||||||
param->statssrv64 += res;
|
param->statssrv64 += res;
|
||||||
inserverpipe += res;
|
inserverpipe += res;
|
||||||
if(inserverpipe >= PIPESIZE) TOSERVERPIPE = 0;
|
if(inserverpipe >= pipesize) TOSERVERPIPE = 0;
|
||||||
if(param->bandlimfunc) {
|
if(param->bandlimfunc) {
|
||||||
int sl1;
|
int sl1;
|
||||||
sl1 = (*param->bandlimfunc)(param, res, 0);
|
sl1 = (*param->bandlimfunc)(param, res, 0);
|
||||||
@ -753,7 +752,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
// }
|
// }
|
||||||
#ifdef WITHSPLICE
|
#ifdef WITHSPLICE
|
||||||
{
|
{
|
||||||
if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < PIPESIZE){
|
if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < pipesize){
|
||||||
if(!after){
|
if(!after){
|
||||||
fds[fdsc].fd = pipecli[1];
|
fds[fdsc].fd = pipecli[1];
|
||||||
fds[fdsc].events |= POLLOUT;
|
fds[fdsc].events |= POLLOUT;
|
||||||
@ -781,7 +780,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|||||||
}
|
}
|
||||||
fdsc++;
|
fdsc++;
|
||||||
}
|
}
|
||||||
if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < PIPESIZE){
|
if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < pipesize){
|
||||||
if(!after){
|
if(!after){
|
||||||
fds[fdsc].fd = pipesrv[1];
|
fds[fdsc].fd = pipesrv[1];
|
||||||
fds[fdsc].events |= POLLOUT;
|
fds[fdsc].events |= POLLOUT;
|
||||||
|
|||||||
@ -723,6 +723,7 @@ struct srvparam {
|
|||||||
int usesplice;
|
int usesplice;
|
||||||
/* the automatic mode's heuristics, -s[N]:MIN,STREAK,SMALL */
|
/* the automatic mode's heuristics, -s[N]:MIN,STREAK,SMALL */
|
||||||
int splicemin, splicestreak, splicesmall;
|
int splicemin, splicestreak, splicesmall;
|
||||||
|
unsigned pipesize; /* -b,SIZE: what a pipe is made to hold, 0 PIPESIZE */
|
||||||
#endif
|
#endif
|
||||||
int halfclose;
|
int halfclose;
|
||||||
int udpauth;
|
int udpauth;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user