diff --git a/src/mainloop.c b/src/mainloop.c index d642301..a539e8e 100644 --- a/src/mainloop.c +++ b/src/mainloop.c @@ -446,8 +446,6 @@ DONE: #define SPLICE_F_NONBLOCK 0x02 #endif ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags); -/* what a pipe of splice() takes at once, as sockmap()'s MAXSPLICE */ -#define CBSPLICE 65536 #endif /* One way of the relay: from the side src to dst, through the buffer of @@ -621,13 +619,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 < CBSPLICE && + if(!inb && !w->wantbuf && w->left > w->inpipe && !m->term_r[w->src] && !end && w->inpipe < PIPESIZE && (rs->ready & (POLLIN | POLLHUP | POLLERR))){ - if(pipe[0] < 0 && pipe2(pipe, O_NONBLOCK) < 0){ + if(pipe[0] < 0 && pipenew(pipe) < 0){ w->splice = 0; return 1; } - n = splice(from, NULL, pipe[1], NULL, (size_t)CBMIN((uint64_t)CBSPLICE - w->inpipe, + n = splice(from, NULL, pipe[1], NULL, (size_t)CBMIN((uint64_t)PIPESIZE - w->inpipe, w->left - w->inpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE); if(n > 0){ w->inpipe += n; diff --git a/src/proxy.h b/src/proxy.h index 694a0d0..da6dfbf 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -628,6 +628,12 @@ extern struct commands commandhandlers[]; #define SPLICE_TLS 1 #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=, pipes are made that large */ +#ifndef PIPESIZE +#define PIPESIZE 65536 +#endif +int pipenew(int p[2]); #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) diff --git a/src/sockmap.c b/src/sockmap.c index 16af624..5ca5f8c 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -36,12 +36,29 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le #define SPLICE_F_GIFT 0x08 #endif +#ifndef F_SETPIPE_SZ +#define F_SETPIPE_SZ 1031 +#endif -#define MAXSPLICE 65536 /* splice() refuses a kernel TLS record that is not data: EINVAL, or EIO 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]){ + if(pipe2(p, O_NONBLOCK) < 0) return -1; +#if PIPESIZE != 65536 + if(fcntl(p[0], F_SETPIPE_SZ, PIPESIZE) < 0){ + close(p[0]); + close(p[1]); + p[0] = p[1] = -1; + return -1; + } +#endif + return 0; +} + /* With SPLICE_AUTO, when a direction allowed to splice actually does (without it, an allowed direction always does). A body of known length is spliced if at least splicemin of it is left @@ -391,7 +408,7 @@ log("done send to client from buf"); #ifdef WITHLOG log("send to server from pipe"); #endif - res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, 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); #ifdef WITHLOG @@ -430,7 +447,7 @@ log(logbuf); #ifdef WITHLOG log("send to client from pipe"); #endif - res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, 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); #ifdef WITHLOG @@ -462,7 +479,7 @@ log(logbuf); #ifdef WITHLOG log("read from client to pipe"); #endif - if(pipecli[0] < 0 && pipe2(pipecli, O_NONBLOCK) < 0){ + if(pipecli[0] < 0 && pipenew(pipecli) < 0){ /* no pipe to be had: copy instead */ allowcli = splicecli = TOCLIENTPIPE = FROMCLIENTPIPE = 0; if(param->cliinbuf < CLIROOM) TOCLIENTBUF = 1; @@ -479,7 +496,7 @@ log("read from client to pipe"); continue; } errno = 0; - res = splice(param->clisock, NULL, pipecli[1], NULL, (int)MIN((uint64_t)MAXSPLICE - 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); #ifdef WITHLOG log("client to pipe splice finished\n"); #if WITHLOG > 1 @@ -521,7 +538,7 @@ log("done read from client to pipe"); else if(++streakcli > splicestreak) wantbufcli = 1; } inclientpipe += res; - if(inclientpipe >= MAXSPLICE) TOCLIENTPIPE = 0; + if(inclientpipe >= PIPESIZE) TOCLIENTPIPE = 0; needaction = 0; continue; } @@ -530,7 +547,7 @@ log("done read from client to pipe"); #ifdef WITHLOG log("read from server to pipe\n"); #endif - if(pipesrv[0] < 0 && pipe2(pipesrv, O_NONBLOCK) < 0){ + if(pipesrv[0] < 0 && pipenew(pipesrv) < 0){ allowsrv = splicesrv = TOSERVERPIPE = FROMSERVERPIPE = 0; if(param->srvinbuf < SRVROOM) TOSERVERBUF = 1; continue; @@ -544,7 +561,7 @@ log("read from server to pipe\n"); continue; } errno = 0; - res = splice(param->remsock, NULL, pipesrv[1], NULL, MIN(MAXSPLICE - 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); #ifdef WITHLOG log("server to pipe splice finished\n"); #if WITHLOG > 1 @@ -586,7 +603,7 @@ log("done read from server to pipe\n"); param->nreads++; param->statssrv64 += res; inserverpipe += res; - if(inserverpipe >= MAXSPLICE) TOSERVERPIPE = 0; + if(inserverpipe >= PIPESIZE) TOSERVERPIPE = 0; if(param->bandlimfunc) { int sl1; sl1 = (*param->bandlimfunc)(param, res, 0); @@ -876,7 +893,7 @@ log("server terminated connection"); // } #ifdef WITHSPLICE { - if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < MAXSPLICE){ + if(splicecli && fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < PIPESIZE){ if(!after){ #ifdef WITHLOG log("wait writing to client pipe"); @@ -916,7 +933,7 @@ log("ready reading from client pipe"); } fdsc++; } - if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < MAXSPLICE){ + if(splicesrv && fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < PIPESIZE){ if(!after){ #ifdef WITHLOG log("wait writing to server pipe");