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);
|
struct SSLsock *sslq = searchSSL(param->sostate, s);
|
||||||
|
|
||||||
if(!sslq) return 0;
|
if(!sslq) return 0;
|
||||||
return ssl_pending(sslq->conn)? SPLICE_TLSPENDING : SPLICE_TLS;
|
return ssl_buffered(sslq->conn)? SPLICE_TLSPENDING : SPLICE_TLS;
|
||||||
}
|
}
|
||||||
#endif
|
#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_read(SSL_CONN connection, void * buf, int bufsize);
|
||||||
int ssl_write(SSL_CONN connection, void * buf, int bufsize);
|
int ssl_write(SSL_CONN connection, void * buf, int bufsize);
|
||||||
int ssl_pending(SSL_CONN connection);
|
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
|
/* 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
|
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);
|
return SSL_write(conn->ssl, buf, bufsize);
|
||||||
}
|
}
|
||||||
int ssl_pending(SSL_CONN connection)
|
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;
|
ssl_conn *conn = (ssl_conn *) connection;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user