A TLS sendData() failing with SSL_ERROR_WANT_READ (mid-handshake application data, or a post-handshake session ticket exchange) has nothing to do with write-readiness, but resetSocket() kept re-arming EPOLLWRNORM anyway - an already-writable TCP socket fires that immediately, so the retry loop spun the CPU as fast as it could until the connection was eventually dropped, without ever reading the peer's first command. Confirmed via a 15GB+ debug log from one stuck connection. sendNeedsRead() lets Socket now tell the difference and wait for a real EPOLLIN instead of busy-retrying.
87 lines
2.4 KiB
C++
87 lines
2.4 KiB
C++
#ifndef __TLS_h__
|
|
#define __TLS_h__
|
|
|
|
#include "ZString.h"
|
|
#include "TLSInfo.h"
|
|
#include <openssl/ssl.h>
|
|
|
|
namespace core {
|
|
|
|
///
|
|
/// TLS
|
|
///
|
|
/// This object provides the support methods to handle TLS on the server core and
|
|
/// session environment.
|
|
///
|
|
|
|
class TLS {
|
|
|
|
public:
|
|
|
|
///
|
|
///
|
|
///
|
|
|
|
TLS();
|
|
|
|
///
|
|
/// Use this constructor when the SSL context needs to be created as when opening
|
|
/// a server TCPSocket.
|
|
///
|
|
|
|
TLS(TLSInfo *tlsInfo);
|
|
|
|
///
|
|
/// Use this constructor on creation of a new TCPSocket that needs access to
|
|
/// the generating server's SSL context.
|
|
///
|
|
|
|
TLS(SSL_CTX *ctx);
|
|
|
|
///
|
|
/// The destructor for this object.
|
|
///
|
|
|
|
~TLS();
|
|
|
|
void createContext(TLSInfo *tlsInfo);
|
|
|
|
// A never-configured TLS object (either the listening TCPServer
|
|
// itself when constructed with tlsInfo=NULL, or a TCPSession spawned
|
|
// from one via TLS(SSL_CTX*)) must default to a real NULL here, not
|
|
// garbage - TCPSocket::receiveData()/sendData() key their TLS-vs-
|
|
// plain dispatch on this exact value (see TCPSocket.cpp).
|
|
SSL_CTX *ctx = NULL;
|
|
|
|
protected:
|
|
int receiveData(coreutils::ZString &buffer);
|
|
int sendData(const char *data, int length);
|
|
void registerSocket(int fd);
|
|
void acceptSocket();
|
|
|
|
protected:
|
|
// Set by sendData() when the last SSL_write() failed specifically
|
|
// with SSL_ERROR_WANT_READ (needs a READ to make progress - e.g.
|
|
// mid-handshake application data, or a post-handshake session
|
|
// ticket exchange) rather than any other reason. TCPSocket::
|
|
// sendNeedsRead() reads this (protected, so a subclass can reach
|
|
// it directly) to tell Socket::writeSocket()/resetSocket() not to
|
|
// busy-spin retrying the write via EPOLLWRNORM - see their own
|
|
// doc comments for the confirmed real damage (a 15GB+ debug log,
|
|
// and every affected connection dropped before ever reading the
|
|
// client's first command) this caused when unaddressed.
|
|
bool lastSendWantedRead = false;
|
|
|
|
private:
|
|
char *sip_cacert = (char *)"../testkeys/certs/pbxca.crt";
|
|
char *sip_cert = (char *)"../testkeys/certs/pbxserver.crt";
|
|
char *sip_key = (char *)"../testkeys/certs/pbxserver.key";
|
|
bool initialized = false;
|
|
SSL *ssl;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|