|
|
@@ -1,6 +1,6 @@
|
|
|
/*
|
|
|
3APA3A simpliest proxy server
|
|
|
- (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
|
|
|
+ (c) 2002-2020 by Vladimir Dubrovin <3proxy@3proxy.ru>
|
|
|
|
|
|
please read License Agreement
|
|
|
|
|
|
@@ -8,6 +8,15 @@
|
|
|
|
|
|
#include "proxy.h"
|
|
|
|
|
|
+#ifdef WITHLOG
|
|
|
+#if WITHLOG > 1
|
|
|
+char logbuf[1024];
|
|
|
+#endif
|
|
|
+#define log(X) dolog(param,X)
|
|
|
+#else
|
|
|
+#define log(X)
|
|
|
+#endif
|
|
|
+
|
|
|
#ifdef WITHSPLICE
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
@@ -25,565 +34,641 @@ 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
|
|
|
|
|
|
-#define RETURN(xxx) { res = xxx; goto CLEANRET; }
|
|
|
-#define MIN(a,b) ((a>b)?b:a)
|
|
|
|
|
|
#define MAXSPLICE 65536
|
|
|
|
|
|
+#endif
|
|
|
+
|
|
|
+#define MIN(a,b) ((a>b)?b:a)
|
|
|
+#define RETURN(xxx) { res = xxx; goto CLEANRET; }
|
|
|
|
|
|
-int splicemap(struct clientparam * param, int timeo){
|
|
|
- struct pollfd fds[2];
|
|
|
+int sockmap(struct clientparam * param, int timeo, int usesplice){
|
|
|
+ uint64_t fromclient=0x7fffffffffffffff, fromserver =0x7fffffffffffffff;
|
|
|
+ uint64_t inclientbuf = 0, inserverbuf = 0;
|
|
|
+ int FROMCLIENT = 1, TOCLIENTBUF = 1, FROMCLIENTBUF = 1, TOSERVER = 1,
|
|
|
+ FROMSERVER = 1, TOSERVERBUF = 1, FROMSERVERBUF = 1, TOCLIENT = 1;
|
|
|
+ int HASERROR=0;
|
|
|
+ int CLIENTTERM = 0, SERVERTERM = 0;
|
|
|
+ int after = 0;
|
|
|
+ struct pollfd fds[6];
|
|
|
struct pollfd *fdsp = fds;
|
|
|
- int fdsc = 2;
|
|
|
- int pipesrv[2] = {-1,-1};
|
|
|
- int pipecli[2] = {-1,-1};
|
|
|
- uint64_t sent=0, received=0;
|
|
|
- SASIZETYPE sasize;
|
|
|
- int res = 0, stop = 0;
|
|
|
- int srvstate = 0, clistate = 0;
|
|
|
- int srvsockstate = 0, clisockstate = 0;
|
|
|
- int insrvpipe = 0, inclipipe = 0;
|
|
|
- int rfromserver = 0, rfromclient = 0;
|
|
|
+ int fdsc = 0;
|
|
|
int sleeptime = 0;
|
|
|
- int needcontinue;
|
|
|
- int tosend;
|
|
|
+ FILTER_ACTION action;
|
|
|
+ int res;
|
|
|
+ SASIZETYPE sasize;
|
|
|
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ uint64_t inclientpipe = 0, inserverpipe = 0;
|
|
|
+ int TOCLIENTPIPE = 0, FROMCLIENTPIPE = 0, TOSERVERPIPE = 0, FROMSERVERPIPE = 0;
|
|
|
+ int pipesrv[2] = {-1,-1};
|
|
|
+ int pipecli[2] = {-1,-1};
|
|
|
|
|
|
- tosend = param->srvinbuf - param->srvoffset;
|
|
|
- if(!param->waitclient64 && tosend){
|
|
|
- needcontinue = 1;
|
|
|
- if(param->waitserver64 && param->waitserver64 <= tosend){
|
|
|
- needcontinue = 0;
|
|
|
- tosend = param->waitserver64;
|
|
|
- }
|
|
|
- if(socksend(param->clisock, param->srvbuf + param->srvoffset, tosend, conf.timeouts[STRING_S]) != tosend){
|
|
|
- return 96;
|
|
|
- }
|
|
|
- if(!needcontinue){
|
|
|
- param->srvoffset += tosend;
|
|
|
- if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0;
|
|
|
- return 98;
|
|
|
- }
|
|
|
- received += tosend;
|
|
|
- param->srvoffset = param->srvinbuf = 0;
|
|
|
+ if(param->operation == UDPASSOC) usesplice = 0;
|
|
|
+ if(usesplice){
|
|
|
+ TOCLIENTPIPE = FROMCLIENTPIPE = TOSERVERPIPE = FROMSERVERPIPE = 1;
|
|
|
+ TOCLIENTBUF = TOSERVERBUF = 0;
|
|
|
+ if(pipe2(pipecli, O_NONBLOCK) < 0) RETURN (21);
|
|
|
+ if(pipe2(pipesrv, O_NONBLOCK) < 0) RETURN (21);
|
|
|
}
|
|
|
- tosend = param->cliinbuf - param->clioffset;
|
|
|
- if(!param->waitserver64 && tosend){
|
|
|
- needcontinue = 1;
|
|
|
- if(param->waitclient64 && param->waitclient64 <= tosend){
|
|
|
- needcontinue = 0;
|
|
|
- tosend = param->waitclient64;
|
|
|
- }
|
|
|
- if(socksend(param->remsock, param->clibuf + param->clioffset, tosend, conf.timeouts[STRING_S]) != tosend){
|
|
|
- return 97;
|
|
|
- }
|
|
|
- param->nwrites++;
|
|
|
- param->statscli64 += tosend;
|
|
|
+#endif
|
|
|
|
|
|
- if(!needcontinue){
|
|
|
- param->clioffset += tosend;
|
|
|
- if(param->clioffset == param->cliinbuf) param->clioffset = param->cliinbuf = 0;
|
|
|
- return 99;
|
|
|
- }
|
|
|
- sent += tosend;
|
|
|
- param->clioffset = param->cliinbuf = 0;
|
|
|
+ inserverbuf = param->srvinbuf - param->srvoffset;
|
|
|
+ inclientbuf = param->cliinbuf - param->clioffset;
|
|
|
+
|
|
|
+ if(param->waitclient64) {
|
|
|
+ fromclient = param->waitclient64;
|
|
|
+ fromserver = 0;
|
|
|
+ inserverbuf = 0;
|
|
|
+ TOCLIENT = 0;
|
|
|
+ FROMSERVER = 0;
|
|
|
}
|
|
|
-
|
|
|
- if(!param->waitserver64 && !param->waitclient64){
|
|
|
- myfree(param->srvbuf);
|
|
|
- param->srvbuf = NULL;
|
|
|
- param->srvbufsize = 0;
|
|
|
- myfree(param->clibuf);
|
|
|
- param->clibuf = NULL;
|
|
|
- param->clibufsize = 0;
|
|
|
- param->srvinbuf = param->srvoffset = param->cliinbuf = param->clioffset = 0;
|
|
|
+ if(param->waitserver64) {
|
|
|
+ fromserver = param->waitserver64;
|
|
|
+ fromclient = 0;
|
|
|
+ inclientbuf = 0;
|
|
|
+ TOSERVER = 0;
|
|
|
+ FROMCLIENT = 0;
|
|
|
}
|
|
|
-
|
|
|
- param->res = 0;
|
|
|
- if(pipe(pipecli) < 0) RETURN(21);
|
|
|
- if(pipe(pipesrv) < 0) RETURN(21);
|
|
|
-
|
|
|
- fds[0].fd = param->clisock;
|
|
|
- fds[1].fd = param->remsock;
|
|
|
-
|
|
|
- while((!stop || (inclipipe && !srvsockstate) || (insrvpipe && !clisockstate)) && !conf.timetoexit){
|
|
|
-
|
|
|
- param->cycles++;
|
|
|
-#ifdef NOIPV6
|
|
|
- sasize = sizeof(struct sockaddr_in);
|
|
|
-#else
|
|
|
- sasize = sizeof(struct sockaddr_in6);
|
|
|
-#endif
|
|
|
- fds[0].events = fds[1].events = 0;
|
|
|
- fds[0].revents = fds[1].revents = 0;
|
|
|
-
|
|
|
- if(srvstate && !clisockstate && !param->waitclient64 && param->clisock != INVALID_SOCKET){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: will send to client");
|
|
|
-#endif
|
|
|
- fds[0].events |= POLLOUT;
|
|
|
- }
|
|
|
- rfromserver = MAXSPLICE - insrvpipe;
|
|
|
- if(param->waitserver64) rfromserver = MIN(MAXSPLICE, param->waitserver64 - (received + insrvpipe));
|
|
|
- if(srvstate < 2 && !srvsockstate && rfromserver > 0 && param->remsock != INVALID_SOCKET) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: will recv from server");
|
|
|
-#endif
|
|
|
- fds[1].events |= (POLLIN|POLLRDHUP);
|
|
|
- }
|
|
|
- if(clistate && !srvsockstate && !param->waitserver64 && param->remsock != INVALID_SOCKET){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: will send to server");
|
|
|
-#endif
|
|
|
- fds[1].events |= POLLOUT;
|
|
|
- }
|
|
|
- rfromclient = MAXSPLICE - inclipipe;
|
|
|
- if(param->waitclient64) rfromclient = MIN(MAXSPLICE, param->waitclient64 - (sent + inclipipe));
|
|
|
- if(clistate < 2 && !clisockstate && rfromclient > 0 && param->clisock != INVALID_SOCKET) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: will recv from client");
|
|
|
-#endif
|
|
|
- fds[0].events |= (POLLIN|POLLRDHUP);
|
|
|
- }
|
|
|
- if(!fds[0].events && !fds[1].events) RETURN (666);
|
|
|
- if(fds[0].fd == INVALID_SOCKET){
|
|
|
- fdsp = fds +1;
|
|
|
- fdsc = 1;
|
|
|
- }
|
|
|
- else if(fds[1].fd == INVALID_SOCKET){
|
|
|
- fdsp = fds;
|
|
|
- fdsc = 1;
|
|
|
- }
|
|
|
- else {
|
|
|
- fdsp = fds;
|
|
|
- fdsc = 2;
|
|
|
- }
|
|
|
- res = so._poll(fdsp, fdsc, timeo*1000);
|
|
|
- if(res < 0){
|
|
|
- if(errno == EINTR) so._poll(NULL, 0, 1);
|
|
|
- else if(errno != EAGAIN) RETURN(91);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if(res < 1){
|
|
|
- RETURN(92);
|
|
|
- }
|
|
|
- if( (fds[0].revents & (POLLERR|POLLNVAL)) || (fds[1].revents & (POLLERR|POLLNVAL))) {
|
|
|
- RETURN(90);
|
|
|
- }
|
|
|
- if( (fds[0].revents & (POLLHUP|POLLRDHUP))) {
|
|
|
- stop = clisockstate = 1;
|
|
|
- }
|
|
|
- if( (fds[1].revents & (POLLERR|POLLNVAL|POLLHUP|POLLRDHUP)) && !(fds[1].revents & POLLIN)){
|
|
|
- stop = srvsockstate = 1;
|
|
|
- }
|
|
|
- if((fds[0].revents & POLLOUT)){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: spliced send to client");
|
|
|
-#endif
|
|
|
- res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, insrvpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
|
|
- if(res <= 0) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: send to client error");
|
|
|
-#endif
|
|
|
- if(errno == EINTR) so._poll(NULL, 0, 1);
|
|
|
- else if(errno != EAGAIN) RETURN(96);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if(res){
|
|
|
- insrvpipe -= res;
|
|
|
- received += res;
|
|
|
-
|
|
|
- if(param->bandlimfunc) {
|
|
|
- sleeptime = (*param->bandlimfunc)(param, res, 0);
|
|
|
- }
|
|
|
- srvstate = 0;
|
|
|
- }
|
|
|
- if(param->waitserver64 && param->waitserver64 <= received){
|
|
|
- RETURN (98);
|
|
|
- }
|
|
|
- }
|
|
|
- if((fds[1].revents & POLLOUT)){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: spliced send to server");
|
|
|
-#endif
|
|
|
- res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, inclipipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
|
|
- if(res <= 0) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: send to server error");
|
|
|
-#endif
|
|
|
- if(errno == EINTR) so._poll(NULL, 0, 1);
|
|
|
- else if(errno != EAGAIN) RETURN(97);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if(res){
|
|
|
- inclipipe -= res;
|
|
|
- sent += res;
|
|
|
- param->nwrites++;
|
|
|
- param->statscli64 += res;
|
|
|
-
|
|
|
- if(param->bandlimfunc) {
|
|
|
- int sl1;
|
|
|
- sl1 = (*param->bandlimfunc)(param, 0, res);
|
|
|
- if(sl1 > sleeptime) sleeptime = sl1;
|
|
|
- }
|
|
|
- clistate = 0;
|
|
|
- }
|
|
|
- if(param->waitclient64 && param->waitclient64 <= sent){
|
|
|
- RETURN (99);
|
|
|
- }
|
|
|
- }
|
|
|
- if ((fds[0].revents & POLLIN) || clisockstate == 1) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: recv from client");
|
|
|
-#endif
|
|
|
- res = splice(param->clisock, NULL, pipecli[1], NULL, rfromclient, SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
|
|
- if (res < 0){
|
|
|
- if(errno == EINTR) so._poll(NULL, 0, 1);
|
|
|
- else if(errno != EAGAIN) RETURN(94);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (res==0) {
|
|
|
- clisockstate = 2;
|
|
|
- stop = 1;
|
|
|
- }
|
|
|
- else {
|
|
|
- inclipipe += res;
|
|
|
- clistate = 1;
|
|
|
- if(insrvpipe >= MAXSPLICE) clistate = 2;
|
|
|
- }
|
|
|
- }
|
|
|
- if ((fds[1].revents & POLLIN) || srvsockstate == 1) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: recv from server");
|
|
|
-#endif
|
|
|
- res = splice(param->remsock, NULL, pipesrv[1], NULL, rfromserver, SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
|
|
|
- if (res < 0){
|
|
|
- if(errno == EINTR) so._poll(NULL, 0, 1);
|
|
|
- else if(errno != EAGAIN) RETURN(93);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (res==0) {
|
|
|
- srvsockstate = 2;
|
|
|
- stop = 1;
|
|
|
- }
|
|
|
- else {
|
|
|
- insrvpipe += res;
|
|
|
- param->statssrv64 += res;
|
|
|
- param->nreads++;
|
|
|
- srvstate = 1;
|
|
|
- if(insrvpipe >= MAXSPLICE) srvstate = 2;
|
|
|
- }
|
|
|
- }
|
|
|
- if(sleeptime > 0) {
|
|
|
- if(sleeptime > (timeo * 1000)){RETURN (95);}
|
|
|
- so._poll(NULL, 0, sleeptime);
|
|
|
- sleeptime = 0;
|
|
|
- }
|
|
|
+ if(param->operation == UDPASSOC && param->srv->singlepacket){
|
|
|
+ fromclient = inclientbuf;
|
|
|
+ FROMCLIENT = 0;
|
|
|
}
|
|
|
-
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "splice: finished with mapping");
|
|
|
-#endif
|
|
|
-
|
|
|
-CLEANRET:
|
|
|
-
|
|
|
- if(pipecli[0] >= 0) close(pipecli[0]);
|
|
|
- if(pipecli[1] >= 0) close(pipecli[1]);
|
|
|
- if(pipesrv[0] >= 0) close(pipesrv[0]);
|
|
|
- if(pipesrv[1] >= 0) close(pipesrv[1]);
|
|
|
-
|
|
|
- return res;
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
-
|
|
|
-int sockmap(struct clientparam * param, int timeo){
|
|
|
- int res=0;
|
|
|
- uint64_t sent=0, received=0;
|
|
|
- SASIZETYPE sasize;
|
|
|
- struct pollfd fds[2];
|
|
|
- int sleeptime = 0, stop = 0;
|
|
|
- unsigned minsize;
|
|
|
- unsigned bufsize;
|
|
|
- FILTER_ACTION action;
|
|
|
- int retcode = 0;
|
|
|
-
|
|
|
- bufsize = SRVBUFSIZE;
|
|
|
-
|
|
|
- minsize = (param->service == S_UDPPM || param->service == S_TCPPM)? bufsize - 1 : (bufsize>>2);
|
|
|
-
|
|
|
- fds[0].fd = param->clisock;
|
|
|
- fds[1].fd = param->remsock;
|
|
|
-
|
|
|
-
|
|
|
- if(param->cliinbuf == param->clioffset) param->cliinbuf = param->clioffset = 0;
|
|
|
- if(param->srvinbuf == param->srvoffset) param->srvinbuf = param->srvoffset = 0;
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "Starting sockets mapping");
|
|
|
+ if(inserverbuf >= fromserver) FROMSERVER = 0;
|
|
|
+ if(inclientbuf >= fromclient) FROMCLIENT = 0;
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ if(!usesplice)
|
|
|
#endif
|
|
|
- if(!param->waitclient64){
|
|
|
- if(!param->srvbuf && (!(param->srvbuf=myalloc(bufsize)) || !(param->srvbufsize = bufsize))){
|
|
|
- return (21);
|
|
|
+ {
|
|
|
+ if(fromserver && !param->srvbuf && (!(param->srvbuf=myalloc(SRVBUFSIZE)) || !(param->srvbufsize = SRVBUFSIZE))){
|
|
|
+ RETURN (21);
|
|
|
}
|
|
|
- }
|
|
|
- if(!param->waitserver64){
|
|
|
- if(!param->clibuf && (!(param->clibuf=myalloc(bufsize)) || !(param->clibufsize = bufsize))){
|
|
|
- return (21);
|
|
|
+ if(fromclient && !param->clibuf && (!(param->clibuf=myalloc(SRVBUFSIZE)) || !(param->clibufsize = SRVBUFSIZE))){
|
|
|
+ RETURN (21);
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
+ if(param->srvinbuf == param->srvoffset) param->srvinbuf =param->srvoffset = 0;
|
|
|
+ if(param->cliinbuf == param->clioffset) param->cliinbuf =param->clioffset = 0;
|
|
|
+ if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0;
|
|
|
+ if(param->srvbufsize == param->srvinbuf) TOSERVERBUF = 0;
|
|
|
|
|
|
action = handlepredatflt(param);
|
|
|
if(action == HANDLED){
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if(action != PASS) return 19;
|
|
|
- if(!param->nolongdatfilter){
|
|
|
- if(param->cliinbuf > param->clioffset){
|
|
|
- action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, param->clioffset, (int *)¶m->cliinbuf);
|
|
|
- if(action == HANDLED){
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if(action != PASS) return 19;
|
|
|
- }
|
|
|
- if(param->srvinbuf > param->srvoffset){
|
|
|
- action = handledatfltsrv(param, ¶m->srvbuf, (int *)¶m->srvbufsize, param->srvoffset, (int *)¶m->srvinbuf);
|
|
|
- if(action == HANDLED){
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if(action != PASS) return 19;
|
|
|
- }
|
|
|
+ RETURN(0);
|
|
|
}
|
|
|
+ if(action != PASS) RETURN(19);
|
|
|
|
|
|
+ while(
|
|
|
+ ((!CLIENTTERM) && (inserverbuf
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ || inserverpipe
|
|
|
+#endif
|
|
|
+ || (!SERVERTERM && fromserver)))
|
|
|
+ ||
|
|
|
+ ((!SERVERTERM) && (inclientbuf
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ || inclientpipe
|
|
|
+#endif
|
|
|
+ || (!CLIENTTERM && fromclient)))
|
|
|
+ ){
|
|
|
|
|
|
|
|
|
- while (!stop&&!conf.timetoexit){
|
|
|
- param->cycles++;
|
|
|
-#ifdef NOIPV6
|
|
|
- sasize = sizeof(struct sockaddr_in);
|
|
|
-#else
|
|
|
- sasize = sizeof(struct sockaddr_in6);
|
|
|
+#if WITHLOG > 1
|
|
|
+sprintf(logbuf, "int FROMCLIENT = %d, TOCLIENTBUF = %d, FROMCLIENTBUF = %d, TOSERVER = %d, "
|
|
|
+ "FROMSERVER = %d, TOSERVERBUF = %d, FROMSERVERBUF = %d, TOCLIENT = %d; inclientbuf=%d; "
|
|
|
+ "inserverbuf=%d, CLIENTTERM = %d, SERVERTERM =%d, fromserver=%u, fromclient=%u"
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ ", inserverpipe=%d, inclentpipe=%d "
|
|
|
+ "TOCLIENTPIPE=%d FROMCLIENTPIPE==%d TOSERVERPIPE==%d FROMSERVERPIPE=%d"
|
|
|
+#endif
|
|
|
+ ,
|
|
|
+ FROMCLIENT, TOCLIENTBUF, FROMCLIENTBUF, TOSERVER,
|
|
|
+ FROMSERVER, TOSERVERBUF, FROMSERVERBUF, TOCLIENT,
|
|
|
+ (int)inclientbuf, (int)inserverbuf, CLIENTTERM, SERVERTERM,
|
|
|
+ (unsigned)fromserver, (unsigned)fromclient
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ ,(int)inserverpipe, (int)inclientpipe,
|
|
|
+ TOCLIENTPIPE, FROMCLIENTPIPE, TOSERVERPIPE, FROMSERVERPIPE
|
|
|
+#endif
|
|
|
+ );
|
|
|
+log(logbuf);
|
|
|
#endif
|
|
|
+
|
|
|
+ if(sleeptime > 0) {
|
|
|
+ if(sleeptime > (timeo * 1000)){RETURN (92);}
|
|
|
+ memset(fds, 0, sizeof(fds));
|
|
|
+ fds[0].fd = param->clisock;
|
|
|
+ fds[1].fd = param->remsock;
|
|
|
+#ifdef POLLRDHUP
|
|
|
+ fds[0].events = POLLRDHUP;
|
|
|
+ fds[1].events = POLLRDHUP;
|
|
|
+#endif
|
|
|
+ so._poll(fds, 2, sleeptime);
|
|
|
+ sleeptime = 0;
|
|
|
+ }
|
|
|
+ if((param->srv->logdumpsrv && (param->statssrv64 > param->srv->logdumpsrv)) ||
|
|
|
+ (param->srv->logdumpcli && (param->statscli64 > param->srv->logdumpcli)))
|
|
|
+ dolog(param, NULL);
|
|
|
+
|
|
|
if(param->version < conf.version){
|
|
|
- if((res = (*param->srv->authfunc)(param)) && res != 2 && !param->srv->noforce) {return(res);}
|
|
|
+ if(!param->srv->noforce && (res = (*param->srv->authfunc)(param)) && res != 2) {RETURN(res);}
|
|
|
param->paused = conf.paused;
|
|
|
param->version = conf.version;
|
|
|
}
|
|
|
+
|
|
|
if((param->maxtrafin64 && param->statssrv64 >= param->maxtrafin64) || (param->maxtrafout64 && param->statscli64 >= param->maxtrafout64)){
|
|
|
- return (10);
|
|
|
- }
|
|
|
- if((param->srv->logdumpsrv && (param->statssrv64 > param->srv->logdumpsrv)) ||
|
|
|
- (param->srv->logdumpcli && (param->statscli64 > param->srv->logdumpcli)))
|
|
|
- (*param->srv->logfunc)(param, NULL);
|
|
|
- fds[0].events = fds[1].events = 0;
|
|
|
- if(param->srvinbuf > param->srvoffset && !param->waitclient64) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "will send to client");
|
|
|
-#endif
|
|
|
- fds[0].events |= POLLOUT;
|
|
|
- }
|
|
|
- if((param->srvbufsize - param->srvinbuf) > minsize && !param->waitclient64 && (!param->waitserver64 ||(received + param->srvinbuf - param->srvoffset < param->waitserver64))) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "Will recv from server");
|
|
|
-#endif
|
|
|
- fds[1].events |= POLLIN;
|
|
|
+ RETURN (10);
|
|
|
}
|
|
|
|
|
|
- if(param->cliinbuf > param->clioffset && !param->waitserver64) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "Will send to server");
|
|
|
+ if(inclientbuf && TOSERVER){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("send to server from buf");
|
|
|
#endif
|
|
|
- fds[1].events |= POLLOUT;
|
|
|
- }
|
|
|
- if((param->clibufsize - param->cliinbuf) > minsize && !param->waitserver64 &&(!param->srv->singlepacket || param->service != S_UDPPM) ) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "Will recv from client");
|
|
|
-#endif
|
|
|
- fds[0].events |= POLLIN;
|
|
|
- }
|
|
|
- if(!fds[0].events && !fds[1].events) return 666;
|
|
|
- res = so._poll(fds, 2, timeo*1000);
|
|
|
- if(res < 0){
|
|
|
- if(errno != EAGAIN && errno != EINTR) return 91;
|
|
|
- if(errno == EINTR) usleep(SLEEPTIME);
|
|
|
- continue;
|
|
|
- }
|
|
|
- if(res < 1){
|
|
|
- return 92;
|
|
|
- }
|
|
|
- if( (fds[0].revents & (POLLERR|POLLNVAL
|
|
|
-#ifndef WITH_WSAPOLL
|
|
|
- |POLLHUP
|
|
|
-#endif
|
|
|
- )) && !(fds[0].revents & POLLIN)) {
|
|
|
- fds[0].revents = 0;
|
|
|
- stop = 1;
|
|
|
- retcode = 90;
|
|
|
- }
|
|
|
- if( (fds[1].revents & (POLLERR|POLLNVAL
|
|
|
-#ifndef WITH_WSAPOLL
|
|
|
- |POLLHUP
|
|
|
-#endif
|
|
|
- )) && !(fds[1].revents & POLLIN)){
|
|
|
- fds[1].revents = 0;
|
|
|
- stop = 1;
|
|
|
- retcode = 90;
|
|
|
- }
|
|
|
- if((fds[0].revents & POLLOUT)){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "send to client");
|
|
|
-#endif
|
|
|
- if(param->bandlimfunc) {
|
|
|
- sleeptime = (*param->bandlimfunc)(param, param->srvinbuf - param->srvoffset, 0);
|
|
|
- }
|
|
|
- res = so._sendto(param->clisock, (char *)param->srvbuf + param->srvoffset,(!param->waitserver64 || (param->waitserver64 - received) > (param->srvinbuf - param->srvoffset))? param->srvinbuf - param->srvoffset : (int)(param->waitserver64 - received), 0, (struct sockaddr*)¶m->sincr, sasize);
|
|
|
- if(res < 0) {
|
|
|
- if(errno != EAGAIN && errno != EINTR) return 96;
|
|
|
- if(errno == EINTR) usleep(SLEEPTIME);
|
|
|
- continue;
|
|
|
+ if(!param->nolongdatfilter){
|
|
|
+ action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, param->cliinbuf - res, (int *)¶m->cliinbuf);
|
|
|
+ if(action == HANDLED){
|
|
|
+ RETURN(0);
|
|
|
+ }
|
|
|
+ if(action != PASS) RETURN(19);
|
|
|
+ inclientbuf=param->cliinbuf - param->clioffset;
|
|
|
}
|
|
|
- param->srvoffset += res;
|
|
|
- received += res;
|
|
|
- if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0;
|
|
|
- if(param->waitserver64 && param->waitserver64<= received){
|
|
|
- return (98);
|
|
|
+ if(!inclientbuf){
|
|
|
+ param->clioffset = param->cliinbuf = 0;
|
|
|
+ if(fromclient) TOCLIENTBUF = 1;
|
|
|
}
|
|
|
- if(param->service == S_UDPPM && param->srv->singlepacket) {
|
|
|
- stop = 1;
|
|
|
+ sasize = sizeof(param->sinsr);
|
|
|
+ res = so._sendto(param->remsock, (char *)param->clibuf + param->clioffset, (int)MIN(inclientbuf, fromclient), 0, (struct sockaddr*)¶m->sinsr, sasize);
|
|
|
+ if(res <= 0) TOSERVER = 0;
|
|
|
+ else {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done send to server from buf");
|
|
|
+#endif
|
|
|
+ param->nwrites++;
|
|
|
+ param->statscli64 += res;
|
|
|
+ inclientbuf -= res;
|
|
|
+ fromclient -= res;
|
|
|
+ param->clioffset += res;
|
|
|
+ if(param->clioffset == param->cliinbuf)param->clioffset = param->cliinbuf = 0;
|
|
|
+ if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1;
|
|
|
+ if(param->bandlimfunc) {
|
|
|
+ int sl1;
|
|
|
+ sl1 = (*param->bandlimfunc)(param, 0, res);
|
|
|
+ if(sl1 > sleeptime) sleeptime = sl1;
|
|
|
+ }
|
|
|
+ continue;
|
|
|
}
|
|
|
}
|
|
|
- if((fds[1].revents & POLLOUT)){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "send to server");
|
|
|
+ if(inserverbuf && TOCLIENT){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("send to client from buf");
|
|
|
#endif
|
|
|
- if(param->bandlimfunc) {
|
|
|
- int sl1;
|
|
|
-
|
|
|
- sl1 = (*param->bandlimfunc)(param, 0, param->cliinbuf - param->clioffset);
|
|
|
- if(sl1 > sleeptime) sleeptime = sl1;
|
|
|
+ if(!param->nolongdatfilter){
|
|
|
+ action = handledatfltsrv(param, ¶m->srvbuf, (int *)¶m->srvbufsize, param->srvinbuf - res, (int *)¶m->srvinbuf);
|
|
|
+ if(action == HANDLED){
|
|
|
+ RETURN(0);
|
|
|
+ }
|
|
|
+ if(action != PASS) RETURN(19);
|
|
|
+ inserverbuf = param->srvinbuf - param->srvoffset;
|
|
|
}
|
|
|
- res = so._sendto(param->remsock, (char *)param->clibuf + param->clioffset, (!param->waitclient64 || (param->waitclient64 - sent) > (param->cliinbuf - param->clioffset))? param->cliinbuf - param->clioffset : (int)(param->waitclient64 - sent), 0, (struct sockaddr*)¶m->sinsr, sasize);
|
|
|
- if(res < 0) {
|
|
|
- if(errno != EAGAIN && errno != EINTR) return 97;
|
|
|
- if(errno == EINTR) usleep(SLEEPTIME);
|
|
|
+ if(!inserverbuf){
|
|
|
+ param->srvinbuf = param->srvoffset = 0;
|
|
|
continue;
|
|
|
}
|
|
|
- param->clioffset += res;
|
|
|
- if(param->clioffset == param->cliinbuf) param->clioffset = param->cliinbuf = 0;
|
|
|
- sent += res;
|
|
|
- param->nwrites++;
|
|
|
- param->statscli64 += res;
|
|
|
- if(param->waitclient64 && param->waitclient64<= sent) {
|
|
|
- return (99);
|
|
|
+ sasize = sizeof(param->sincr);
|
|
|
+ res = so._sendto(param->clisock, (char *)param->srvbuf + param->srvoffset, (int)MIN(inserverbuf,fromserver), 0, (struct sockaddr*)¶m->sincr, sasize);
|
|
|
+ if(res <= 0) TOCLIENT = 0;
|
|
|
+ else {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done send to client from buf");
|
|
|
+#endif
|
|
|
+ inserverbuf -= res;
|
|
|
+ fromserver -= res;
|
|
|
+ param->srvoffset += res;
|
|
|
+ if(param->srvoffset == param->srvinbuf)param->srvoffset = param->srvinbuf =0;
|
|
|
+ if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1;
|
|
|
+ continue;
|
|
|
}
|
|
|
}
|
|
|
- if ((fds[0].revents & POLLIN)
|
|
|
-#ifdef WITH_WSAPOLL
|
|
|
- ||(fds[0].revents & POLLHUP)
|
|
|
-#endif
|
|
|
- ) {
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "recv from client");
|
|
|
-#endif
|
|
|
- res = so._recvfrom(param->clisock, (char *)param->clibuf + param->cliinbuf, param->clibufsize - param->cliinbuf, 0, (struct sockaddr *)¶m->sincr, &sasize);
|
|
|
- if (res==0) {
|
|
|
- so._shutdown(param->clisock, SHUT_RDWR);
|
|
|
- so._closesocket(param->clisock);
|
|
|
- fds[0].fd = param->clisock = INVALID_SOCKET;
|
|
|
- stop = 1;
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ if(usesplice){
|
|
|
+ if(inclientpipe && !inclientbuf && FROMCLIENTPIPE && TOSERVER){
|
|
|
+#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);
|
|
|
+ if(res >0) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done send to server from pipe");
|
|
|
+#endif
|
|
|
+ param->nwrites++;
|
|
|
+ param->statscli64 += res;
|
|
|
+ inclientpipe -= res;
|
|
|
+ fromclient -= res;
|
|
|
+ if(param->bandlimfunc) {
|
|
|
+ int sl1;
|
|
|
+ sl1 = (*param->bandlimfunc)(param, 0, res);
|
|
|
+ if(sl1 > sleeptime) sleeptime = sl1;
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ FROMCLIENTPIPE = TOSERVER = 0;
|
|
|
+ }
|
|
|
}
|
|
|
- else {
|
|
|
- if (res < 0){
|
|
|
- if(errno != EAGAIN && errno != EINTR) return 94;
|
|
|
- if(errno == EINTR) usleep(SLEEPTIME);
|
|
|
+ if(inserverpipe && !inserverbuf && FROMSERVERPIPE && TOCLIENT){
|
|
|
+#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);
|
|
|
+ if(res > 0) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done send to client from pipe");
|
|
|
+#endif
|
|
|
+ inserverpipe -= res;
|
|
|
+ fromserver -= res;
|
|
|
+ if(fromserver)TOSERVERPIPE = 1;
|
|
|
continue;
|
|
|
}
|
|
|
- param->cliinbuf += res;
|
|
|
- if(!param->nolongdatfilter){
|
|
|
- action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, param->cliinbuf - res, (int *)¶m->cliinbuf);
|
|
|
- if(action == HANDLED){
|
|
|
- return 0;
|
|
|
+ else {
|
|
|
+ FROMSERVERPIPE = TOCLIENT = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(fromclient>inclientpipe && FROMCLIENT && TOCLIENTPIPE){
|
|
|
+ int error;
|
|
|
+ socklen_t len=sizeof(error);
|
|
|
+#ifdef WITHLOG
|
|
|
+log("read from client to pipe");
|
|
|
+#endif
|
|
|
+ res = splice(param->clisock, NULL, pipecli[1], NULL, (int)MIN((uint64_t)MAXSPLICE - inclientpipe, (uint64_t)fromclient-inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
|
|
+ if(res <= 0) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("read failed");
|
|
|
+#endif
|
|
|
+ FROMCLIENT = TOCLIENTPIPE = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done read from client to pipe");
|
|
|
+#endif
|
|
|
+ inclientpipe += res;
|
|
|
+ if(inclientpipe >= MAXSPLICE) TOCLIENTPIPE = 0;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(fromserver > inserverpipe && FROMSERVER && TOSERVERPIPE){
|
|
|
+ int error;
|
|
|
+ socklen_t len=sizeof(error);
|
|
|
+#ifdef WITHLOG
|
|
|
+log("read from server to pipe\n");
|
|
|
+#endif
|
|
|
+ res = splice(param->remsock, NULL, pipesrv[1], NULL, MIN(MAXSPLICE - inclientpipe, fromserver - inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE);
|
|
|
+#ifdef WITHLOG
|
|
|
+log("splice finished\n");
|
|
|
+#endif
|
|
|
+ if(res <= 0) {
|
|
|
+ FROMSERVER = TOSERVERPIPE = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done read from server to pipe\n");
|
|
|
+#endif
|
|
|
+ param->nreads++;
|
|
|
+ param->statssrv64 += res;
|
|
|
+ inserverpipe += res;
|
|
|
+ if(inserverpipe >= MAXSPLICE) TOSERVERPIPE = 0;
|
|
|
+ if(param->bandlimfunc) {
|
|
|
+ int sl1;
|
|
|
+ sl1 = (*param->bandlimfunc)(param, 1, res);
|
|
|
+ if(sl1 > sleeptime) sleeptime = sl1;
|
|
|
+ }
|
|
|
+ if(param->operation == UDPASSOC && param->srv->singlepacket){
|
|
|
+ fromserver = inserverpipe;
|
|
|
+ FROMSERVER = 0;
|
|
|
}
|
|
|
- if(action != PASS) return 19;
|
|
|
}
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ if(fromclient > inclientbuf && FROMCLIENT && TOCLIENTBUF){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("read from client to buf");
|
|
|
+#endif
|
|
|
+ sasize = sizeof(param->sincr);
|
|
|
+ res = so._recvfrom(param->clisock, (char *)param->clibuf + param->cliinbuf, (int)MIN((uint64_t)param->clibufsize - param->cliinbuf, fromclient-inclientbuf), 0, (struct sockaddr *)¶m->sincr, &sasize);
|
|
|
+ if(res <= 0) {
|
|
|
+ if(!errno)CLIENTTERM = 1;
|
|
|
+ FROMCLIENT = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done read from client to buf");
|
|
|
+#endif
|
|
|
+ inclientbuf += res;
|
|
|
+ param->cliinbuf += res;
|
|
|
+ if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ if(fromserver > inserverbuf && FROMSERVER && TOSERVERBUF){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("read from server to buf");
|
|
|
+#endif
|
|
|
+ sasize = sizeof(param->sinsr);
|
|
|
+ res = so._recvfrom(param->remsock, (char *)param->srvbuf + param->srvinbuf, (int)MIN((uint64_t)param->srvbufsize - param->srvinbuf, fromserver-inserverbuf), 0, (struct sockaddr *)¶m->sinsr, &sasize);
|
|
|
+ if(res <= 0) {
|
|
|
+ if(!errno) SERVERTERM = 1;
|
|
|
+ FROMSERVER = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("done read from server to buf");
|
|
|
+#endif
|
|
|
+ param->nreads++;
|
|
|
+ param->statssrv64 += res;
|
|
|
+ inserverbuf += res;
|
|
|
+ param->srvinbuf += res;
|
|
|
+ if(param->bandlimfunc) {
|
|
|
+ int sl1;
|
|
|
+ sl1 = (*param->bandlimfunc)(param, 1, res);
|
|
|
+ if(sl1 > sleeptime) sleeptime = sl1;
|
|
|
+ }
|
|
|
+ if(param->srvbufsize == param->srvinbuf) TOSERVERBUF = 0;
|
|
|
+ if(param->operation == UDPASSOC && param->srv->singlepacket){
|
|
|
+ fromserver = inserverbuf;
|
|
|
+ FROMSERVER = 0;
|
|
|
+ }
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- if (!stop && ((fds[1].revents & POLLIN)
|
|
|
-#ifdef WITH_WSAPOLL
|
|
|
- ||(fds[1].revents & POLLHUP)
|
|
|
+ for(after = 0; after < 2; after ++){
|
|
|
+ fdsc = 0;
|
|
|
+ if(!after){
|
|
|
+ memset(fds, 0, sizeof(fds));
|
|
|
+ }
|
|
|
+ if(!CLIENTTERM){
|
|
|
+ if(!after){
|
|
|
+ fds[fdsc].fd = param->clisock;
|
|
|
+ if(fromclient && !FROMCLIENT && ((
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ !usesplice &&
|
|
|
#endif
|
|
|
- )) {
|
|
|
-#ifdef NOIPV6
|
|
|
- struct sockaddr_in sin;
|
|
|
-#else
|
|
|
- struct sockaddr_in6 sin;
|
|
|
+ TOCLIENTBUF)
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ || (usesplice)
|
|
|
+#endif
|
|
|
+ )){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait reading from client");
|
|
|
+#endif
|
|
|
+ fds[fdsc].events |= (POLLIN
|
|
|
+#ifdef POLLRDHUP
|
|
|
+ |POLLRDHUP
|
|
|
+#endif
|
|
|
+ );
|
|
|
+ }
|
|
|
+ if(!TOCLIENT && (inserverbuf
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ || inserverpipe
|
|
|
+#endif
|
|
|
+ )){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait writing to client");
|
|
|
+#endif
|
|
|
+ fds[fdsc].events |= POLLOUT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if(fds[fdsc].revents & (POLLERR|POLLNVAL)) {
|
|
|
+ CLIENTTERM = 1;
|
|
|
+ HASERROR |= 1;
|
|
|
+ }
|
|
|
+ else if(fds[fdsc].revents & (POLLHUP
|
|
|
+#ifdef POLLRDHUP
|
|
|
+ |POLLRDHUP
|
|
|
+#endif
|
|
|
+ )) {
|
|
|
+ CLIENTTERM = 1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if(fds[fdsc].revents & POLLIN) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready to read from client");
|
|
|
+#endif
|
|
|
+ FROMCLIENT = 1;
|
|
|
+ }
|
|
|
+ if(fds[fdsc].revents & POLLOUT) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready to write to client");
|
|
|
+#endif
|
|
|
+ TOCLIENT = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fdsc++;
|
|
|
+ }
|
|
|
+ if(!SERVERTERM){
|
|
|
+ if(!after){
|
|
|
+ fds[fdsc].fd = param->remsock;
|
|
|
+ if(fromserver && !FROMSERVER && ((
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ !usesplice &&
|
|
|
+#endif
|
|
|
+ TOSERVERBUF)
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ || (usesplice)
|
|
|
+#endif
|
|
|
+ )){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait reading from server");
|
|
|
+#endif
|
|
|
+ fds[fdsc].events |= (POLLIN
|
|
|
+#ifdef POLLRDHUP
|
|
|
+ |POLLRDHUP
|
|
|
#endif
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "recv from server");
|
|
|
+ );
|
|
|
+ }
|
|
|
+ if(!TOSERVER && (inclientbuf
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ || inclientpipe
|
|
|
+#endif
|
|
|
+ )){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait writing from server");
|
|
|
+#endif
|
|
|
+ fds[fdsc].events |= POLLOUT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if(fds[fdsc].revents & (POLLERR|POLLNVAL)) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("poll from server failed");
|
|
|
#endif
|
|
|
|
|
|
- sasize = sizeof(sin);
|
|
|
- res = so._recvfrom(param->remsock, (char *)param->srvbuf + param->srvinbuf, param->srvbufsize - param->srvinbuf, 0, (struct sockaddr *)&sin, &sasize);
|
|
|
- if (res==0) {
|
|
|
- so._shutdown(param->remsock, SHUT_RDWR);
|
|
|
- so._closesocket(param->remsock);
|
|
|
- fds[1].fd = param->remsock = INVALID_SOCKET;
|
|
|
- stop = 2;
|
|
|
+ SERVERTERM = 1;
|
|
|
+ HASERROR |=2;
|
|
|
+ }
|
|
|
+ if(fds[fdsc].revents & (POLLHUP
|
|
|
+#ifdef POLLRDHUP
|
|
|
+ |POLLRDHUP
|
|
|
+#endif
|
|
|
+ )) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("server terminated connection");
|
|
|
+#endif
|
|
|
+ SERVERTERM = 1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if(fds[fdsc].revents & POLLIN) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready to read from server");
|
|
|
+#endif
|
|
|
+ FROMSERVER = 1;
|
|
|
+ }
|
|
|
+ if(fds[fdsc].revents & POLLOUT) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready to write to server");
|
|
|
+#endif
|
|
|
+ TOSERVER = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fdsc++;
|
|
|
}
|
|
|
- else {
|
|
|
- if (res < 0){
|
|
|
- if(errno != EAGAIN && errno != EINTR) return 93;
|
|
|
- if(errno == EINTR) usleep(SLEEPTIME);
|
|
|
- continue;
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ if(usesplice){
|
|
|
+ if(fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < MAXSPLICE){
|
|
|
+ if(!after){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait writing to client pipe");
|
|
|
+#endif
|
|
|
+ fds[fdsc].fd = pipecli[1];
|
|
|
+ fds[fdsc].events |= POLLOUT;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){
|
|
|
+ RETURN(90);
|
|
|
+ }
|
|
|
+ if(fds[fdsc].revents & POLLOUT) {
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready to write to client pipe");
|
|
|
+#endif
|
|
|
+ TOCLIENTPIPE = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fdsc++;
|
|
|
}
|
|
|
- param->srvinbuf += res;
|
|
|
- param->nreads++;
|
|
|
- param->statssrv64 += res;
|
|
|
- if(!param->nolongdatfilter){
|
|
|
- action = handledatfltsrv(param, ¶m->srvbuf, (int *)¶m->srvbufsize, param->srvinbuf - res, (int *)¶m->srvinbuf);
|
|
|
- if(action == HANDLED){
|
|
|
- return 0;
|
|
|
+ if(inclientpipe && !FROMCLIENTPIPE){
|
|
|
+ if(!after){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait reading from client pipe");
|
|
|
+#endif
|
|
|
+ fds[fdsc].fd = pipecli[0];
|
|
|
+ fds[fdsc].events |= (POLLIN);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){
|
|
|
+ RETURN(90);
|
|
|
+ }
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready reading from client pipe");
|
|
|
+#endif
|
|
|
+ if(fds[fdsc].revents & POLLIN) FROMCLIENTPIPE = 1;
|
|
|
+ }
|
|
|
+ fdsc++;
|
|
|
+ }
|
|
|
+ if(fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < MAXSPLICE){
|
|
|
+ if(!after){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait writing to server pipe");
|
|
|
+#endif
|
|
|
+ fds[fdsc].fd = pipesrv[1];
|
|
|
+ fds[fdsc].events |= POLLOUT;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){
|
|
|
+ RETURN(90);
|
|
|
+ }
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready writing to server pipe");
|
|
|
+#endif
|
|
|
+ if(fds[fdsc].revents & POLLOUT) TOSERVERPIPE = 1;
|
|
|
}
|
|
|
- if(action != PASS) return 19;
|
|
|
+ fdsc++;
|
|
|
}
|
|
|
+ if(inserverpipe && !FROMSERVERPIPE){
|
|
|
+ if(!after){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("wait reading from server pipe");
|
|
|
+#endif
|
|
|
+ fds[fdsc].fd = pipesrv[0];
|
|
|
+ fds[fdsc].events |= (POLLIN);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){
|
|
|
+ RETURN(90);
|
|
|
+ }
|
|
|
+#ifdef WITHLOG
|
|
|
+log("ready reading from server pipe");
|
|
|
+#endif
|
|
|
+ if(fds[fdsc].revents & POLLIN) FROMSERVERPIPE = 1;
|
|
|
+ }
|
|
|
+ fdsc++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ if(!after){
|
|
|
+ if(!fdsc) RETURN(90);
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#ifdef WITHLOG
|
|
|
+log("entering poll");
|
|
|
+#endif
|
|
|
+ res = so._poll(fds, fdsc, timeo*1000);
|
|
|
+#ifdef WITHLOG
|
|
|
+log("leaving poll");
|
|
|
+#endif
|
|
|
+ if(res < 0){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("poll error");
|
|
|
+#endif
|
|
|
+ if(errno != EAGAIN && errno != EINTR) RETURN(91);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if(res < 1){
|
|
|
+#ifdef WITHLOG
|
|
|
+log("timeout");
|
|
|
+#endif
|
|
|
+ RETURN (92);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(sleeptime > 0) {
|
|
|
- if(sleeptime > (timeo * 1000)){return (95);}
|
|
|
- usleep(sleeptime * SLEEPTIME);
|
|
|
- sleeptime = 0;
|
|
|
- }
|
|
|
}
|
|
|
- if(conf.timetoexit) return 89;
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "finished with mapping");
|
|
|
-#endif
|
|
|
- while(!param->waitclient64 && param->srvinbuf > param->srvoffset && param->clisock != INVALID_SOCKET){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "flushing buffer to client");
|
|
|
-#endif
|
|
|
- res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, param->srvbuf + param->srvoffset, param->srvinbuf - param->srvoffset, conf.timeouts[STRING_S] * 1000);
|
|
|
- if(res > 0){
|
|
|
- param->srvoffset += res;
|
|
|
- param->statssrv64 += res;
|
|
|
- if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0;
|
|
|
- }
|
|
|
- else break;
|
|
|
- }
|
|
|
- while(!param->waitserver64 && param->cliinbuf > param->clioffset && param->remsock != INVALID_SOCKET){
|
|
|
-#if DEBUGLEVEL > 2
|
|
|
-(*param->srv->logfunc)(param, "flushing buffer to server");
|
|
|
-#endif
|
|
|
- res = socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, param->clibuf + param->clioffset, param->cliinbuf - param->clioffset, conf.timeouts[STRING_S] * 1000);
|
|
|
- if(res > 0){
|
|
|
- param->clioffset += res;
|
|
|
- param->statscli64 += res;
|
|
|
- if(param->cliinbuf == param->clioffset) param->cliinbuf = param->clioffset = 0;
|
|
|
- }
|
|
|
- else break;
|
|
|
- }
|
|
|
- return retcode;
|
|
|
+ res = 0;
|
|
|
+ if(!fromserver) res = 98;
|
|
|
+ else if(!fromclient) res = 99;
|
|
|
+ else if((inclientbuf || inserverbuf)) res = HASERROR?93:94;
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ else if(inclientpipe || inserverpipe) res = HASERROR?93:94;
|
|
|
+#endif
|
|
|
+ else if(HASERROR) res = 94+HASERROR;
|
|
|
+
|
|
|
+CLEANRET:
|
|
|
+
|
|
|
+#ifdef WITHSPLICE
|
|
|
+ if(pipecli[0] >= 0) close(pipecli[0]);
|
|
|
+ if(pipecli[1] >= 0) close(pipecli[1]);
|
|
|
+ if(pipesrv[0] >= 0) close(pipesrv[0]);
|
|
|
+ if(pipesrv[1] >= 0) close(pipesrv[1]);
|
|
|
+#endif
|
|
|
+
|
|
|
+ return res;
|
|
|
}
|