mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 13:55:48 +08:00
Sockets read after a wait are non-blocking, and a read finding nothing waits again
A wait may end with nothing to read: a TLS record not yet whole, a connection gone before it is accepted, and, once clients share a thread, nothing more than a chance to try. Where a read or an accept() followed a wait on a blocking socket, or ended the operation when it found nothing, the socket is non-blocking and the wait is made again: the listening sockets of SOCKS BIND and of FTP passive mode, httpsrv reading what is left of a request body, and the RADIUS client, which reads with sockrecvfrom(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7718ffa9f7
commit
0d6b2950f0
@ -294,10 +294,8 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
int total_length;
|
||||
int len;
|
||||
PROXYSOCKADDRTYPE saremote;
|
||||
struct pollfd fds[1];
|
||||
char vector[AUTH_VECTOR_LEN];
|
||||
radius_packet_t packet, rpacket;
|
||||
SASIZETYPE salen;
|
||||
int data_len;
|
||||
int count=0;
|
||||
uint8_t *attr;
|
||||
@ -545,6 +543,7 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
if ((sockfd = so._socket(so.state, SASOCK(&saremote), SOCK_DGRAM, 0)) < 0) {
|
||||
return 4;
|
||||
}
|
||||
nonblock(sockfd);
|
||||
remsock = sockfd;
|
||||
/*
|
||||
}
|
||||
@ -557,17 +556,8 @@ int radsend(struct clientparam * param, int auth, int stop){
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(fds, 0, sizeof(fds));
|
||||
fds[0].fd = remsock;
|
||||
fds[0].events = POLLIN;
|
||||
if(sockpoll(&so, so.state, fds, 1, param->srv->config->timeouts[SINGLEBYTE_L]*1000) <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
salen = sizeof(saremote);
|
||||
|
||||
data_len = so._recvfrom(so.state, remsock, (char *)&rpacket, sizeof(packet)-16,
|
||||
0, (struct sockaddr *)&saremote, &salen);
|
||||
data_len = sockrecvfrom(NULL, remsock, (struct sockaddr *)&saremote, (unsigned char *)&rpacket,
|
||||
sizeof(packet)-16, param->srv->config->timeouts[SINGLEBYTE_L]*1000);
|
||||
|
||||
|
||||
if (data_len < 20) {
|
||||
|
||||
15
src/ftppr.c
15
src/ftppr.c
@ -138,6 +138,7 @@ void * ftpprchild(struct clientparam* param) {
|
||||
if(bindwithrange(param, clidatasock, ¶m->sincl, param->intport)){RETURN(822);}
|
||||
if (pasv) {
|
||||
if(param->srv->so._listen(param->sostate, clidatasock, 1)) {RETURN(823);}
|
||||
nonblock(clidatasock);
|
||||
sasize = sizeof(param->sincl);
|
||||
if(param->srv->so._getsockname(param->sostate, clidatasock, (struct sockaddr *)¶m->sincl, &sasize)){RETURN(824);}
|
||||
if(pasv == 1){
|
||||
@ -222,12 +223,14 @@ void * ftpprchild(struct clientparam* param) {
|
||||
fds.fd = clidatasock;
|
||||
fds.events = POLLIN;
|
||||
|
||||
res = sockpoll(¶m->srv->so, param->sostate, &fds, 1, param->srv->timeouts[STRING_L]*1000);
|
||||
if(res != 1) {
|
||||
RETURN(857);
|
||||
}
|
||||
sasize = sizeof(param->sincr);
|
||||
ss = param->srv->so._accept(param->sostate, clidatasock, (struct sockaddr *)¶m->sincr, &sasize);
|
||||
do {
|
||||
res = sockpoll(¶m->srv->so, param->sostate, &fds, 1, param->srv->timeouts[STRING_L]*1000);
|
||||
if(res != 1) {
|
||||
RETURN(857);
|
||||
}
|
||||
sasize = sizeof(param->sincr);
|
||||
ss = param->srv->so._accept(param->sostate, clidatasock, (struct sockaddr *)¶m->sincr, &sasize);
|
||||
} while (ss == INVALID_SOCKET && acceptagain());
|
||||
if (ss == INVALID_SOCKET) { RETURN (858);}
|
||||
#ifdef _WIN32
|
||||
{ unsigned long ul = 1; ioctlsocket(ss, FIONBIO, &ul); }
|
||||
|
||||
@ -1189,6 +1189,7 @@ static void httpsrv_linger(struct clientparam *param)
|
||||
if(sockpoll(¶m->srv->so, param->sostate, &fd, 1, timeo * 1000) <= 0) break;
|
||||
got = (int)param->srv->so._recv(param->sostate, param->clisock, buf,
|
||||
(left > HTTPSRV_BLOCK)? (int)HTTPSRV_BLOCK : (int)left, 0);
|
||||
if(got < 0 && (errno == EAGAIN || errno == EINTR)) continue;
|
||||
if(got <= 0) break;
|
||||
left -= (uint64_t)got;
|
||||
}
|
||||
|
||||
10
src/socks.c
10
src/socks.c
@ -351,17 +351,21 @@ fflush(stderr);
|
||||
break;
|
||||
case 2:
|
||||
param->srv->so._listen (param->sostate, param->remsock, 1);
|
||||
nonblock(param->remsock);
|
||||
|
||||
fds[0].fd = param->remsock;
|
||||
fds[1].fd = param->clisock;
|
||||
fds[0].events = fds[1].events = POLLIN;
|
||||
res = sockpoll(¶m->srv->so, param->sostate, fds, 2, param->srv->timeouts[CONNECTION_L] * 1000);
|
||||
do {
|
||||
res = sockpoll(¶m->srv->so, param->sostate, fds, 2, param->srv->timeouts[CONNECTION_L] * 1000);
|
||||
if (res < 1 || fds[1].revents) break;
|
||||
sasize = sizeof(param->sinsr);
|
||||
s = param->srv->so._accept(param->sostate, param->remsock, (struct sockaddr *)¶m->sinsr, &sasize);
|
||||
} while (s == INVALID_SOCKET && acceptagain());
|
||||
if (res < 1 || fds[1].revents) {
|
||||
res = 460;
|
||||
break;
|
||||
}
|
||||
sasize = sizeof(param->sinsr);
|
||||
s = param->srv->so._accept(param->sostate, param->remsock, (struct sockaddr *)¶m->sinsr, &sasize);
|
||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||
param->remsock = s;
|
||||
if(s == INVALID_SOCKET) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user