From eb829b062b7e65093284e0842d4b0792b55f8844 Mon Sep 17 00:00:00 2001
From: z3APA3A <3APA3A@3proxy.ru>
Date: Fri, 9 Oct 2020 15:42:34 +0300
Subject: [PATCH] Major code refactoring
- sockmapping rewritten from stratch to minimilse polling. poll() is now
only called if blocking is actually expected, splice pipes are now
polled if splice fails, buffers flushing is much more accurate.
- logging code moved to separate files
- signal masks added to client threads to prevent unneeded interruptions
- bandwidth limitation will not delay the thread after client or server
shutdown
---
doc/html/howtoe.html | 10 +
doc/html/howtor.html | 12 +
src/common.c | 2 +-
src/dnspr.c | 2 +-
src/ftppr.c | 4 +-
src/log.c | 24 +-
src/pop3p.c | 4 +-
src/proxy.c | 2 +-
src/proxy.h | 8 +-
src/proxymain.c | 61 ++-
src/smtpp.c | 4 +-
src/sockmap.c | 1163 ++++++++++++++++++++++--------------------
src/socks.c | 2 +-
src/structures.h | 2 +-
src/tcppm.c | 2 +-
src/udppm.c | 6 +-
src/webadmin.c | 2 +-
17 files changed, 724 insertions(+), 586 deletions(-)
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);