Просмотр исходного кода

Call poll() only on EAGAIN/EINTR

z3APA3A 5 лет назад
Родитель
Сommit
2b1025a79b
3 измененных файлов с 103 добавлено и 82 удалено
  1. 1 3
      src/3proxy.c
  2. 20 18
      src/sockgetchar.c
  3. 82 61
      src/socks.c

+ 1 - 3
src/3proxy.c

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

+ 20 - 18
src/sockgetchar.c

@@ -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;
 }
 }
 
 

+ 82 - 61
src/socks.c

@@ -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(res <= 0) {
-						param->res = 463;
-						break;
-					}
-					if (fds[2].revents) {
-						param->res = 0;
-						break;
-					}
-					if (fds[1].revents) {
+					if(!fds[1].events || fds[1].revents){
 						sasize = sizeof(sin);
 						sasize = sizeof(sin);
-						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;
+						len = so._recvfrom(param->clisock, (char *)buf, 65535, 0, (struct sockaddr *)&sin, &sasize);
+						if(len >= 0) {
+							fds[1].events = fds[1].revents = 0;
+							if(len < 10) continue;
+
+							sasize = sizeof(sin);
+							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;
 								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);
+							}
+							if(buf[0] || buf[1] || buf[2]) {
+								param->res = 466;
 								break;
 								break;
-							default:
-								RETURN(997);
-						 }
+							}
+							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);
-						i+=2;
+							memcpy(SAPORT(&param->sinsr), buf+i, 2);
+							i+=2;
 
 
-						sasize = sizeof(param->sinsr);
-						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++;
+							sasize = sizeof(param->sinsr);
+							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;
-						param->nreads++;
-						memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
-						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);
+						else if(len > 0){
+							fds[0].events = fds[0].revents = 0;
+							param->statssrv64+=len;
+							param->nreads++;
+							memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
+							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;