Call poll() only on EAGAIN/EINTR

This commit is contained in:
z3APA3A 2020-11-16 14:11:18 +03:00
parent 4ec9229acb
commit 2b1025a79b
3 changed files with 105 additions and 84 deletions

View File

@ -265,9 +265,7 @@ void cyclestep(void){
if(conf.timetoexit){ if(conf.timetoexit){
conf.paused++; conf.paused++;
doschedule(); doschedule();
usleep(SLEEPTIME*999); usleep(3*SLEEPTIME*999);
usleep(SLEEPTIME*999);
usleep(SLEEPTIME*999);
return; return;
} }

View File

@ -10,19 +10,20 @@
int socksend(SOCKET sock, char * buf, int bufsize, int to){ int socksend(SOCKET sock, char * buf, int bufsize, int to){
int sent = 0; int sent = 0;
int res; int res;
struct pollfd fds; struct pollfd fds={0};
fds.fd = sock; fds.fd = sock;
fds.events = POLLOUT;
do { do {
if(conf.timetoexit) return 0;
res = so._poll(&fds, 1, to*1000);
if(res < 0 && (errno == EAGAIN || errno == EINTR)) continue;
if(res < 1) break;
res = so._send(sock, (char *)buf + sent, bufsize - sent, 0); res = so._send(sock, (char *)buf + sent, bufsize - sent, 0);
if(res < 0) { if(res < 0) {
if(errno == EAGAIN || errno == EINTR) continue; if(errno == EAGAIN || errno == EINTR) continue;
break; break;
fds.events = POLLOUT;
if(conf.timetoexit) return sent;
res = so._poll(&fds, 1, to*1000);
if(res < 0 && (errno == EAGAIN || errno == EINTR)) continue;
if(res < 1) break;
res = 0;
} }
sent += res; sent += res;
} while (sent < bufsize); } while (sent < bufsize);
@ -33,19 +34,20 @@ int socksend(SOCKET sock, char * buf, int bufsize, int to){
int socksendto(SOCKET sock, struct sockaddr * sin, char * buf, int bufsize, int to){ int socksendto(SOCKET sock, struct sockaddr * sin, char * buf, int bufsize, int to){
int sent = 0; int sent = 0;
int res; int res;
struct pollfd fds; struct pollfd fds={0};
fds.fd = sock; fds.fd = sock;
do { do {
if(conf.timetoexit) return 0; if(conf.timetoexit) return 0;
fds.events = POLLOUT;
res = so._poll(&fds, 1, to);
if(res < 0 && (errno == EAGAIN || errno == EINTR)) continue;
if(res < 1) break;
res = so._sendto(sock, (char *)buf + sent, bufsize - sent, 0, sin, SASIZE(sin)); res = so._sendto(sock, (char *)buf + sent, bufsize - sent, 0, sin, SASIZE(sin));
if(res < 0) { if(res < 0) {
if(errno != EAGAIN && errno != EINTR) break; if(errno != EAGAIN && errno != EINTR) break;
continue; fds.events = POLLOUT;
if(conf.timetoexit) return sent;
res = so._poll(&fds, 1, to);
if(res < 0 && (errno == EAGAIN || errno == EINTR)) continue;
if(res < 1) break;
res = 0;
} }
sent += res; sent += res;
} while (sent < bufsize); } while (sent < bufsize);
@ -53,18 +55,18 @@ int socksendto(SOCKET sock, struct sockaddr * sin, char * buf, int bufsize, int
} }
int sockrecvfrom(SOCKET sock, struct sockaddr * sin, char * buf, int bufsize, int to){ int sockrecvfrom(SOCKET sock, struct sockaddr * sin, char * buf, int bufsize, int to){
struct pollfd fds; struct pollfd fds={0};
SASIZETYPE sasize; SASIZETYPE sasize;
int res; int res;
fds.fd = sock; fds.fd = sock;
fds.events = POLLIN;
if(conf.timetoexit) return EOF;
if (so._poll(&fds, 1, to)<1) return 0;
sasize = SASIZE(sin);
do { do {
sasize = SASIZE(sin);
res = so._recvfrom(sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize); res = so._recvfrom(sock, (char *)buf, bufsize, 0, (struct sockaddr *)sin, &sasize);
} while (res < 0 && (errno == EAGAIN || errno == EINTR)); if ((res >= 0) || (errno != EAGAIN && errno != EINTR) || conf.timetoexit) break;
fds.events = POLLIN;
res = so._poll(&fds, 1, to);
} while (res == 1 || (res < 0 && (errno == EAGAIN || errno == EINTR)));
return res; return res;
} }

View File

@ -7,7 +7,6 @@
*/ */
#include "proxy.h" #include "proxy.h"
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; } #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
char * commands[] = {"UNKNOWN", "CONNECT", "BIND", "UDPMAP"}; char * commands[] = {"UNKNOWN", "CONNECT", "BIND", "UDPMAP"};
@ -333,64 +332,61 @@ fflush(stderr);
if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);} if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);}
sin = param->sincr; sin = param->sincr;
fds[2].events = fds[1].events = fds[0].events = 0;
fds[0].fd = param->remsock;
fds[1].fd = param->clisock;
fds[2].fd = param->ctrlsock;
for(;;){ for(;;){
fds[0].fd = param->remsock;
fds[1].fd = param->clisock;
fds[2].fd = param->ctrlsock;
fds[2].events = fds[1].events = fds[0].events = POLLIN;
res = so._poll(fds, 3, conf.timeouts[CONNECTION_L]*1000); if(!fds[1].events || fds[1].revents){
if(res <= 0) {
param->res = 463;
break;
}
if (fds[2].revents) {
param->res = 0;
break;
}
if (fds[1].revents) {
sasize = sizeof(sin); sasize = sizeof(sin);
if((len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) { len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize);
param->res = 464; if(len >= 0) {
break; fds[1].events = fds[1].revents = 0;
} if(len < 10) continue;
if(SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) || memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin))){
param->res = 465;
break;
}
if(buf[0] || buf[1] || buf[2]) {
param->res = 466;
break;
}
size = 4;
switch(buf[3]) {
case 4:
size = 16;
case 1:
i = 4+size;
memcpy(SAADDR(&param->sinsr), buf+4, size);
*SAFAMILY(&param->sinsr) = (size == 4)?AF_INET:AF_INET6;
break;
case 3:
size = buf[4];
for (i=4; size; i++, size--){
buf[i] = buf[i+1];
}
buf[i++] = 0;
if(!getip46(param->srv->family, buf+4, (struct sockaddr *) &param->sinsr)) RETURN(100);
break;
default:
RETURN(997);
}
memcpy(SAPORT(&param->sinsr), buf+i, 2); sasize = sizeof(sin);
i+=2; if((len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) {
param->res = 464;
break;
}
if(SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) || memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin))){
param->res = 465;
break;
}
if(buf[0] || buf[1] || buf[2]) {
param->res = 466;
break;
}
size = 4;
switch(buf[3]) {
case 4:
size = 16;
case 1:
i = 4+size;
memcpy(SAADDR(&param->sinsr), buf+4, size);
*SAFAMILY(&param->sinsr) = (size == 4)?AF_INET:AF_INET6;
break;
case 3:
size = buf[4];
for (i=4; size; i++, size--){
buf[i] = buf[i+1];
}
buf[i++] = 0;
if(!getip46(param->srv->family, buf+4, (struct sockaddr *) &param->sinsr)) RETURN(100);
break;
default:
RETURN(997);
}
sasize = sizeof(param->sinsr); memcpy(SAPORT(&param->sinsr), buf+i, 2);
if(len > (int)i){ i+=2;
socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000);
param->statscli64+=(len - i); sasize = sizeof(param->sinsr);
param->nwrites++; if(len > (int)i){
socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000);
param->statscli64+=(len - i);
param->nwrites++;
#if SOCKSTRACE > 1 #if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n", fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n",
inet_ntoa(param->sins.sin_addr), inet_ntoa(param->sins.sin_addr),
@ -404,23 +400,32 @@ fprintf(stderr, "client address is assumed to be %s:%hu\n",
); );
fflush(stderr); fflush(stderr);
#endif #endif
}
continue;
} }
else if(len ==0 || (len <0 && errno != EINTR && errno != EAGAIN)){
param->res = 464;
break;
}
fds[1].events = POLLIN;
} }
if (fds[0].revents) { if (!fds[0].events || fds[0].revents) {
sasize = sizeof(param->sinsr); sasize = sizeof(param->sinsr);
buf[0]=buf[1]=buf[2]=0; buf[0]=buf[1]=buf[2]=0;
buf[3]=(*SAFAMILY(&param->sinsl) == AF_INET)?1:4; buf[3]=(*SAFAMILY(&param->sinsl) == AF_INET)?1:4;
if((len = so._recvfrom(param->remsock, (char *)buf+6+SAADDRLEN(&param->sinsl), 65535 - (6+SAADDRLEN(&param->sinsl)), 0, (struct sockaddr *)&param->sinsr, &sasize)) <= 0) { len = so._recvfrom(param->remsock, (char *)buf+6+SAADDRLEN(&param->sinsl), 65535 - (6+SAADDRLEN(&param->sinsl)), 0, (struct sockaddr *)&param->sinsr, &sasize);
if(len == 0 || (len < 0 && errno != EAGAIN && errno !=EINTR)) {
param->res = 468; param->res = 468;
break; break;
} }
param->statssrv64+=len; else if(len > 0){
param->nreads++; fds[0].events = fds[0].revents = 0;
memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr)); param->statssrv64+=len;
memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2); param->nreads++;
sasize = sizeof(sin); memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(&param->sinsr), conf.timeouts[SINGLEBYTE_L]*1000); memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
sasize = sizeof(sin);
socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(&param->sinsr), conf.timeouts[SINGLEBYTE_L]*1000);
#if SOCKSTRACE > 1 #if SOCKSTRACE > 1
fprintf(stderr, "UDP packet relayed to client from %hu size %d\n", fprintf(stderr, "UDP packet relayed to client from %hu size %d\n",
ntohs(*SAPORT(&param->sinsr)), ntohs(*SAPORT(&param->sinsr)),
@ -429,6 +434,22 @@ fprintf(stderr, "UDP packet relayed to client from %hu size %d\n",
fflush(stderr); fflush(stderr);
#endif #endif
continue;
}
fds[0].events = POLLIN;
}
if (fds[2].revents) {
param->res = 0;
break;
}
fds[0].revents = fds[1].revents = fds[2].revents = 0;
fds[2].events = POLLIN;
res = so._poll(fds, 3, conf.timeouts[CONNECTION_L]*1000);
if(res == 0 || (res < 0 && errno != EAGAIN && errno != EINTR)) {
param->res = 463;
break;
} }
} }
break; break;