mirror of
https://github.com/debauchee/barrier.git
synced 2026-05-08 14:41:57 +08:00
Made socket self-aware of when it is in a fatal state #4697
Added code to cleanly terminate connection on fatal socket state #4697
This commit is contained in:
@@ -52,7 +52,8 @@ SecureSocket::SecureSocket(
|
||||
SocketMultiplexer* socketMultiplexer) :
|
||||
TCPSocket(events, socketMultiplexer),
|
||||
m_secureReady(false),
|
||||
m_maxRetry(MAX_RETRY_COUNT)
|
||||
m_maxRetry(MAX_RETRY_COUNT),
|
||||
m_fatal(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -62,12 +63,14 @@ SecureSocket::SecureSocket(
|
||||
ArchSocket socket) :
|
||||
TCPSocket(events, socketMultiplexer, socket),
|
||||
m_secureReady(false),
|
||||
m_maxRetry(MAX_RETRY_COUNT)
|
||||
m_maxRetry(MAX_RETRY_COUNT),
|
||||
m_fatal(false)
|
||||
{
|
||||
}
|
||||
|
||||
SecureSocket::~SecureSocket()
|
||||
{
|
||||
isFatal(true);
|
||||
if (m_ssl->m_ssl != NULL) {
|
||||
SSL_shutdown(m_ssl->m_ssl);
|
||||
|
||||
@@ -78,13 +81,15 @@ SecureSocket::~SecureSocket()
|
||||
SSL_CTX_free(m_ssl->m_context);
|
||||
m_ssl->m_context = NULL;
|
||||
}
|
||||
|
||||
ARCH->sleep(1);
|
||||
delete m_ssl;
|
||||
}
|
||||
|
||||
void
|
||||
SecureSocket::close()
|
||||
{
|
||||
isFatal(true);
|
||||
|
||||
SSL_shutdown(m_ssl->m_ssl);
|
||||
|
||||
TCPSocket::close();
|
||||
@@ -114,17 +119,23 @@ SecureSocket::secureRead(void* buffer, UInt32 n)
|
||||
LOG((CLOG_DEBUG2 "reading secure socket"));
|
||||
r = SSL_read(m_ssl->m_ssl, buffer, n);
|
||||
|
||||
bool fatal;
|
||||
static int retry;
|
||||
|
||||
checkResult(r, fatal, retry);
|
||||
// Check result will cleanup the connection in the case of a fatal
|
||||
checkResult(r, retry);
|
||||
|
||||
if (retry) {
|
||||
r = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isFatal()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return r > 0 ? (UInt32)r : 0;
|
||||
// According to SSL spec, r must not be negative and not have an error code
|
||||
// from SSL_get_error(). If this happens, it is itself an error. Let the
|
||||
// parent handle the case
|
||||
return (UInt32)r;
|
||||
}
|
||||
|
||||
UInt32
|
||||
@@ -132,20 +143,27 @@ SecureSocket::secureWrite(const void* buffer, UInt32 n)
|
||||
{
|
||||
int r = 0;
|
||||
if (m_ssl->m_ssl != NULL) {
|
||||
LOG((CLOG_DEBUG2 "writing secure socket"));
|
||||
LOG((CLOG_DEBUG2 "writing secure socket:%p", this));
|
||||
|
||||
r = SSL_write(m_ssl->m_ssl, buffer, n);
|
||||
|
||||
bool fatal;
|
||||
static int retry;
|
||||
|
||||
checkResult(r, fatal, retry);
|
||||
// Check result will cleanup the connection in the case of a fatal
|
||||
checkResult(r, retry);
|
||||
|
||||
if (retry) {
|
||||
r = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isFatal()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return r > 0 ? (UInt32)r : 0;
|
||||
// According to SSL spec, r must not be negative and not have an error code
|
||||
// from SSL_get_error(). If this happens, it is itself an error. Let the
|
||||
// parent handle the case
|
||||
return (UInt32)r;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -260,12 +278,11 @@ SecureSocket::secureAccept(int socket)
|
||||
LOG((CLOG_DEBUG2 "accepting secure socket"));
|
||||
int r = SSL_accept(m_ssl->m_ssl);
|
||||
|
||||
bool fatal;
|
||||
static int retry;
|
||||
|
||||
checkResult(r, fatal, retry);
|
||||
checkResult(r, retry);
|
||||
|
||||
if (fatal) {
|
||||
if (isFatal()) {
|
||||
// tell user and sleep so the socket isn't hammered.
|
||||
LOG((CLOG_ERR "failed to accept secure socket"));
|
||||
LOG((CLOG_INFO "client connection may not be secure"));
|
||||
@@ -304,12 +321,11 @@ SecureSocket::secureConnect(int socket)
|
||||
LOG((CLOG_DEBUG2 "connecting secure socket"));
|
||||
int r = SSL_connect(m_ssl->m_ssl);
|
||||
|
||||
bool fatal;
|
||||
static int retry;
|
||||
|
||||
checkResult(r, fatal, retry);
|
||||
checkResult(r, retry);
|
||||
|
||||
if (fatal) {
|
||||
if (isFatal()) {
|
||||
LOG((CLOG_ERR "failed to connect secure socket"));
|
||||
return -1;
|
||||
}
|
||||
@@ -362,13 +378,11 @@ SecureSocket::showCertificate()
|
||||
}
|
||||
|
||||
void
|
||||
SecureSocket::checkResult(int n, bool& fatal, int& retry)
|
||||
SecureSocket::checkResult(int n, int& retry)
|
||||
{
|
||||
// ssl errors are a little quirky. the "want" errors are normal and
|
||||
// should result in a retry.
|
||||
|
||||
fatal = false;
|
||||
|
||||
int errorCode = SSL_get_error(m_ssl->m_ssl, n);
|
||||
switch (errorCode) {
|
||||
case SSL_ERROR_NONE:
|
||||
@@ -378,8 +392,8 @@ SecureSocket::checkResult(int n, bool& fatal, int& retry)
|
||||
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
// connection closed
|
||||
retry = 0;
|
||||
LOG((CLOG_DEBUG2 "SSL connection has been closed"));
|
||||
isFatal(true);
|
||||
LOG((CLOG_DEBUG "SSL connection has been closed"));
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
@@ -389,7 +403,7 @@ SecureSocket::checkResult(int n, bool& fatal, int& retry)
|
||||
retry += 1;
|
||||
// If there are a lot of retrys, it's worth warning about
|
||||
if ( retry % 5 == 0 ) {
|
||||
LOG((CLOG_INFO "need to retry the same SSL function(%d) retry:%d", errorCode, retry));
|
||||
LOG((CLOG_DEBUG "need to retry the same SSL function(%d) retry:%d", errorCode, retry));
|
||||
}
|
||||
else if ( retry == (maxRetry() / 2) ) {
|
||||
LOG((CLOG_WARN "need to retry the same SSL function(%d) retry:%d", errorCode, retry));
|
||||
@@ -416,27 +430,27 @@ SecureSocket::checkResult(int n, bool& fatal, int& retry)
|
||||
}
|
||||
}
|
||||
|
||||
fatal = true;
|
||||
isFatal(true);
|
||||
break;
|
||||
|
||||
case SSL_ERROR_SSL:
|
||||
LOG((CLOG_ERR "a failure in the SSL library occurred"));
|
||||
fatal = true;
|
||||
isFatal(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG((CLOG_ERR "unknown secure socket error"));
|
||||
fatal = true;
|
||||
isFatal(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the retry max would exceed the allowed, treat it as a fatal error
|
||||
if (retry > maxRetry()) {
|
||||
LOG((CLOG_ERR "Maximum retry count exceeded:%d",retry));
|
||||
fatal = true;
|
||||
isFatal(true);
|
||||
}
|
||||
|
||||
if (fatal) {
|
||||
if (isFatal()) {
|
||||
retry = 0;
|
||||
showError();
|
||||
disconnect();
|
||||
|
||||
Reference in New Issue
Block a user