mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
Connect back: a connection one client takes leaves the others waiting
The clients of a -R service all wait for the connection back on the
same listening socket, which was blocking: one connection woke them
all, one took it, and the others were left in accept() until the next,
past their time out and through a reload. The socket is non-blocking,
and an accept() which finds nothing, the connection taken by another
client or gone, is not one of the client's tries. nonblock() makes a
socket non-blocking, acceptagain() tells such an accept().
(cherry picked from commit 126c7d0)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
76cd4d8447
commit
94a095dda9
20
src/common.c
20
src/common.c
@ -661,6 +661,26 @@ int parseconnusername(char *username, struct clientparam *param, int extpasswd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* What waits for a socket waits in poll(): a call on it never does. */
|
||||||
|
void nonblock(SOCKET sock){
|
||||||
|
#ifdef _WIN32
|
||||||
|
unsigned long ul = 1;
|
||||||
|
ioctlsocket(sock, FIONBIO, &ul);
|
||||||
|
#else
|
||||||
|
fcntl(sock, F_SETFL, O_NONBLOCK | fcntl(sock, F_GETFL));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* accept() with nothing to accept: another took it, or it was gone */
|
||||||
|
int acceptagain(void){
|
||||||
|
#ifdef _WIN32
|
||||||
|
int err = WSAGetLastError();
|
||||||
|
return err == WSAEWOULDBLOCK || err == WSAECONNRESET || err == WSAEINTR;
|
||||||
|
#else
|
||||||
|
return errno == EAGAIN || errno == EWOULDBLOCK || errno == ECONNABORTED || errno == EINTR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to){
|
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to){
|
||||||
struct pollfd fds[1];
|
struct pollfd fds[1];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
@ -369,6 +369,8 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign
|
|||||||
int readconfig(FILE * fp);
|
int readconfig(FILE * fp);
|
||||||
void initcommands(void);
|
void initcommands(void);
|
||||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
||||||
|
void nonblock(SOCKET sock);
|
||||||
|
int acceptagain(void);
|
||||||
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family);
|
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family);
|
||||||
int extbindtodevice(struct clientparam *param, SOCKET sock);
|
int extbindtodevice(struct clientparam *param, SOCKET sock);
|
||||||
int intbindtodevice(struct clientparam *param, SOCKET sock);
|
int intbindtodevice(struct clientparam *param, SOCKET sock);
|
||||||
|
|||||||
@ -88,6 +88,8 @@ void * threadfunc (void *p) {
|
|||||||
}
|
}
|
||||||
param->remsock = param->srv->so._accept(param->sostate, param->srv->cbsock, (struct sockaddr*)¶m->sinsr, &size);
|
param->remsock = param->srv->so._accept(param->sostate, param->srv->cbsock, (struct sockaddr*)¶m->sinsr, &size);
|
||||||
if(param->remsock == INVALID_SOCKET) {
|
if(param->remsock == INVALID_SOCKET) {
|
||||||
|
/* another client of the service took it: not a try */
|
||||||
|
if(acceptagain()) { i++; continue; }
|
||||||
dolog(param, (unsigned char *)"Connect back accept() failed");
|
dolog(param, (unsigned char *)"Connect back accept() failed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -984,6 +986,8 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
setopts(srv.cbsock, srv.cbssockopts);
|
setopts(srv.cbsock, srv.cbssockopts);
|
||||||
|
/* the clients of the service all wait for it: one accepts what comes */
|
||||||
|
nonblock(srv.cbsock);
|
||||||
|
|
||||||
if(srv.so._bind(srv.so.state, srv.cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) {
|
if(srv.so._bind(srv.so.state, srv.cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) {
|
||||||
dolog(&defparam, (unsigned char *)"Failed to bind connect back socket");
|
dolog(&defparam, (unsigned char *)"Failed to bind connect back socket");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user