205 lines
5.6 KiB
C++
205 lines
5.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "XmppStrophe/StropheConnection.h"
|
|
#include "XmppStrophe/StropheContext.h"
|
|
#include "XmppStrophe/StropheStanza.h"
|
|
#include "XmppStrophe/StropheError.h"
|
|
#include "XmppStrophe/XmppConnectionStrophe.h"
|
|
#include "XmppLog.h"
|
|
#include "HAL/PlatformProcess.h"
|
|
|
|
#if WITH_XMPP_STROPHE
|
|
|
|
THIRD_PARTY_INCLUDES_START
|
|
#include "strophe.h"
|
|
THIRD_PARTY_INCLUDES_END
|
|
|
|
int StropheStanzaEventHandler(xmpp_conn_t* const UnusedPtr, xmpp_stanza_t* const EventStanza, void* const VoidConnectionPtr)
|
|
{
|
|
check(VoidConnectionPtr != nullptr);
|
|
|
|
const FStropheStanza IncomingStanza(EventStanza);
|
|
|
|
// Ignore session stanza (bug in libstrophe that we see get this at all)
|
|
static const FString LoginSessionStanza(TEXT("_xmpp_session1"));
|
|
if (IncomingStanza.GetId() != LoginSessionStanza)
|
|
{
|
|
// We want to forward our stanza to our connection and out to our handlers
|
|
FXmppConnectionStrophe* const ConnectionPtr = static_cast<FXmppConnectionStrophe* const>(VoidConnectionPtr);
|
|
ConnectionPtr->ReceiveStanza(IncomingStanza);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
void StropheConnectionEventHandler(xmpp_conn_t* const UnusedPtr,
|
|
const xmpp_conn_event_t ConnectionEvent,
|
|
const int ErrorNo,
|
|
xmpp_stream_error_t* const StreamError,
|
|
void* const VoidConnectionPtr)
|
|
{
|
|
check(VoidConnectionPtr != nullptr);
|
|
FXmppConnectionStrophe* const ConnectionPtr = static_cast<FXmppConnectionStrophe* const>(VoidConnectionPtr);
|
|
|
|
EStropheConnectionEvent Event = EStropheConnectionEvent::Fail;
|
|
switch (ConnectionEvent)
|
|
{
|
|
case XMPP_CONN_CONNECT:
|
|
Event = EStropheConnectionEvent::Connect;
|
|
break;
|
|
case XMPP_CONN_RAW_CONNECT:
|
|
Event = EStropheConnectionEvent::RawConnect;
|
|
break;
|
|
case XMPP_CONN_DISCONNECT:
|
|
Event = EStropheConnectionEvent::Disconnect;
|
|
break;
|
|
case XMPP_CONN_FAIL:
|
|
Event = EStropheConnectionEvent::Fail;
|
|
break;
|
|
}
|
|
|
|
ConnectionPtr->ReceiveConnectionStateChange(Event);
|
|
|
|
if (StreamError != nullptr)
|
|
{
|
|
const FStropheError Error(*StreamError, ErrorNo);
|
|
ConnectionPtr->ReceiveConnectionError(Error, Event);
|
|
}
|
|
}
|
|
|
|
FStropheConnection::FStropheConnection(FStropheContext& InContext)
|
|
: Context(InContext)
|
|
, XmppConnectionPtr(nullptr)
|
|
, ConnectionTimeoutSeconds(30)
|
|
, ConnectionPingIntervalSeconds(60)
|
|
{
|
|
XmppConnectionPtr = xmpp_conn_new(Context.GetContextPtr());
|
|
check(XmppConnectionPtr);
|
|
|
|
// Set our default timeout
|
|
xmpp_conn_set_keepalive(XmppConnectionPtr, ConnectionTimeoutSeconds, ConnectionPingIntervalSeconds);
|
|
}
|
|
|
|
FStropheConnection::~FStropheConnection()
|
|
{
|
|
check(XmppConnectionPtr != nullptr);
|
|
|
|
xmpp_conn_release(XmppConnectionPtr);
|
|
XmppConnectionPtr = nullptr;
|
|
}
|
|
|
|
int32 FStropheConnection::GetTimeout() const
|
|
{
|
|
return ConnectionTimeoutSeconds;
|
|
}
|
|
|
|
int32 FStropheConnection::GetPingInterval() const
|
|
{
|
|
return ConnectionPingIntervalSeconds;
|
|
}
|
|
|
|
void FStropheConnection::SetKeepAlive(int32 Timeout, int32 PingInterval)
|
|
{
|
|
ConnectionTimeoutSeconds = Timeout;
|
|
ConnectionPingIntervalSeconds = PingInterval;
|
|
|
|
xmpp_conn_set_keepalive(XmppConnectionPtr, ConnectionTimeoutSeconds, ConnectionPingIntervalSeconds);
|
|
}
|
|
|
|
FString FStropheConnection::GetUserId() const
|
|
{
|
|
return FString(UTF8_TO_TCHAR(xmpp_conn_get_jid(XmppConnectionPtr)));
|
|
}
|
|
|
|
void FStropheConnection::SetUserId(const FXmppUserJid& NewUserJid)
|
|
{
|
|
SetUserId(NewUserJid.GetFullPath());
|
|
}
|
|
|
|
void FStropheConnection::SetUserId(const FString& NewUserId)
|
|
{
|
|
xmpp_conn_set_jid(XmppConnectionPtr, TCHAR_TO_UTF8(*NewUserId));
|
|
}
|
|
|
|
FString FStropheConnection::GetPassword() const
|
|
{
|
|
return FString(UTF8_TO_TCHAR(xmpp_conn_get_pass(XmppConnectionPtr)));
|
|
}
|
|
|
|
void FStropheConnection::SetPassword(const FString& NewPassword)
|
|
{
|
|
xmpp_conn_set_pass(XmppConnectionPtr, TCHAR_TO_UTF8(*NewPassword));
|
|
}
|
|
|
|
bool FStropheConnection::Connect(const FString& Domain, uint16 Port, FXmppConnectionStrophe& ConnectionManager)
|
|
{
|
|
bool bSuccess = true;
|
|
|
|
if (xmpp_connect_client(XmppConnectionPtr, TCHAR_TO_UTF8(*Domain), Port, StropheConnectionEventHandler, &ConnectionManager) != XMPP_EOK)
|
|
{
|
|
UE_LOG(LogXmpp, Error, TEXT("Failed to connect to host %s:%d"), *Domain, Port);
|
|
bSuccess = false;
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
void FStropheConnection::Disconnect()
|
|
{
|
|
xmpp_disconnect(XmppConnectionPtr);
|
|
}
|
|
|
|
bool FStropheConnection::SendStanza(const FStropheStanza& Stanza)
|
|
{
|
|
if (GetConnectionState() != EStropheConnectionState::Connected)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
xmpp_send(XmppConnectionPtr, Stanza.GetStanzaPtr());
|
|
return true;
|
|
}
|
|
|
|
void FStropheConnection::XmppThreadTick()
|
|
{
|
|
constexpr const int32 DefaultTimeoutMs = 5;
|
|
constexpr const float DefaultTimeBetweenPollsSec = 0.005f;
|
|
|
|
// Will process any data queued for send/receive and return. Will wait up to DefaultTimeoutMs if the socket is blocked.
|
|
xmpp_run_once(Context.GetContextPtr(), DefaultTimeoutMs);
|
|
|
|
// Since xmpp_run_once will not wait if the socket is not blocked, add a sleep between polls to avoid monopolizing the CPU
|
|
FPlatformProcess::Sleep(DefaultTimeBetweenPollsSec);
|
|
}
|
|
|
|
void FStropheConnection::RegisterStropheHandler(FXmppConnectionStrophe& ConnectionManager)
|
|
{
|
|
xmpp_handler_add(XmppConnectionPtr, StropheStanzaEventHandler, nullptr, nullptr, nullptr, &ConnectionManager);
|
|
}
|
|
|
|
void FStropheConnection::RemoveStropheHandler()
|
|
{
|
|
xmpp_handler_delete(XmppConnectionPtr, StropheStanzaEventHandler);
|
|
}
|
|
|
|
EStropheConnectionState FStropheConnection::GetConnectionState() const
|
|
{
|
|
if (xmpp_conn_is_connected(XmppConnectionPtr) != 0)
|
|
{
|
|
return EStropheConnectionState::Connected;
|
|
}
|
|
else if (xmpp_conn_is_disconnected(XmppConnectionPtr) != 0)
|
|
{
|
|
return EStropheConnectionState::Disconnected;
|
|
}
|
|
else if (xmpp_conn_is_connecting(XmppConnectionPtr) != 0)
|
|
{
|
|
return EStropheConnectionState::Connecting;
|
|
}
|
|
|
|
checkf(false, TEXT("Missing libstrophe xmpp connection state"));
|
|
return EStropheConnectionState::Unknown;
|
|
}
|
|
|
|
#endif
|