Use non-blocking splice only on write to socket

to prevent race condition data is not copied to the pipe yet
This commit is contained in:
z3APA3A 2018-12-05 23:41:37 +03:00
parent 79ea433caf
commit b7e3a85e88

View File

@ -33,6 +33,8 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le
int splicemap(struct clientparam * param, int timeo){ int splicemap(struct clientparam * param, int timeo){
struct pollfd fds[2]; struct pollfd fds[2];
struct pollfd *fdsp = fds;
int fdsc = 2;
int pipesrv[2] = {-1,-1}; int pipesrv[2] = {-1,-1};
int pipecli[2] = {-1,-1}; int pipecli[2] = {-1,-1};
uint64_t sent=0, received=0; uint64_t sent=0, received=0;
@ -111,6 +113,7 @@ int splicemap(struct clientparam * param, int timeo){
sasize = sizeof(struct sockaddr_in6); sasize = sizeof(struct sockaddr_in6);
#endif #endif
fds[0].events = fds[1].events = 0; fds[0].events = fds[1].events = 0;
fds[0].revents = fds[1].revents = 0;
if(srvstate && !param->waitclient64 && param->clisock != INVALID_SOCKET){ if(srvstate && !param->waitclient64 && param->clisock != INVALID_SOCKET){
#if DEBUGLEVEL > 2 #if DEBUGLEVEL > 2
@ -141,7 +144,19 @@ int splicemap(struct clientparam * param, int timeo){
fds[0].events |= POLLIN; fds[0].events |= POLLIN;
} }
if(!fds[0].events && !fds[1].events) RETURN (666); if(!fds[0].events && !fds[1].events) RETURN (666);
res = so._poll(fds, 2, timeo*1000); if(!fds[0].events){
fdsp = fds +1;
fdsc = 1;
}
else if(!fds[1].events){
fdsp = fds;
fdsc = 1;
}
else {
fdsp = fds;
fdsc = 2;
}
res = so._poll(fdsp, fdsc, timeo*1000);
if(res < 0){ if(res < 0){
if(errno == EINTR) so._poll(NULL, 0, 1); if(errno == EINTR) so._poll(NULL, 0, 1);
else if(errno != EAGAIN) RETURN(91); else if(errno != EAGAIN) RETURN(91);
@ -171,7 +186,7 @@ int splicemap(struct clientparam * param, int timeo){
(*param->srv->logfunc)(param, "splice: spliced send to client"); (*param->srv->logfunc)(param, "splice: spliced send to client");
#endif #endif
res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, insrvpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE); res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, insrvpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
if(res < 0) { if(res <= 0) {
#if DEBUGLEVEL > 2 #if DEBUGLEVEL > 2
(*param->srv->logfunc)(param, "splice: send to client error"); (*param->srv->logfunc)(param, "splice: send to client error");
#endif #endif
@ -188,7 +203,6 @@ int splicemap(struct clientparam * param, int timeo){
} }
srvstate = 0; srvstate = 0;
} }
else srvstate = 2;
if(param->waitserver64 && param->waitserver64 <= received){ if(param->waitserver64 && param->waitserver64 <= received){
RETURN (98); RETURN (98);
} }
@ -198,7 +212,7 @@ int splicemap(struct clientparam * param, int timeo){
(*param->srv->logfunc)(param, "splice: spliced send to server"); (*param->srv->logfunc)(param, "splice: spliced send to server");
#endif #endif
res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, inclipipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE); res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, inclipipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE);
if(res < 0) { if(res <= 0) {
#if DEBUGLEVEL > 2 #if DEBUGLEVEL > 2
(*param->srv->logfunc)(param, "splice: send to server error"); (*param->srv->logfunc)(param, "splice: send to server error");
#endif #endif
@ -227,7 +241,7 @@ int splicemap(struct clientparam * param, int timeo){
#if DEBUGLEVEL > 2 #if DEBUGLEVEL > 2
(*param->srv->logfunc)(param, "splice: recv from client"); (*param->srv->logfunc)(param, "splice: recv from client");
#endif #endif
res = splice(param->clisock, NULL, pipecli[1], NULL, rfromclient, SPLICE_F_NONBLOCK | SPLICE_F_MOVE); res = splice(param->clisock, NULL, pipecli[1], NULL, rfromclient, SPLICE_F_MOVE);
if (res < 0){ if (res < 0){
if(errno == EINTR) so._poll(NULL, 0, 1); if(errno == EINTR) so._poll(NULL, 0, 1);
else if(errno != EAGAIN) RETURN(94); else if(errno != EAGAIN) RETURN(94);
@ -249,7 +263,7 @@ int splicemap(struct clientparam * param, int timeo){
#if DEBUGLEVEL > 2 #if DEBUGLEVEL > 2
(*param->srv->logfunc)(param, "splice: recv from server"); (*param->srv->logfunc)(param, "splice: recv from server");
#endif #endif
res = splice(param->remsock, NULL, pipesrv[1], NULL, rfromserver, SPLICE_F_NONBLOCK | SPLICE_F_MOVE); res = splice(param->remsock, NULL, pipesrv[1], NULL, rfromserver, SPLICE_F_MOVE);
if (res < 0){ if (res < 0){
if(errno == EINTR) so._poll(NULL, 0, 1); if(errno == EINTR) so._poll(NULL, 0, 1);
else if(errno != EAGAIN) RETURN(93); else if(errno != EAGAIN) RETURN(93);