diff --git a/src/ftppr.c b/src/ftppr.c index 0cc0762..3209578 100644 --- a/src/ftppr.c +++ b/src/ftppr.c @@ -242,7 +242,7 @@ void * ftpprchild(struct clientparam* param) { so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); so._setsockopt(clidatasock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); param->clisock = clidatasock; - res = sockmap(param, conf.timeouts[CONNECTION_S]); + res = mapsocket(param, conf.timeouts[CONNECTION_S]); if(param->remsock != INVALID_SOCKET) { so._shutdown (param->remsock, SHUT_RDWR); so._closesocket(param->remsock); diff --git a/src/pop3p.c b/src/pop3p.c index b5f3088..26f145b 100644 --- a/src/pop3p.c +++ b/src/pop3p.c @@ -44,7 +44,7 @@ void * pop3pchild(struct clientparam* param) { {RETURN(623);} param->statscli64 += (uint64_t)(strlen((char *)param->extusername) + 7); param->nwrites++; - RETURN (sockmap(param, 180)); + RETURN (mapsocket(param, 180)); CLEANRET: if(param->hostname&¶m->extusername) { diff --git a/src/proxy.c b/src/proxy.c index 911ea76..d7ae236 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -616,7 +616,7 @@ for(;;){ s = param->remsock; param->remsock = ftps; if((param->operation == FTP_PUT) && (contentlength64 > 0)) param->waitclient64 = contentlength64; - res = sockmap(param, conf.timeouts[CONNECTION_L]); + res = mapsocket(param, conf.timeouts[CONNECTION_L]); if (res == 99) res = 0; so._closesocket(ftps); ftps = INVALID_SOCKET; @@ -803,7 +803,7 @@ for(;;){ if(isconnect && param->redirtype != R_HTTP) { socksend(param->clisock, (unsigned char *)proxy_stringtable[8], (int)strlen(proxy_stringtable[8]), conf.timeouts[STRING_S]); if(param->redirectfunc) return (*param->redirectfunc)(param); - param->res = sockmap(param, conf.timeouts[CONNECTION_L]); + param->res = mapsocket(param, conf.timeouts[CONNECTION_L]); if(param->redirectfunc) return (*param->redirectfunc)(param); RETURN(param->res); } @@ -866,7 +866,7 @@ for(;;){ if(contentlength64 > 0){ param->nolongdatfilter = 0; param->waitclient64 = contentlength64; - res = sockmap(param, conf.timeouts[CONNECTION_S]); + res = mapsocket(param, conf.timeouts[CONNECTION_S]); param->waitclient64 = 0; if(res != 99) { RETURN(res); @@ -1034,7 +1034,7 @@ for(;;){ } if(param->chunked != 2){ param->waitserver64 = contentlength64; - if((res = sockmap(param, conf.timeouts[CONNECTION_S])) != 98){ + if((res = mapsocket(param, conf.timeouts[CONNECTION_S])) != 98){ RETURN(res); } param->waitserver64 = 0; @@ -1042,13 +1042,13 @@ for(;;){ } while(param->chunked); } if(isconnect && res == 200 && param->operation){ - RETURN (sockmap(param, conf.timeouts[CONNECTION_S])); + RETURN (mapsocket(param, conf.timeouts[CONNECTION_S])); } else if(isconnect){ ckeepalive = keepalive = 1; } else if(!hascontent && !param->chunked) { - RETURN(sockmap(param, conf.timeouts[CONNECTION_S])); + RETURN(mapsocket(param, conf.timeouts[CONNECTION_S])); } contentlength64 = 0; REQUESTEND: diff --git a/src/smtpp.c b/src/smtpp.c index e40e4ea..3444efd 100644 --- a/src/smtpp.c +++ b/src/smtpp.c @@ -272,7 +272,7 @@ void * smtppchild(struct clientparam* param) { if(param->nhdrfilterscli || param->nhdrfilterssrv || param->ndatfilterscli || param->ndatfilterssrv){ do { - if(res == 22) RETURN (sockmap(param, 180)); + if(res == 22) RETURN (mapsocket(param, 180)); if(res != 2 && (res = readreply(param)) <= 0) break; if(res == 221) RETURN(0); if(res == 354) res = readdata(param); @@ -286,7 +286,7 @@ void * smtppchild(struct clientparam* param) { #endif - RETURN (sockmap(param, 180)); + RETURN (mapsocket(param, 180)); CLEANRET: diff --git a/src/sockmap.c b/src/sockmap.c index a7d36c5..343ce91 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -37,6 +37,7 @@ int splicemap(struct clientparam * param, int timeo){ 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 insrvpipe = 0, inclipipe = 0; @@ -44,6 +45,23 @@ int splicemap(struct clientparam * param, int timeo){ int sleeptime = 0; + + if(param->srv->usesplice > 1 && !param->waitserver64 && !param->waitclient64){ + if(param->clioffset == param->cliinbuf){ + param->clioffset = param->cliinbuf = 0; + if(param->clibuf){ + myfree(param->clibuf); + param->clibuf = NULL; + } + } + if(param->srvoffset == param->srvinbuf){ + param->srvoffset = param->srvinbuf = 0; + if(param->srvbuf){ + myfree(param->srvbuf); + param->srvbuf = NULL; + } + } + } param->res = 0; if(pipe(pipecli) < 0) RETURN(21); if(pipe(pipesrv) < 0) RETURN(21); @@ -53,30 +71,37 @@ int splicemap(struct clientparam * param, int timeo){ while(!stop && !conf.timetoexit){ +#ifdef NOIPV6 + sasize = sizeof(struct sockaddr_in); +#else + sasize = sizeof(struct sockaddr_in6); +#endif fds[0].events = fds[1].events = 0; - if(srvstate && !param->waitclient64){ + if((srvstate || param->srvinbuf > param->srvoffset) && !param->waitclient64){ #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "splice: will send to client"); #endif fds[0].events |= POLLOUT; } rfromserver = MAXSPLICE; - if(param->waitserver64) rfromserver = MIN(MAXSPLICE, param->waitserver64 - (received + insrvpipe)); + if(param->srvinbuf > param->srvoffset) rfromserver = 0; + else if(param->waitserver64) rfromserver = MIN(MAXSPLICE, param->waitserver64 - (received + insrvpipe)); if(srvstate < 2 && rfromserver > 0) { #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "splice: will recv from server"); #endif fds[1].events |= POLLIN; } - if(clistate && !param->waitserver64){ + if((clistate || param->cliinbuf > param->clioffset)&& !param->waitserver64){ #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "splice: will send to server"); #endif fds[1].events |= POLLOUT; } rfromclient = MAXSPLICE; - if(param->waitclient64) rfromclient = MIN(MAXSPLICE, param->waitclient64 - (sent + inclipipe)); + if(param->cliinbuf > param->clioffset) rfromclient = 0; + else if(param->waitclient64) rfromclient = MIN(MAXSPLICE, param->waitclient64 - (sent + inclipipe)); if(clistate < 2 && rfromclient > 0) { #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "splice :will recv from client"); @@ -104,17 +129,37 @@ int splicemap(struct clientparam * param, int timeo){ param->res = 90; } if((fds[0].revents & POLLOUT)){ + if (param->srvinbuf > param->srvoffset) { #if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: send to client"); +(*param->srv->logfunc)(param, "splice: non-spliced send to client"); #endif - res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, insrvpipe), SPLICE_F_NONBLOCK | SPLICE_F_MORE | SPLICE_F_MOVE); + 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); + } + else { +#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_MORE | SPLICE_F_MOVE); + } if(res < 0) { +#if DEBUGLEVEL > 2 +(*param->srv->logfunc)(param, "splice: send to client error"); +#endif if(errno != EAGAIN && errno != EINTR) RETURN(96); if(errno == EINTR) usleep(SLEEPTIME); continue; } if(res){ - insrvpipe -= res; + if (param->srvinbuf > param->srvoffset){ + param->srvinbuf = param->srvoffset = 0; + if(param->srv->usesplice > 1 && !param->waitclient64 && !param->waitserver64){ + if(param->srvbuf){ + myfree(param->srvbuf); + param->srvbuf = NULL; + } + } + } + else insrvpipe -= res; received += res; if(param->bandlimfunc) { @@ -128,17 +173,40 @@ int splicemap(struct clientparam * param, int timeo){ } } if((fds[1].revents & POLLOUT)){ + if(param->cliinbuf > param->clioffset){ #if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: send to server"); +(*param->srv->logfunc)(param, "splice: non-spliced send to server"); #endif - res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, inclipipe), SPLICE_F_NONBLOCK | SPLICE_F_MORE | SPLICE_F_MOVE); + 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); + } + else { +#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_MORE | SPLICE_F_MOVE); + } if(res < 0) { +#if DEBUGLEVEL > 2 +(*param->srv->logfunc)(param, "splice: send to server error"); +#endif if(errno != EAGAIN && errno != EINTR) RETURN(97); if(errno == EINTR) usleep(SLEEPTIME); continue; } if(res){ - inclipipe -= res; + if(param->cliinbuf > param->clioffset){ + param->clioffset += res; + if(param->clioffset == param->cliinbuf){ + param->clioffset = param->cliinbuf = 0; + if(param->srv->usesplice > 1 && !param->waitclient64 && !param->waitserver64){ + if(param->clibuf){ + myfree(param->clibuf); + param->clibuf = NULL; + } + } + } + } + else inclipipe -= res; sent += res; param->nwrites++; param->statscli64 += res; @@ -150,7 +218,6 @@ int splicemap(struct clientparam * param, int timeo){ } clistate = 0; } - else clistate = 2; if(param->waitclient64 && param->waitclient64 <= sent){ RETURN (99); } @@ -282,7 +349,11 @@ int sockmap(struct clientparam * param, int timeo){ while (!stop&&!conf.timetoexit){ +#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; @@ -417,7 +488,11 @@ int sockmap(struct clientparam * param, int timeo){ } } if (!stop && (fds[1].revents & POLLIN)) { +#ifdef NOIPV6 struct sockaddr_in sin; +#else + struct sockaddr_in6 sin; +#endif #if DEBUGLEVEL > 2 (*param->srv->logfunc)(param, "recv from server"); #endif diff --git a/src/socks.c b/src/socks.c index 4d048f8..1bc3fa8 100644 --- a/src/socks.c +++ b/src/socks.c @@ -279,7 +279,7 @@ fflush(stderr); if(buf)myfree(buf); return (*param->redirectfunc)(param); } - param->res = sockmap(param, conf.timeouts[CONNECTION_L]); + param->res = mapsocket(param, conf.timeouts[CONNECTION_L]); break; case 2: so._listen (param->remsock, 1); @@ -325,7 +325,7 @@ fflush(stderr); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } - param->res = sockmap(param, conf.timeouts[CONNECTION_S]); + param->res = mapsocket(param, conf.timeouts[CONNECTION_S]); break; case 3: param->sinsr = param->req;