mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-28 22:05:48 +08:00
TLS: a part of a record read ahead is not pending data
SSL_has_pending() is true when only a part of a record has been read ahead, which is no data yet. ssl_poll() took it for data: poll() returned at once, over and over and without its timeout, until the rest came, so a peer sending half a record kept a thread spinning and its connection from timing out. ssl_pending() is now true only when decrypted data waits, or when what was read ahead makes a whole record (an SSL_peek() of one byte, the sockets not blocking); otherwise the socket is polled for the rest. splice() over kernel TLS still needs to know of any byte OpenSSL holds, a part of a record too: ssl_buffered() tells it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3d20e1104e
commit
2514fb3dbf
@ -429,7 +429,7 @@ static int ssl_splicetls(struct clientparam *param, SOCKET s){
|
||||
struct SSLsock *sslq = searchSSL(param->sostate, s);
|
||||
|
||||
if(!sslq) return 0;
|
||||
return ssl_pending(sslq->conn)? SPLICE_TLSPENDING : SPLICE_TLS;
|
||||
return ssl_buffered(sslq->conn)? SPLICE_TLSPENDING : SPLICE_TLS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@ -78,6 +78,9 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CONFIG *config,
|
||||
int ssl_read(SSL_CONN connection, void * buf, int bufsize);
|
||||
int ssl_write(SSL_CONN connection, void * buf, int bufsize);
|
||||
int ssl_pending(SSL_CONN connection);
|
||||
/* any data read from the socket and not handed out, a part of a record
|
||||
too */
|
||||
int ssl_buffered(SSL_CONN connection);
|
||||
|
||||
/* TLS records are read ahead, a buffer at a time rather than two reads for
|
||||
each record, where what is read ahead and not yet decrypted shows as
|
||||
|
||||
24
src/ssllib.c
24
src/ssllib.c
@ -259,6 +259,30 @@ int ssl_write(SSL_CONN connection, void * buf, int bufsize)
|
||||
return SSL_write(conn->ssl, buf, bufsize);
|
||||
}
|
||||
int ssl_pending(SSL_CONN connection)
|
||||
{
|
||||
ssl_conn *conn = (ssl_conn *) connection;
|
||||
#if SSL_READAHEAD
|
||||
char c;
|
||||
int res;
|
||||
|
||||
if(SSL_pending(conn->ssl) > 0) return 1;
|
||||
if(!SSL_has_pending(conn->ssl)) return 0;
|
||||
/* Read ahead and not decrypted: a record, or only a part of one. A
|
||||
part is no data, and saying so would have poll() return at once,
|
||||
again and again, without its timeout, until the rest came: it is
|
||||
pending only once the record is whole (or the connection ended),
|
||||
the socket polled for the rest otherwise. The sockets are not
|
||||
blocking, so this does not wait. */
|
||||
res = SSL_peek(conn->ssl, &c, 1);
|
||||
if(res > 0) return 1;
|
||||
res = SSL_get_error(conn->ssl, res);
|
||||
return res != SSL_ERROR_WANT_READ && res != SSL_ERROR_WANT_WRITE;
|
||||
#else
|
||||
return SSL_pending(conn->ssl);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ssl_buffered(SSL_CONN connection)
|
||||
{
|
||||
ssl_conn *conn = (ssl_conn *) connection;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user