More cleanup in LuprexSockets.
This commit is contained in:
@@ -9,7 +9,6 @@
|
|||||||
#include "SocketSubsystem.h"
|
#include "SocketSubsystem.h"
|
||||||
#include "AddressInfoTypes.h"
|
#include "AddressInfoTypes.h"
|
||||||
|
|
||||||
|
|
||||||
#define UI UI_ST
|
#define UI UI_ST
|
||||||
THIRD_PARTY_INCLUDES_START
|
THIRD_PARTY_INCLUDES_START
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
@@ -36,7 +35,9 @@ THIRD_PARTY_INCLUDES_END
|
|||||||
|
|
||||||
#define MAX_BIO_BUFFER (128 * 1024)
|
#define MAX_BIO_BUFFER (128 * 1024)
|
||||||
|
|
||||||
static const char* dummy_cert =
|
namespace {
|
||||||
|
|
||||||
|
const char* dummy_cert =
|
||||||
"-----BEGIN CERTIFICATE-----\n"
|
"-----BEGIN CERTIFICATE-----\n"
|
||||||
"MIIDezCCAmOgAwIBAgIUajKmxrLMr9zBMlphrTJU5qKG8FgwDQYJKoZIhvcNAQEL\n"
|
"MIIDezCCAmOgAwIBAgIUajKmxrLMr9zBMlphrTJU5qKG8FgwDQYJKoZIhvcNAQEL\n"
|
||||||
"BQAwTDELMAkGA1UEBhMCVVMxFTATBgNVBAgMDFBlbm5zeWx2YW5pYTESMBAGA1UE\n"
|
"BQAwTDELMAkGA1UEBhMCVVMxFTATBgNVBAgMDFBlbm5zeWx2YW5pYTESMBAGA1UE\n"
|
||||||
@@ -59,7 +60,7 @@ static const char* dummy_cert =
|
|||||||
"z+DnJGjHrV1J/jHPrnVvVLpigBlGno3C5O/sRw3gcQ==\n"
|
"z+DnJGjHrV1J/jHPrnVvVLpigBlGno3C5O/sRw3gcQ==\n"
|
||||||
"-----END CERTIFICATE-----\n";
|
"-----END CERTIFICATE-----\n";
|
||||||
|
|
||||||
static const char* dummy_key =
|
const char* dummy_key =
|
||||||
"-----BEGIN PRIVATE KEY-----\n"
|
"-----BEGIN PRIVATE KEY-----\n"
|
||||||
"MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDk5Yhoqphp7ic/\n"
|
"MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDk5Yhoqphp7ic/\n"
|
||||||
"G+7kQ/dWKVyMClhwxPj7bKl9CgHo8R6nmXCC4D3b2s2xMqeEawSJABnR5k8Rk3tW\n"
|
"G+7kQ/dWKVyMClhwxPj7bKl9CgHo8R6nmXCC4D3b2s2xMqeEawSJABnR5k8Rk3tW\n"
|
||||||
@@ -116,7 +117,8 @@ public:
|
|||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
enum EChanState {
|
enum EChanState
|
||||||
|
{
|
||||||
CHAN_INACTIVE,
|
CHAN_INACTIVE,
|
||||||
CHAN_SSL_CONNECTING,
|
CHAN_SSL_CONNECTING,
|
||||||
CHAN_SSL_ACCEPTING,
|
CHAN_SSL_ACCEPTING,
|
||||||
@@ -204,20 +206,16 @@ public:
|
|||||||
TArray<FlxListener> Listeners;
|
TArray<FlxListener> Listeners;
|
||||||
|
|
||||||
// Pointer to the socket subsystem.
|
// Pointer to the socket subsystem.
|
||||||
ISocketSubsystem* Subsys;
|
ISocketSubsystem* Subsys = nullptr;
|
||||||
|
|
||||||
BIO* TraceBIO;
|
SSL_CTX* ServerCTX = nullptr;
|
||||||
|
SSL_CTX* ClientSecureCTX = nullptr;
|
||||||
SSL_CTX* ServerCTX;
|
SSL_CTX* ClientInsecureCTX = nullptr;
|
||||||
SSL_CTX* ClientSecureCTX;
|
|
||||||
SSL_CTX* ClientInsecureCTX;
|
|
||||||
|
|
||||||
|
public:
|
||||||
FlxSocketsI(FlxLockedWrapper &w);
|
FlxSocketsI(FlxLockedWrapper &w);
|
||||||
virtual ~FlxSocketsI() override;
|
virtual ~FlxSocketsI() override;
|
||||||
|
|
||||||
// Copy the trace to UE_LOG.
|
|
||||||
void LogTrace();
|
|
||||||
|
|
||||||
// Error handling.
|
// Error handling.
|
||||||
void SetError(const std::string& s);
|
void SetError(const std::string& s);
|
||||||
virtual std::string GetError() override { return FatalError; }
|
virtual std::string GetError() override { return FatalError; }
|
||||||
@@ -246,8 +244,7 @@ public:
|
|||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
FSocket* OpenConnection(ISocketSubsystem *subsys, const std::string& host, const std::string& port, std::string& err)
|
||||||
static FSocket* OpenConnection(ISocketSubsystem *subsys, const std::string& host, const std::string& port, std::string& err)
|
|
||||||
{
|
{
|
||||||
std::string hostport = host + ":" + port;
|
std::string hostport = host + ":" + port;
|
||||||
FString fshost(host.size(), (const UTF8CHAR*)host.c_str());
|
FString fshost(host.size(), (const UTF8CHAR*)host.c_str());
|
||||||
@@ -255,7 +252,8 @@ static FSocket* OpenConnection(ISocketSubsystem *subsys, const std::string& host
|
|||||||
|
|
||||||
FAddressInfoResult air = subsys->GetAddressInfo(*fshost, *fsport, EAddressInfoFlags::Default, NAME_None, ESocketType::SOCKTYPE_Streaming);
|
FAddressInfoResult air = subsys->GetAddressInfo(*fshost, *fsport, EAddressInfoFlags::Default, NAME_None, ESocketType::SOCKTYPE_Streaming);
|
||||||
|
|
||||||
if (air.Results.Num() == 0) {
|
if (air.Results.Num() == 0)
|
||||||
|
{
|
||||||
err = std::string("DNS Lookup failed for: ") + hostport;
|
err = std::string("DNS Lookup failed for: ") + hostport;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -336,12 +334,14 @@ FSocket* ListenOnPort(ISocketSubsystem* subsys, int port, std::string& err)
|
|||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void SSLClearErrors() {
|
void SSLClearErrors()
|
||||||
|
{
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string SSLFullErrorString() {
|
std::string SSLFullErrorString()
|
||||||
|
{
|
||||||
BIO* b = BIO_new(BIO_s_mem());
|
BIO* b = BIO_new(BIO_s_mem());
|
||||||
ERR_print_errors(b);
|
ERR_print_errors(b);
|
||||||
char* data;
|
char* data;
|
||||||
@@ -352,10 +352,12 @@ static std::string SSLFullErrorString() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string SSLErrorString() {
|
std::string SSLErrorString()
|
||||||
|
{
|
||||||
// Get the last code.
|
// Get the last code.
|
||||||
int code = 0;
|
int code = 0;
|
||||||
while (true) {
|
while (true)
|
||||||
|
{
|
||||||
int icode = ERR_get_error();
|
int icode = ERR_get_error();
|
||||||
if (icode == 0) break;
|
if (icode == 0) break;
|
||||||
code = icode;
|
code = icode;
|
||||||
@@ -365,50 +367,55 @@ static std::string SSLErrorString() {
|
|||||||
int terrno = errno;
|
int terrno = errno;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if (code != 0) {
|
if (code != 0)
|
||||||
|
{
|
||||||
const char* rc = ERR_reason_error_string(code);
|
const char* rc = ERR_reason_error_string(code);
|
||||||
if (rc != nullptr) {
|
if (rc != nullptr)
|
||||||
|
{
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
return std::system_category().message(ERR_GET_REASON(code));
|
return std::system_category().message(ERR_GET_REASON(code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (terrno != 0) {
|
else if (terrno != 0)
|
||||||
|
{
|
||||||
return std::system_category().message(terrno);
|
return std::system_category().message(terrno);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SSL_CTX* SSLNewContext(int verify, const SSL_METHOD *method, BIO *tracebio) {
|
SSL_CTX* SSLNewContext(int verify, const SSL_METHOD *method)
|
||||||
|
{
|
||||||
check(method != nullptr);
|
check(method != nullptr);
|
||||||
SSL_CTX* ctx = SSL_CTX_new(method);
|
SSL_CTX* ctx = SSL_CTX_new(method);
|
||||||
SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||||
SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||||
SSL_CTX_set_verify(ctx, verify, nullptr);
|
SSL_CTX_set_verify(ctx, verify, nullptr);
|
||||||
SSL_CTX_set_ecdh_auto(ctx, 1);
|
SSL_CTX_set_ecdh_auto(ctx, 1);
|
||||||
//if (tracebio != nullptr)
|
|
||||||
//{
|
|
||||||
// SSL_CTX_set_msg_callback(ctx, SSL_trace);
|
|
||||||
// SSL_CTX_set_msg_callback_arg(ctx, tracebio);
|
|
||||||
//}
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
static std::string SSLLoadCertificateAuthorities(SSL_CTX* ctx) {
|
std::string SSLLoadCertificateAuthorities(SSL_CTX* ctx)
|
||||||
if (SSL_CTX_set_default_verify_paths(ctx) != 1) {
|
{
|
||||||
|
if (SSL_CTX_set_default_verify_paths(ctx) != 1)
|
||||||
|
{
|
||||||
return "Could not load default certificate authority paths.";
|
return "Could not load default certificate authority paths.";
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static std::string SSLLoadCertificateAuthorities(SSL_CTX* ctx) {
|
std::string SSLLoadCertificateAuthorities(SSL_CTX* ctx)
|
||||||
|
{
|
||||||
HCERTSTORE hStore = CertOpenSystemStoreW(0, L"ROOT");
|
HCERTSTORE hStore = CertOpenSystemStoreW(0, L"ROOT");
|
||||||
|
|
||||||
if (!hStore) {
|
if (!hStore)
|
||||||
|
{
|
||||||
return "Could not open system cert store.";
|
return "Could not open system cert store.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +429,8 @@ static std::string SSLLoadCertificateAuthorities(SSL_CTX* ctx) {
|
|||||||
if (pContext == nullptr) break;
|
if (pContext == nullptr) break;
|
||||||
const unsigned char* encoded_cert = pContext->pbCertEncoded;
|
const unsigned char* encoded_cert = pContext->pbCertEncoded;
|
||||||
x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
|
x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
|
||||||
if (x509) {
|
if (x509)
|
||||||
|
{
|
||||||
X509_STORE_add_cert(store, x509);
|
X509_STORE_add_cert(store, x509);
|
||||||
X509_free(x509);
|
X509_free(x509);
|
||||||
}
|
}
|
||||||
@@ -433,7 +441,8 @@ static std::string SSLLoadCertificateAuthorities(SSL_CTX* ctx) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::string SSLUseCertificateString(SSL_CTX* ctx, const char* str) {
|
std::string SSLUseCertificateString(SSL_CTX* ctx, const char* str)
|
||||||
|
{
|
||||||
SSLClearErrors();
|
SSLClearErrors();
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
BIO* bio = BIO_new(BIO_s_mem());
|
||||||
BIO_puts(bio, str);
|
BIO_puts(bio, str);
|
||||||
@@ -452,7 +461,8 @@ static std::string SSLUseCertificateString(SSL_CTX* ctx, const char* str) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string SSLUsePrivateKeyString(SSL_CTX* ctx, const char* str) {
|
std::string SSLUsePrivateKeyString(SSL_CTX* ctx, const char* str)
|
||||||
|
{
|
||||||
SSLClearErrors();
|
SSLClearErrors();
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
BIO* bio = BIO_new(BIO_s_mem());
|
||||||
BIO_puts(bio, str);
|
BIO_puts(bio, str);
|
||||||
@@ -471,7 +481,7 @@ static std::string SSLUsePrivateKeyString(SSL_CTX* ctx, const char* str) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string SSLLoadDummyCert(SSL_CTX* ctx)
|
std::string SSLLoadDummyCert(SSL_CTX* ctx)
|
||||||
{
|
{
|
||||||
std::string err1 = SSLUseCertificateString(ctx, dummy_cert);
|
std::string err1 = SSLUseCertificateString(ctx, dummy_cert);
|
||||||
std::string err2 = SSLUsePrivateKeyString(ctx, dummy_key);
|
std::string err2 = SSLUsePrivateKeyString(ctx, dummy_key);
|
||||||
@@ -484,7 +494,8 @@ static std::string SSLLoadDummyCert(SSL_CTX* ctx)
|
|||||||
// because MEM BIOs technically have unlimited capacity. We're
|
// because MEM BIOs technically have unlimited capacity. We're
|
||||||
// artificially limiting them to a certain size because there's no
|
// artificially limiting them to a certain size because there's no
|
||||||
// reason to buffer huge amounts of data.
|
// reason to buffer huge amounts of data.
|
||||||
static int BIOSpace(BIO* bio) {
|
int BIOSpace(BIO* bio)
|
||||||
|
{
|
||||||
int space = (MAX_BIO_BUFFER)-BIO_pending(bio);
|
int space = (MAX_BIO_BUFFER)-BIO_pending(bio);
|
||||||
if (space < 0) space = 0;
|
if (space < 0) space = 0;
|
||||||
return space;
|
return space;
|
||||||
@@ -493,8 +504,10 @@ static int BIOSpace(BIO* bio) {
|
|||||||
// Discard the first nbytes in buffer.
|
// Discard the first nbytes in buffer.
|
||||||
// This is a terribly inefficient way to discard data that has
|
// This is a terribly inefficient way to discard data that has
|
||||||
// already been processed. There has to be something better.
|
// already been processed. There has to be something better.
|
||||||
static void BIODiscard(BIO* b, int nbytes, char* chbuf) {
|
void BIODiscard(BIO* b, int nbytes, char* chbuf)
|
||||||
while (nbytes > 0) {
|
{
|
||||||
|
while (nbytes > 0)
|
||||||
|
{
|
||||||
int nread = nbytes;
|
int nread = nbytes;
|
||||||
if (nread > DRV_SHORTSTRING_SIZE) nread = DRV_SHORTSTRING_SIZE;
|
if (nread > DRV_SHORTSTRING_SIZE) nread = DRV_SHORTSTRING_SIZE;
|
||||||
int ndropped = BIO_read(b, chbuf, nread);
|
int ndropped = BIO_read(b, chbuf, nread);
|
||||||
@@ -510,7 +523,6 @@ static void BIODiscard(BIO* b, int nbytes, char* chbuf) {
|
|||||||
//
|
//
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#pragma optimize("", off)
|
|
||||||
FlxChannel::FlxChannel(FlxSocketsI* lsi, FSocket* sock, int chid, SSL_CTX* ctx, EChanState st)
|
FlxChannel::FlxChannel(FlxSocketsI* lsi, FSocket* sock, int chid, SSL_CTX* ctx, EChanState st)
|
||||||
{
|
{
|
||||||
LSI = lsi;
|
LSI = lsi;
|
||||||
@@ -530,10 +542,12 @@ FlxChannel::FlxChannel(FlxSocketsI* lsi, FSocket* sock, int chid, SSL_CTX* ctx,
|
|||||||
State = st;
|
State = st;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlxChannel::Close(std::string_view err) {
|
void FlxChannel::Close(std::string_view err)
|
||||||
|
{
|
||||||
// Close and release the SSL channel.
|
// Close and release the SSL channel.
|
||||||
// This frees the BIO objects as well.
|
// This frees the BIO objects as well.
|
||||||
if (SSLState != nullptr) {
|
if (SSLState != nullptr)
|
||||||
|
{
|
||||||
SSL_free(SSLState);
|
SSL_free(SSLState);
|
||||||
SSLState = nullptr;
|
SSLState = nullptr;
|
||||||
}
|
}
|
||||||
@@ -567,9 +581,10 @@ void FlxChannel::Close(std::string_view err) {
|
|||||||
State = CHAN_INACTIVE;
|
State = CHAN_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma optimize("", off)
|
void FlxChannel::TransferSocketToRecvBIO()
|
||||||
void FlxChannel::TransferSocketToRecvBIO() {
|
{
|
||||||
if ((State == CHAN_INACTIVE) || RecvFail) {
|
if ((State == CHAN_INACTIVE) || RecvFail)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,8 +602,10 @@ void FlxChannel::TransferSocketToRecvBIO() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlxChannel::TransferSendBIOToSocket() {
|
void FlxChannel::TransferSendBIOToSocket()
|
||||||
if ((State == CHAN_INACTIVE) || SendFail) {
|
{
|
||||||
|
if ((State == CHAN_INACTIVE) || SendFail)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,7 +628,8 @@ void FlxChannel::TransferSendBIOToSocket() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlxChannel::CloseChannelIfSSLErrorIsSerious(int retval) {
|
void FlxChannel::CloseChannelIfSSLErrorIsSerious(int retval)
|
||||||
|
{
|
||||||
int error = SSL_get_error(SSLState, retval);
|
int error = SSL_get_error(SSLState, retval);
|
||||||
|
|
||||||
// Should never have write errors, because we're
|
// Should never have write errors, because we're
|
||||||
@@ -620,8 +638,10 @@ void FlxChannel::CloseChannelIfSSLErrorIsSerious(int retval) {
|
|||||||
|
|
||||||
// If we get a read error, make sure it's plausible:
|
// If we get a read error, make sure it's plausible:
|
||||||
// if the recv bio is full, that makes no sense.
|
// if the recv bio is full, that makes no sense.
|
||||||
if (error == SSL_ERROR_WANT_READ) {
|
if (error == SSL_ERROR_WANT_READ)
|
||||||
if (BIOSpace(RecvBIO) == 0) {
|
{
|
||||||
|
if (BIOSpace(RecvBIO) == 0)
|
||||||
|
{
|
||||||
Close("ssl waiting for data, but there's tons of data");
|
Close("ssl waiting for data, but there's tons of data");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -646,7 +666,6 @@ void FlxChannel::AdvanceConnecting()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma optimize("", off)
|
|
||||||
void FlxChannel::AdvanceAccepting()
|
void FlxChannel::AdvanceAccepting()
|
||||||
{
|
{
|
||||||
int retval = SSL_accept(SSLState);
|
int retval = SSL_accept(SSLState);
|
||||||
@@ -658,7 +677,6 @@ void FlxChannel::AdvanceAccepting()
|
|||||||
{
|
{
|
||||||
CloseChannelIfSSLErrorIsSerious( retval);
|
CloseChannelIfSSLErrorIsSerious( retval);
|
||||||
}
|
}
|
||||||
LSI->LogTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlxChannel::AdvanceReadWrite()
|
void FlxChannel::AdvanceReadWrite()
|
||||||
@@ -718,7 +736,6 @@ void FlxChannel::AdvanceReadWrite()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma optimize("", off)
|
|
||||||
void FlxChannel::Advance()
|
void FlxChannel::Advance()
|
||||||
{
|
{
|
||||||
check(State != CHAN_INACTIVE);
|
check(State != CHAN_INACTIVE);
|
||||||
@@ -731,9 +748,12 @@ void FlxChannel::Advance()
|
|||||||
|
|
||||||
// If all outgoing buffers are empty, and Luprex has released
|
// If all outgoing buffers are empty, and Luprex has released
|
||||||
// the channel, close the channel.
|
// the channel, close the channel.
|
||||||
if (NBytes == 0) {
|
if (NBytes == 0)
|
||||||
if (LSI->Luprex->get_channel_released(LSI->Luprex, ChannelID)) {
|
{
|
||||||
if (BIO_pending(SendBIO) == 0) {
|
if (LSI->Luprex->get_channel_released(LSI->Luprex, ChannelID))
|
||||||
|
{
|
||||||
|
if (BIO_pending(SendBIO) == 0)
|
||||||
|
{
|
||||||
Close("");
|
Close("");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -741,7 +761,8 @@ void FlxChannel::Advance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSLClearErrors();
|
SSLClearErrors();
|
||||||
switch (State) {
|
switch (State)
|
||||||
|
{
|
||||||
case CHAN_SSL_CONNECTING:
|
case CHAN_SSL_CONNECTING:
|
||||||
AdvanceConnecting();
|
AdvanceConnecting();
|
||||||
break;
|
break;
|
||||||
@@ -789,7 +810,6 @@ FlxListener::~FlxListener()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma optimize("", off)
|
|
||||||
void FlxListener::AcceptConnection()
|
void FlxListener::AcceptConnection()
|
||||||
{
|
{
|
||||||
FSocket* csocket = Socket->Accept(TEXT("Incoming Connection"));
|
FSocket* csocket = Socket->Accept(TEXT("Incoming Connection"));
|
||||||
@@ -811,7 +831,8 @@ void FlxListener::AcceptConnection()
|
|||||||
|
|
||||||
void FlxSocketsI::SetError(const std::string& s)
|
void FlxSocketsI::SetError(const std::string& s)
|
||||||
{
|
{
|
||||||
if (FatalError.empty()) {
|
if (FatalError.empty())
|
||||||
|
{
|
||||||
FatalError = s;
|
FatalError = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -822,13 +843,6 @@ FlxSocketsI::FlxSocketsI(FlxLockedWrapper &w)
|
|||||||
// We retain this pointer only so long as we have the wrapper lock.
|
// We retain this pointer only so long as we have the wrapper lock.
|
||||||
TGuardValue<EngineWrapper*> GuardLuprex(Luprex, w.Get());
|
TGuardValue<EngineWrapper*> GuardLuprex(Luprex, w.Get());
|
||||||
|
|
||||||
// This function is nonreentrant. It's not clear whether
|
|
||||||
// this is needed - it may be initialized elsewhere in unreal.
|
|
||||||
// It is also not clear that it's safe to do this in the
|
|
||||||
// blueprint thread (this constructor runs in the blueprint
|
|
||||||
// thread).
|
|
||||||
SSL_library_init();
|
|
||||||
|
|
||||||
ServerCTX = nullptr;
|
ServerCTX = nullptr;
|
||||||
ClientSecureCTX = nullptr;
|
ClientSecureCTX = nullptr;
|
||||||
ClientInsecureCTX = nullptr;
|
ClientInsecureCTX = nullptr;
|
||||||
@@ -839,11 +853,9 @@ FlxSocketsI::FlxSocketsI(FlxLockedWrapper &w)
|
|||||||
SetError("Cannot obtain the socket subsystem");
|
SetError("Cannot obtain the socket subsystem");
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceBIO = BIO_new(BIO_s_mem());
|
ServerCTX = SSLNewContext(SSL_VERIFY_NONE, TLS_server_method());
|
||||||
|
ClientSecureCTX = SSLNewContext(SSL_VERIFY_PEER, TLS_client_method());
|
||||||
ServerCTX = SSLNewContext(SSL_VERIFY_NONE, TLS_server_method(), TraceBIO);
|
ClientInsecureCTX = SSLNewContext(SSL_VERIFY_NONE, TLS_client_method());
|
||||||
ClientSecureCTX = SSLNewContext(SSL_VERIFY_PEER, TLS_client_method(), TraceBIO);
|
|
||||||
ClientInsecureCTX = SSLNewContext(SSL_VERIFY_NONE, TLS_client_method(), TraceBIO);
|
|
||||||
|
|
||||||
SetError(SSLLoadCertificateAuthorities(ClientSecureCTX));
|
SetError(SSLLoadCertificateAuthorities(ClientSecureCTX));
|
||||||
SetError(SSLLoadDummyCert(ServerCTX));
|
SetError(SSLLoadDummyCert(ServerCTX));
|
||||||
@@ -865,7 +877,8 @@ void FlxSocketsI::ForceCloseEverything(FlxLockedWrapper& w)
|
|||||||
TGuardValue<EngineWrapper*> GuardLuprex(Luprex, w.Get());
|
TGuardValue<EngineWrapper*> GuardLuprex(Luprex, w.Get());
|
||||||
|
|
||||||
// Close all channels
|
// Close all channels
|
||||||
for (FlxChannel& chan : Channels) {
|
for (FlxChannel& chan : Channels)
|
||||||
|
{
|
||||||
chan.Close("Force Close Everything");
|
chan.Close("Force Close Everything");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,30 +896,15 @@ FlxSocketsI::~FlxSocketsI()
|
|||||||
if (ServerCTX != nullptr)
|
if (ServerCTX != nullptr)
|
||||||
{
|
{
|
||||||
SSL_CTX_free(ServerCTX);
|
SSL_CTX_free(ServerCTX);
|
||||||
ServerCTX = nullptr;
|
|
||||||
}
|
}
|
||||||
if (ClientSecureCTX != nullptr)
|
if (ClientSecureCTX != nullptr)
|
||||||
{
|
{
|
||||||
SSL_CTX_free(ClientSecureCTX);
|
SSL_CTX_free(ClientSecureCTX);
|
||||||
ClientSecureCTX = nullptr;
|
|
||||||
}
|
}
|
||||||
if (ClientInsecureCTX != nullptr)
|
if (ClientInsecureCTX != nullptr)
|
||||||
{
|
{
|
||||||
SSL_CTX_free(ClientInsecureCTX);
|
SSL_CTX_free(ClientInsecureCTX);
|
||||||
ClientInsecureCTX = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Be more thorough.
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlxSocketsI::LogTrace()
|
|
||||||
{
|
|
||||||
char* data;
|
|
||||||
int ndata = BIO_get_mem_data(TraceBIO, &data);
|
|
||||||
if (ndata == 0) return;
|
|
||||||
FString text(ndata, (const UTF8CHAR *)data);
|
|
||||||
UE_LOG(LogLuprexIntegration, Verbose, TEXT("SSL Trace: %s"), *text);
|
|
||||||
BIO_reset(TraceBIO);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlxSocketsI::ListeningOnPort(int p)
|
bool FlxSocketsI::ListeningOnPort(int p)
|
||||||
@@ -922,7 +920,8 @@ void FlxSocketsI::HandleListenPorts()
|
|||||||
{
|
{
|
||||||
uint32_t nports; const uint32_t* ports;
|
uint32_t nports; const uint32_t* ports;
|
||||||
Luprex->get_listen_ports(Luprex, &nports, &ports);
|
Luprex->get_listen_ports(Luprex, &nports, &ports);
|
||||||
for (uint32_t i = 0; i < nports; i++) {
|
for (uint32_t i = 0; i < nports; i++)
|
||||||
|
{
|
||||||
int port = ports[i];
|
int port = ports[i];
|
||||||
if (!ListeningOnPort(port))
|
if (!ListeningOnPort(port))
|
||||||
{
|
{
|
||||||
@@ -945,32 +944,38 @@ void FlxSocketsI::HandleNewOutgoingSockets()
|
|||||||
{
|
{
|
||||||
uint32_t nchids; const uint32_t* chids;
|
uint32_t nchids; const uint32_t* chids;
|
||||||
Luprex->get_new_outgoing(Luprex, &nchids, &chids);
|
Luprex->get_new_outgoing(Luprex, &nchids, &chids);
|
||||||
for (uint32_t i = 0; i < nchids; i++) {
|
for (uint32_t i = 0; i < nchids; i++)
|
||||||
|
{
|
||||||
uint32_t chid = chids[i];
|
uint32_t chid = chids[i];
|
||||||
std::string err, cert, host, port;
|
std::string err, cert, host, port;
|
||||||
const char* target = Luprex->get_target(Luprex, chid);
|
const char* target = Luprex->get_target(Luprex, chid);
|
||||||
drvutil::split_target(target, cert, host, port);
|
drvutil::split_target(target, cert, host, port);
|
||||||
if (cert.empty() || host.empty() || port.empty()) {
|
if (cert.empty() || host.empty() || port.empty())
|
||||||
|
{
|
||||||
std::string message = "invalid target: ";
|
std::string message = "invalid target: ";
|
||||||
message += target;
|
message += target;
|
||||||
Luprex->play_notify_close(Luprex, chid, message.size(), message.c_str());
|
Luprex->play_notify_close(Luprex, chid, message.size(), message.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SSL_CTX* ctx = nullptr;
|
SSL_CTX* ctx = nullptr;
|
||||||
if (cert == "cert") {
|
if (cert == "cert")
|
||||||
|
{
|
||||||
ctx = ClientSecureCTX;
|
ctx = ClientSecureCTX;
|
||||||
}
|
}
|
||||||
else if (cert == "nocert") {
|
else if (cert == "nocert")
|
||||||
|
{
|
||||||
ctx = ClientInsecureCTX;
|
ctx = ClientInsecureCTX;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
std::string message = "invalid cert rule: ";
|
std::string message = "invalid cert rule: ";
|
||||||
message += target;
|
message += target;
|
||||||
Luprex->play_notify_close(Luprex, chid, message.size(), message.c_str());
|
Luprex->play_notify_close(Luprex, chid, message.size(), message.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
FSocket *sock = OpenConnection(Subsys, host, port, err);
|
FSocket *sock = OpenConnection(Subsys, host, port, err);
|
||||||
if (sock == nullptr) {
|
if (sock == nullptr)
|
||||||
|
{
|
||||||
Luprex->play_notify_close(Luprex, chid, err.size(), err.c_str());
|
Luprex->play_notify_close(Luprex, chid, err.size(), err.c_str());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -986,10 +991,12 @@ void FlxSocketsI::RemoveInactiveChannels()
|
|||||||
int n = Channels.Num();
|
int n = Channels.Num();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while ((n > 0) && (Channels[n - 1].State == CHAN_INACTIVE)) {
|
while ((n > 0) && (Channels[n - 1].State == CHAN_INACTIVE))
|
||||||
|
{
|
||||||
n -= 1;
|
n -= 1;
|
||||||
}
|
}
|
||||||
while ((i < n) && (Channels[i].State != CHAN_INACTIVE)) {
|
while ((i < n) && (Channels[i].State != CHAN_INACTIVE))
|
||||||
|
{
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
if (i >= n) break;
|
if (i >= n) break;
|
||||||
@@ -1002,7 +1009,6 @@ void FlxSocketsI::RemoveInactiveChannels()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void FlxSocketsI::HandleSocketInputOutput()
|
void FlxSocketsI::HandleSocketInputOutput()
|
||||||
{
|
{
|
||||||
for (FlxListener& listener : Listeners)
|
for (FlxListener& listener : Listeners)
|
||||||
@@ -1020,6 +1026,7 @@ void FlxSocketsI::HandleSocketInputOutput()
|
|||||||
RemoveInactiveChannels();
|
RemoveInactiveChannels();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FlxSocketsI::Update(FlxLockedWrapper &w)
|
void FlxSocketsI::Update(FlxLockedWrapper &w)
|
||||||
{
|
{
|
||||||
// We retain this pointer only so long as we have the wrapper lock.
|
// We retain this pointer only so long as we have the wrapper lock.
|
||||||
@@ -1029,6 +1036,9 @@ void FlxSocketsI::Update(FlxLockedWrapper &w)
|
|||||||
HandleSocketInputOutput();
|
HandleSocketInputOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
FlxSockets* FlxSockets::Create(FlxLockedWrapper &w)
|
FlxSockets* FlxSockets::Create(FlxLockedWrapper &w)
|
||||||
{
|
{
|
||||||
return new FlxSocketsI(w);
|
return new FlxSocketsI(w);
|
||||||
|
|||||||
Reference in New Issue
Block a user