mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-15 16:15:49 +08:00
Write to a peer that hung up while it still reads, on Windows
sockmap() took a hang-up on a socket it had data to write to for a peer it could no longer write to. With poll() a hang-up comes once both sides are shut down, so that held. WSAPoll reports one as soon as the peer has half-closed, still reading, and a half-closed client got nothing on Windows: the test added with the previous fix failed there. The write is now tried, and a peer really gone makes it fail, which ends the connection as before. WSAPoll keeps reporting the hang-up whether the socket has room or not, so on Windows room is waited for with select() first unless poll() reported it too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit ddefa40affb76de267a8be1cf59a183a8eb77e32)
This commit is contained in:
parent
993c1ef95e
commit
84dd84a993
@ -61,6 +61,28 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le
|
||||
before the sockets are closed. */
|
||||
#define SESSIONEND (!halfclose && (CLIENTTERMREAD || SERVERTERMREAD))
|
||||
|
||||
/* A hang-up on a socket there is data to write to. With poll() it comes
|
||||
once both sides are shut down, and the write tried then fails, which ends
|
||||
it. WSAPoll reports it as soon as the peer has half-closed, a peer still
|
||||
reading, and keeps reporting it whether the socket has room or not: room
|
||||
is waited for with select() then, up to timeo seconds. Returns whether to
|
||||
try the write. */
|
||||
static int hupwrite(SOCKET s, short revents, int timeo){
|
||||
#ifdef _WIN32
|
||||
if(!(revents & POLLOUT)){
|
||||
fd_set wfd;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&wfd);
|
||||
FD_SET(s, &wfd);
|
||||
tv.tv_sec = timeo;
|
||||
tv.tv_usec = 0;
|
||||
if(select(0, NULL, &wfd, NULL, &tv) < 1) return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* usesplice is a mask of the directions passed with splice() rather than
|
||||
through a buffer: SPLICE_DOWNLOAD, server to client, and SPLICE_UPLOAD,
|
||||
client to server. */
|
||||
@ -677,7 +699,10 @@ log("ready to write to client");
|
||||
}
|
||||
if(fds[fdsc].revents & (POLLHUP)) {
|
||||
if(fds[fdsc].events & POLLIN) FROMCLIENT = 1;
|
||||
if(fds[fdsc].events & POLLOUT) CLIENTTERMWRITE = 1;
|
||||
if(fds[fdsc].events & POLLOUT){
|
||||
if(hupwrite(param->clisock, fds[fdsc].revents, timeo)) TOCLIENT = 1;
|
||||
else CLIENTTERMWRITE = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(fds[fdsc].revents & (POLLERR|POLLNVAL)) {
|
||||
@ -742,7 +767,10 @@ log("ready to write to server");
|
||||
log("server terminated connection");
|
||||
#endif
|
||||
if(fds[fdsc].events & POLLIN) FROMSERVER = 1;
|
||||
if(fds[fdsc].events & POLLOUT) SERVERTERMWRITE = 1;
|
||||
if(fds[fdsc].events & POLLOUT){
|
||||
if(hupwrite(param->remsock, fds[fdsc].revents, timeo)) TOSERVER = 1;
|
||||
else SERVERTERMWRITE = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(fds[fdsc].revents & (POLLERR|POLLNVAL)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user