diff --git a/doc/html/howtoe.html b/doc/html/howtoe.html
index 7c29aa5..36b250b 100644
--- a/doc/html/howtoe.html
+++ b/doc/html/howtoe.html
@@ -870,6 +870,16 @@ You can control 3proxy service via "Services" administration ot via "net" comman
50-69 - SOCKS5 PROXY REDIRECTION ERRORS
70-79 PARENT PROXY CONNECTION ERRORS (identical to 1x)
90-99 - established connection errors
+since 0.9
+ 90 - unexpected system error (should not happen)
+ 91 - unexpected poll error (should not happen)
+ 92 - connection terminated by timeout
+ 93 - dirty connection termination by server or client (or network issue) with unsent data
+ 94 - clear connection termination by server or client with unsent data
+ 95 - dirty connection termination by client (or network issue)
+ 96 - dirty connection termination by server (or network issue)
+ 97 - dirty connection termination by both client and server (probably network issue)
+prior to 0.9:
90 - socket error or connection broken
91 - TCP/IP common failure
92 - connection timed out
diff --git a/doc/html/howtor.html b/doc/html/howtor.html
index a97ecad..c34a9cc 100644
--- a/doc/html/howtor.html
+++ b/doc/html/howtor.html
@@ -1046,6 +1046,18 @@
50-69 - ошибки перенаправления SOCKS5
70-79 ошибки установки родительского соединения, аналогичны 1x
90-99 - ошибки разрыва соединения
+ с версии 0.9
+ 90 - неожиданная системная ошибка (не должно происходить)
+ 91 - ошибка poll (не должно происходить)
+ 92 - соединение прервано по таймауту
+ 93 - клиент или сервер "грязно" закрыли соединение или произошла сетевая ошибка, остались неотправленные данные
+ 94 - клиент или сервер "чисто" закрыли соединение или произошла сетевая ошибка, остались неотправленные данные
+ 95 - клиент "грязно" закрыл соединение или сетевая ошибка
+ 96 - сервер "грязно" закрыл соединение или сетевая ошибка
+ 97 - клиент и сервер "грязно" закрыли соединение или сетевая ошибка
+ 98 - исчерпан лимит данных сервера (не должно быть в журнале)
+ 99 - исчерпан лимит данных клиента (не должно быть в журнале)
+ до версии 0.9
90 - ошибка сокета или соединение неожиданно прервано
91 - общий сбой стека TCP/IP
92 - соединение прервано по таймауту
diff --git a/src/common.c b/src/common.c
index abf3081..1bdf5d4 100644
--- a/src/common.c
+++ b/src/common.c
@@ -369,7 +369,7 @@ int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to){
unsigned long ul = 1;
ioctlsocket(sock, FIONBIO, &ul);
#else
- fcntl(sock,F_SETFL,O_NONBLOCK);
+ fcntl(sock,F_SETFL, O_NONBLOCK | fcntl(sock,F_GETFL));
#endif
if(so._connect(sock,sa,size)) {
if(errno != EAGAIN && errno != EINPROGRESS) return (13);
diff --git a/src/dnspr.c b/src/dnspr.c
index 041e0e2..bdf2e61 100644
--- a/src/dnspr.c
+++ b/src/dnspr.c
@@ -198,7 +198,7 @@ CLEANRET:
if((ip && type == 0x01) || type == 0x1c){
myinet_ntop(type == 0x01? AF_INET:AF_INET6, addr, (char *)buf+strlen((char *)buf), 64);
}
- (*param->srv->logfunc)(param, buf);
+ dolog(param, buf);
}
if(bbuf)myfree(bbuf);
if(host)myfree(host);
diff --git a/src/ftppr.c b/src/ftppr.c
index e22e66a..71eb8cc 100644
--- a/src/ftppr.c
+++ b/src/ftppr.c
@@ -295,7 +295,7 @@ void * ftpprchild(struct clientparam* param) {
sasize = sizeof(param->sincr);
if(so._getpeername(param->ctrlsock, (struct sockaddr *)¶m->sincr, &sasize)){RETURN(819);}
if(req && (param->statscli64 || param->statssrv64)){
- (*param->srv->logfunc)(param, (unsigned char *)req);
+ dolog(param, (unsigned char *)req);
}
}
@@ -316,7 +316,7 @@ CLEANRET:
sasize = sizeof(param->sincr);
so._getpeername(param->ctrlsock, (struct sockaddr *)¶m->sincr, &sasize);
if(param->res != 0 || param->statscli64 || param->statssrv64 ){
- (*param->srv->logfunc)(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
+ dolog(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
}
if(req) myfree(req);
if(buf) myfree(buf);
diff --git a/src/log.c b/src/log.c
index 1f765d5..7572565 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,18 +1,38 @@
/*
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
*/
-pthread_mutex_t log_mutex;
#include "proxy.h"
+pthread_mutex_t log_mutex;
int havelog = 0;
+
+struct clientparam logparam;
+struct srvparam logsrv;
+
+
+
+void dolog(struct clientparam * param, const unsigned char *s){
+ static int init = 0;
+
+ if(param)param->srv->logfunc(param, s);
+ else {
+ if(!init){
+ srvinit(&logsrv, &logparam);
+ init = 1;
+ }
+ logstdout(&logparam, s);
+ }
+}
+
+
void clearstat(struct clientparam * param) {
#ifdef _WIN32
diff --git a/src/pop3p.c b/src/pop3p.c
index 2db17aa..b433998 100644
--- a/src/pop3p.c
+++ b/src/pop3p.c
@@ -49,9 +49,9 @@ CLEANRET:
if(param->hostname&¶m->extusername) {
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==110)?0:':', ntohs(*SAPORT(¶m->sinsr)));
- (*param->srv->logfunc)(param, buf);
+ dolog(param, buf);
}
- else (*param->srv->logfunc)(param, NULL);
+ else dolog(param, NULL);
if(param->clisock != INVALID_SOCKET) {
if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]);
}
diff --git a/src/proxy.c b/src/proxy.c
index efcbe5d..0f530c2 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -152,7 +152,7 @@ static void logurl(struct clientparam * param, char * buf, char * req, int ftp){
strcpy(se, sb);
}
}
- if(param->res != 555 && param->res != 508)(*param->srv->logfunc)(param, (unsigned char *)(req?buf:NULL));
+ if(param->res != 555 && param->res != 508)dolog(param, (unsigned char *)(req?buf:NULL));
}
void decodeurl(unsigned char *s, int allowcr){
diff --git a/src/proxy.h b/src/proxy.h
index b09c901..2912962 100644
--- a/src/proxy.h
+++ b/src/proxy.h
@@ -151,8 +151,7 @@ extern int timetoexit;
extern struct extparam conf;
-int sockmap(struct clientparam * param, int timeo);
-int splicemap(struct clientparam * param, int timeo);
+int sockmap(struct clientparam * param, int timeo, int usesplice);
int socksend(SOCKET sock, unsigned char * buf, int bufsize, int to);
int socksendto(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
int sockrecvfrom(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
@@ -168,6 +167,7 @@ int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char *
+void dolog(struct clientparam * param, const unsigned char *s);
int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec);
int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
extern FILE * stdlog;
@@ -312,9 +312,9 @@ extern struct datatype datatypes[64];
extern struct commands commandhandlers[];
#ifdef WITHSPLICE
-#define mapsocket(a,b) (a->srv->usesplice && !a->ndatfilterssrv && !a->ndatfilterscli && !a->npredatfilters?splicemap(a,b):sockmap(a,b))
+#define mapsocket(a,b) ((a->srv->usesplice && !a->ndatfilterssrv && !a->ndatfilterscli)?sockmap(a,b,1):sockmap(a,b,0))
#else
-#define mapsocket(a,b) sockmap(a,b)
+#define mapsocket(a,b) sockmap(a,b, 0)
#endif
diff --git a/src/proxymain.c b/src/proxymain.c
index deeb2c8..9388955 100644
--- a/src/proxymain.c
+++ b/src/proxymain.c
@@ -23,27 +23,27 @@ void * threadfunc (void *p) {
fds.revents = 0;
for(i=5+(param->srv->maxchild>>10); i; i--){
if(so._poll(&fds, 1, 1000*CONNBACK_TO)!=1){
- param->srv->logfunc(param, (unsigned char *)"Connect back not received, check connback client");
+ dolog(param, (unsigned char *)"Connect back not received, check connback client");
i = 0;
break;
}
param->remsock = so._accept(param->srv->cbsock, (struct sockaddr*)¶m->sinsr, &size);
if(param->remsock == INVALID_SOCKET) {
- param->srv->logfunc(param, (unsigned char *)"Connect back accept() failed");
+ dolog(param, (unsigned char *)"Connect back accept() failed");
continue;
}
#ifndef WITHMAIN
param->req = param->sinsr;
if(param->srv->acl) param->res = checkACL(param);
if(param->res){
- param->srv->logfunc(param, (unsigned char *)"Connect back ACL failed");
+ dolog(param, (unsigned char *)"Connect back ACL failed");
so._closesocket(param->remsock);
param->remsock = INVALID_SOCKET;
continue;
}
#endif
if(socksendto(param->remsock, (struct sockaddr*)¶m->sinsr, (unsigned char *)"C", 1, CONNBACK_TO) != 1){
- param->srv->logfunc(param, (unsigned char *)"Connect back sending command failed");
+ dolog(param, (unsigned char *)"Connect back sending command failed");
so._closesocket(param->remsock);
param->remsock = INVALID_SOCKET;
continue;
@@ -57,6 +57,13 @@ void * threadfunc (void *p) {
freeparam(param);
}
else {
+
+#ifndef _WIN32
+ sigset_t mask;
+ sigfillset(&mask);
+ pthread_sigmask(SIG_SETMASK, &mask, NULL);
+#endif
+
((struct clientparam *) p)->srv->pf((struct clientparam *)p);
}
#ifdef _WIN32
@@ -260,12 +267,8 @@ int MODULEMAINFUNC (int argc, char** argv){
WSADATA wd;
WSAStartup(MAKEWORD( 1, 1 ), &wd);
-
-
-#else
- signal(SIGPIPE, SIG_IGN);
-
#endif
+
#endif
srvinit(&srv, &defparam);
@@ -288,6 +291,14 @@ int MODULEMAINFUNC (int argc, char** argv){
pthread_mutex_init(&log_mutex, NULL);
#endif
+#ifndef _WIN32
+ {
+ sigset_t mask;
+ sigfillset(&mask);
+ pthread_sigmask(SIG_SETMASK, &mask, NULL);
+ }
+#endif
+
for (i=1; i>4))==-1) {
sprintf((char *)buf, "listen(): %s", strerror(errno));
- if(!srv.silent)(*srv.logfunc)(&defparam, buf);
+ if(!srv.silent)dolog(&defparam, buf);
return -4;
}
}
@@ -606,13 +617,13 @@ int MODULEMAINFUNC (int argc, char** argv){
if(!srv.silent && !iscbc){
sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self());
- (*srv.logfunc)(&defparam, buf);
+ dolog(&defparam, buf);
}
}
if(iscbl){
parsehost(srv.family, cbl_string, (struct sockaddr *)&cbsa);
if((srv.cbsock=so._socket(SASOCK(&cbsa), SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) {
- (*srv.logfunc)(&defparam, (unsigned char *)"Failed to allocate connect back socket");
+ dolog(&defparam, (unsigned char *)"Failed to allocate connect back socket");
return -6;
}
opt = 1;
@@ -625,11 +636,11 @@ int MODULEMAINFUNC (int argc, char** argv){
setopts(srv.cbsock, srv.cbssockopts);
if(so._bind(srv.cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) {
- (*srv.logfunc)(&defparam, (unsigned char *)"Failed to bind connect back socket");
+ dolog(&defparam, (unsigned char *)"Failed to bind connect back socket");
return -7;
}
if(so._listen(srv.cbsock, 1 + (srv.maxchild>>4))==-1) {
- (*srv.logfunc)(&defparam, (unsigned char *)"Failed to listen connect back socket");
+ dolog(&defparam, (unsigned char *)"Failed to listen connect back socket");
return -8;
}
}
@@ -649,7 +660,7 @@ int MODULEMAINFUNC (int argc, char** argv){
nlog++;
if(!srv.silent && nlog > 5000) {
sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild);
- (*srv.logfunc)(&defparam, buf);
+ dolog(&defparam, buf);
nlog = 0;
}
usleep(SLEEPTIME);
@@ -667,7 +678,7 @@ int MODULEMAINFUNC (int argc, char** argv){
if (error == 0) continue;
if (errno != EAGAIN && errno != EINTR) {
sprintf((char *)buf, "poll(): %s/%d", strerror(errno), errno);
- if(!srv.silent)(*srv.logfunc)(&defparam, buf);
+ if(!srv.silent)dolog(&defparam, buf);
break;
}
}
@@ -740,7 +751,7 @@ int MODULEMAINFUNC (int argc, char** argv){
nlog++;
if(!srv.silent && (error || nlog > 5000)) {
sprintf((char *)buf, "accept(): %s", strerror(errno));
- (*srv.logfunc)(&defparam, buf);
+ dolog(&defparam, buf);
nlog = 0;
}
continue;
@@ -750,13 +761,13 @@ int MODULEMAINFUNC (int argc, char** argv){
size = sizeof(defparam.sincl);
if(so._getsockname(new_sock, (struct sockaddr *)&defparam.sincl, &size)){
sprintf((char *)buf, "getsockname(): %s", strerror(errno));
- if(!srv.silent)(*srv.logfunc)(&defparam, buf);
+ if(!srv.silent)dolog(&defparam, buf);
continue;
}
#ifdef _WIN32
ioctlsocket(new_sock, FIONBIO, &ul);
#else
- fcntl(new_sock,F_SETFL,O_NONBLOCK);
+ fcntl(new_sock,F_SETFL,O_NONBLOCK | fcntl(new_sock,F_GETFL));
#endif
so._setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
so._setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
@@ -767,7 +778,7 @@ int MODULEMAINFUNC (int argc, char** argv){
if(! (newparam = myalloc (sizeof(defparam)))){
if(!isudp) so._closesocket(new_sock);
defparam.res = 21;
- if(!srv.silent)(*srv.logfunc)(&defparam, (unsigned char *)"Memory Allocation Failed");
+ if(!srv.silent)dolog(&defparam, (unsigned char *)"Memory Allocation Failed");
usleep(SLEEPTIME);
continue;
};
@@ -804,7 +815,7 @@ int MODULEMAINFUNC (int argc, char** argv){
}
else {
sprintf((char *)buf, "_beginthreadex(): %s", _strerror(NULL));
- if(!srv.silent)(*srv.logfunc)(&defparam, buf);
+ if(!srv.silent)dolog(&defparam, buf);
error = 1;
}
#else
@@ -813,7 +824,7 @@ int MODULEMAINFUNC (int argc, char** argv){
srv.childcount++;
if(error){
sprintf((char *)buf, "pthread_create(): %s", strerror(error));
- if(!srv.silent)(*srv.logfunc)(&defparam, buf);
+ if(!srv.silent)dolog(&defparam, buf);
}
else {
newparam->threadid = (unsigned)thread;
diff --git a/src/smtpp.c b/src/smtpp.c
index c369ad7..01519ca 100644
--- a/src/smtpp.c
+++ b/src/smtpp.c
@@ -292,9 +292,9 @@ CLEANRET:
if(param->hostname&¶m->extusername) {
sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(¶m->sinsr)==25?0:':',ntohs(*SAPORT(¶m->sinsr)));
- (*param->srv->logfunc)(param, buf);
+ dolog(param, buf);
}
- else (*param->srv->logfunc)(param, NULL);
+ else dolog(param, NULL);
if(param->clisock != INVALID_SOCKET) {
if ((param->res > 0 && param->res < 100) || (param->res > 661 && param->res <700)) socksend(param->clisock, (unsigned char *)"571 \r\n", 6,conf.timeouts[STRING_S]);
}
diff --git a/src/sockmap.c b/src/sockmap.c
index 559c2c5..b3c54b9 100644
--- a/src/sockmap.c
+++ b/src/sockmap.c
@@ -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
@@ -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
-int splicemap(struct clientparam * param, int timeo){
- struct pollfd fds[2];
+#define MIN(a,b) ((a>b)?b:a)
+#define RETURN(xxx) { res = xxx; goto CLEANRET; }
+
+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 fdsc = 0;
+ int sleeptime = 0;
+ 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};
- 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 sleeptime = 0;
- int needcontinue;
- int tosend;
-
- 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");
+ if(inserverbuf >= fromserver) FROMSERVER = 0;
+ if(inclientbuf >= fromclient) FROMCLIENT = 0;
+#ifdef WITHSPLICE
+ if(!usesplice)
#endif
+ {
+ if(fromserver && !param->srvbuf && (!(param->srvbuf=myalloc(SRVBUFSIZE)) || !(param->srvbufsize = SRVBUFSIZE))){
+ 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);
+
+ while(
+ ((!CLIENTTERM) && (inserverbuf
+#ifdef WITHSPLICE
+ || inserverpipe
+#endif
+ || (!SERVERTERM && fromserver)))
+ ||
+ ((!SERVERTERM) && (inclientbuf
+#ifdef WITHSPLICE
+ || inclientpipe
+#endif
+ || (!CLIENTTERM && fromclient)))
+ ){
+
+
+#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(!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(inclientbuf && TOSERVER){
+#ifdef WITHLOG
+log("send to server from buf");
+#endif
+ 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;
+ }
+ if(!inclientbuf){
+ param->clioffset = param->cliinbuf = 0;
+ if(fromclient) TOCLIENTBUF = 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(inserverbuf && TOCLIENT){
+#ifdef WITHLOG
+log("send to client from buf");
+#endif
+ 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;
+ }
+ if(!inserverbuf){
+ param->srvinbuf = param->srvoffset = 0;
+ continue;
+ }
+ 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;
+ }
+ }
+#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;
+ }
+ }
+ 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;
+ }
+ 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;
+ }
+ }
+ 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;
+ }
+ }
+ }
+ 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
+ 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(!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
+
+ 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++;
+ }
+#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++;
+ }
+ 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;
+ }
+ 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);
+ }
+ }
+ }
+
+ }
+ 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;
}
-
-#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");
-#endif
- if(!param->waitclient64){
- if(!param->srvbuf && (!(param->srvbuf=myalloc(bufsize)) || !(param->srvbufsize = bufsize))){
- return (21);
- }
- }
- if(!param->waitserver64){
- if(!param->clibuf && (!(param->clibuf=myalloc(bufsize)) || !(param->clibufsize = bufsize))){
- return (21);
- }
- }
-
- 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;
- }
- }
-
-
-
- while (!stop&&!conf.timetoexit){
- param->cycles++;
-#ifdef NOIPV6
- sasize = sizeof(struct sockaddr_in);
-#else
- sasize = sizeof(struct sockaddr_in6);
-#endif
- if(param->version < conf.version){
- if((res = (*param->srv->authfunc)(param)) && res != 2 && !param->srv->noforce) {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;
- }
-
- if(param->cliinbuf > param->clioffset && !param->waitserver64) {
-#if DEBUGLEVEL > 2
-(*param->srv->logfunc)(param, "Will send to server");
-#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;
- }
- param->srvoffset += res;
- received += res;
- if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0;
- if(param->waitserver64 && param->waitserver64<= received){
- return (98);
- }
- if(param->service == S_UDPPM && param->srv->singlepacket) {
- stop = 1;
- }
- }
- if((fds[1].revents & POLLOUT)){
-#if DEBUGLEVEL > 2
-(*param->srv->logfunc)(param, "send to server");
-#endif
- if(param->bandlimfunc) {
- int sl1;
-
- sl1 = (*param->bandlimfunc)(param, 0, param->cliinbuf - param->clioffset);
- if(sl1 > sleeptime) sleeptime = sl1;
- }
- 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);
- 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);
- }
- }
- 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;
- }
- else {
- if (res < 0){
- if(errno != EAGAIN && errno != EINTR) return 94;
- if(errno == EINTR) usleep(SLEEPTIME);
- 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;
- }
- if(action != PASS) return 19;
- }
-
- }
- }
- if (!stop && ((fds[1].revents & POLLIN)
-#ifdef WITH_WSAPOLL
- ||(fds[1].revents & POLLHUP)
-#endif
- )) {
-#ifdef NOIPV6
- struct sockaddr_in sin;
-#else
- struct sockaddr_in6 sin;
-#endif
-#if DEBUGLEVEL > 2
-(*param->srv->logfunc)(param, "recv from server");
-#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;
- }
- else {
- if (res < 0){
- if(errno != EAGAIN && errno != EINTR) return 93;
- if(errno == EINTR) usleep(SLEEPTIME);
- continue;
- }
- 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(action != PASS) return 19;
- }
-
- }
- }
-
- 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;
-}
diff --git a/src/socks.c b/src/socks.c
index 97f58d4..9b59a30 100644
--- a/src/socks.c
+++ b/src/socks.c
@@ -448,7 +448,7 @@ fflush(stderr);
else
myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)buf + strlen((char *)buf), 64);
sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(*SAPORT(¶m->req)));
- (*param->srv->logfunc)(param, buf);
+ dolog(param, buf);
myfree(buf);
}
freeparam(param);
diff --git a/src/structures.h b/src/structures.h
index 4df9e07..6e41a03 100644
--- a/src/structures.h
+++ b/src/structures.h
@@ -740,7 +740,7 @@ struct pluginlink {
int (*dobuf2)(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
int (*scanaddr)(const unsigned char *s, unsigned long * ip, unsigned long * mask);
unsigned long (*getip46)(int family, unsigned char *name, struct sockaddr *sa);
- int (*sockmap)(struct clientparam * param, int timeo);
+ int (*sockmap)(struct clientparam * param, int timeo, int usesplice);
int (*ACLMatches)(struct ace* acentry, struct clientparam * param);
int (*alwaysauth)(struct clientparam * param);
int (*checkACL)(struct clientparam * param);
diff --git a/src/tcppm.c b/src/tcppm.c
index d39fd54..043807a 100644
--- a/src/tcppm.c
+++ b/src/tcppm.c
@@ -23,7 +23,7 @@ void * tcppmchild(struct clientparam* param) {
RETURN (mapsocket(param, conf.timeouts[CONNECTION_L]));
CLEANRET:
- (*param->srv->logfunc)(param, param->hostname);
+ dolog(param, param->hostname);
freeparam(param);
return (NULL);
}
diff --git a/src/udppm.c b/src/udppm.c
index 074b923..d4057e2 100644
--- a/src/udppm.c
+++ b/src/udppm.c
@@ -81,7 +81,7 @@ void * udppmchild(struct clientparam* param) {
#ifdef _WIN32
ioctlsocket(param->remsock, FIONBIO, &ul);
#else
- fcntl(param->remsock,F_SETFL,O_NONBLOCK);
+ fcntl(param->remsock,F_SETFL,O_NONBLOCK | fcntl(param->remsock,F_GETFL));
#endif
memcpy(¶m->sinsr, ¶m->req, sizeof(param->req));
@@ -91,7 +91,7 @@ void * udppmchild(struct clientparam* param) {
param->srv->fds.events = POLLIN;
}
- param->res = sockmap(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]);
+ param->res = mapsocket(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]);
if(!param->srv->singlepacket) {
param->srv->fds.events = POLLIN;
}
@@ -99,7 +99,7 @@ void * udppmchild(struct clientparam* param) {
CLEANRET:
if(buf)myfree(buf);
- (*param->srv->logfunc)(param, NULL);
+ dolog(param, NULL);
#ifndef _WIN32
param->clisock = INVALID_SOCKET;
#endif
diff --git a/src/webadmin.c b/src/webadmin.c
index 4ab39bf..8f29481 100644
--- a/src/webadmin.c
+++ b/src/webadmin.c
@@ -576,7 +576,7 @@ CLEANRET:
printstr(&pp, NULL);
if(buf) myfree(buf);
- (*param->srv->logfunc)(param, (unsigned char *)req);
+ dolog(param, (unsigned char *)req);
if(req)myfree(req);
freeparam(param);
return (NULL);