mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
TLS: a read needing to write, or a write to read, waits for it
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
Update version files / version (push) Has been cancelled
Some checks failed
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ubuntu-latest (wolfSSL) (push) Waiting to run
Update version files / version (push) Has been cancelled
A read TLS could do only once it wrote, or a write once it read, was an error which ended the connection, as when TLS 1.3 answers a key update while the socket cannot take more. Each TLS socket remembers what a read and a write it could not do wait for, and the poll of the TLS layer waits for it instead of what was asked: whatever that gets is the caller's chance to try again, revents what it asked for, and its events are given back as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6ec8a4d1ac
commit
f4c5c723bd
44
src/ssl.c
44
src/ssl.c
@ -75,6 +75,9 @@ static int ktls = 0;
|
||||
struct SSLsock {
|
||||
SOCKET s;
|
||||
SSL_CONN conn;
|
||||
/* what a read and a write which could not be done wait for, POLLIN
|
||||
or POLLOUT, 0 once one is: TLS may have to write to read */
|
||||
short rwant, wwant;
|
||||
};
|
||||
|
||||
struct SSLstate {
|
||||
@ -103,10 +106,12 @@ static void addSSL(
|
||||
if (cli_s != INVALID_SOCKET){
|
||||
SOSTATE->cli.s = cli_s;
|
||||
SOSTATE->cli.conn = cli_conn;
|
||||
SOSTATE->cli.rwant = SOSTATE->cli.wwant = 0;
|
||||
}
|
||||
if (srv_s != INVALID_SOCKET){
|
||||
SOSTATE->srv.s = srv_s;
|
||||
SOSTATE->srv.conn = srv_conn;
|
||||
SOSTATE->srv.rwant = SOSTATE->srv.wwant = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,12 +142,14 @@ static ssize_t ssl_send(void *state, SOCKET s, const void *msg, size_t len, int
|
||||
int res, err;
|
||||
if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0){
|
||||
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
|
||||
if (err == SSL_ERROR_WANT_WRITE){
|
||||
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ){
|
||||
sslq->wwant = (err == SSL_ERROR_WANT_READ)? POLLIN : POLLOUT;
|
||||
seterrno3(EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
else seterrno3(err);
|
||||
}
|
||||
else sslq->wwant = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -161,12 +168,14 @@ static ssize_t ssl_sendto(void *state, SOCKET s, const void *msg, size_t len, in
|
||||
int res, err;
|
||||
if((res = ssl_write(sslq->conn, (void *)msg, len)) <= 0){
|
||||
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
|
||||
if (err == SSL_ERROR_WANT_WRITE){
|
||||
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ){
|
||||
sslq->wwant = (err == SSL_ERROR_WANT_READ)? POLLIN : POLLOUT;
|
||||
seterrno3(EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
else seterrno3(err);
|
||||
}
|
||||
else sslq->wwant = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -184,12 +193,14 @@ static ssize_t ssl_recvfrom(void *state, SOCKET s, void *msg, size_t len, int f
|
||||
int res, err;
|
||||
if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) {
|
||||
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
||||
sslq->rwant = (err == SSL_ERROR_WANT_WRITE)? POLLOUT : POLLIN;
|
||||
seterrno3(EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
else seterrno3(err);
|
||||
}
|
||||
else sslq->rwant = 0;
|
||||
return res;
|
||||
}
|
||||
return sso._recvfrom(sso.state, s, msg, len, flags, from, fromlen);
|
||||
@ -206,12 +217,14 @@ static ssize_t ssl_recv(void *state, SOCKET s, void *msg, size_t len, int flags)
|
||||
int res, err;
|
||||
if((res = ssl_read(sslq->conn, (void *)msg, len)) <= 0) {
|
||||
err = SSL_get_error((SSL *)((ssl_conn*)sslq->conn)->ssl, res);
|
||||
if (err == SSL_ERROR_WANT_READ) {
|
||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
|
||||
sslq->rwant = (err == SSL_ERROR_WANT_WRITE)? POLLOUT : POLLIN;
|
||||
seterrno3(EAGAIN);
|
||||
return -1;
|
||||
}
|
||||
else seterrno3(err);
|
||||
}
|
||||
else sslq->rwant = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -236,6 +249,8 @@ static int ssl_poll(void *state, struct pollfd *fds, nfds_t nfds, int timeout){
|
||||
struct SSLsock *sslq = NULL;
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
short own[64], *events = own, ev;
|
||||
|
||||
for(i = 0; i < nfds; i++){
|
||||
if((fds[i].events & POLLIN) && (sslq = searchSSL(state, fds[i].fd)) && ssl_pending(sslq->conn)){
|
||||
fds[i].revents = POLLIN;
|
||||
@ -244,8 +259,29 @@ static int ssl_poll(void *state, struct pollfd *fds, nfds_t nfds, int timeout){
|
||||
else fds[i].revents = 0;
|
||||
}
|
||||
if(ret) return ret;
|
||||
for(i = 0; i < nfds; i++) if((sslq = searchSSL(state, fds[i].fd)) && (sslq->rwant || sslq->wwant)) break;
|
||||
if(i == nfds) return sso._poll(state, fds, nfds, timeout);
|
||||
|
||||
/* A read or a write TLS could not do waits for what TLS needs, a read
|
||||
for the socket to be writable: whatever that gets is the caller's
|
||||
chance to try again, revents what it asked for, and its events are
|
||||
given back as they were. */
|
||||
if(nfds > sizeof(own)/sizeof(own[0]) && !(events = malloc(nfds * sizeof(*events)))) return -1;
|
||||
for(i = 0; i < nfds; i++){
|
||||
events[i] = fds[i].events;
|
||||
if(!(sslq = searchSSL(state, fds[i].fd))) continue;
|
||||
ev = fds[i].events & ~(POLLIN|POLLOUT);
|
||||
if(fds[i].events & POLLIN) ev |= sslq->rwant? sslq->rwant : POLLIN;
|
||||
if(fds[i].events & POLLOUT) ev |= sslq->wwant? sslq->wwant : POLLOUT;
|
||||
fds[i].events = ev;
|
||||
}
|
||||
ret = sso._poll(state, fds, nfds, timeout);
|
||||
for(i = 0; i < nfds; i++){
|
||||
if(ret > 0 && fds[i].events != events[i] && (fds[i].revents & ~(POLLERR|POLLHUP|POLLNVAL)))
|
||||
fds[i].revents = events[i] | (fds[i].revents & (POLLERR|POLLHUP|POLLNVAL));
|
||||
fds[i].events = events[i];
|
||||
}
|
||||
if(events != own) free(events);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user