Tier2: WebSocket system improvements

Naming improvements, additional new comments/documentation and a few assertions. No logic has been changed.
This commit is contained in:
Kawe Mazidjatari 2024-03-31 14:53:14 +02:00
parent e48c9f58ba
commit d7478d3228
2 changed files with 67 additions and 25 deletions

View File

@ -1,8 +1,16 @@
#ifndef TIER2_WEBSOCKETCREATOR_H
#define TIER2_WEBSOCKETCREATOR_H
//===========================================================================//
//
// Purpose: WebSocket implementation
//
//===========================================================================//
#ifndef TIER2_WEBSOCKET_H
#define TIER2_WEBSOCKET_H
#define WEBSOCKET_DEFAULT_BUFFER_SIZE 1024
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
struct ProtoWebSocketRefT;
class CWebSocket
@ -10,17 +18,35 @@ class CWebSocket
public:
enum ConnState_e
{
// The socket has to be created and setup
CS_CREATE = 0,
// The socket connection is established
CS_CONNECTED,
// The socket is listening for data
CS_LISTENING,
// The socket is destroyed and deallocated (if retries are set, the
// code will set the state to 'CS_RETRY' and reattempt to establish
// a connection up to ConnParams_s::maxRetries times
CS_DESTROYED,
// The socket was destroyed and deallocated, and marked for a retry
// attempt
CS_RETRY,
// The socket was destroyed and deallocated, and is marked unavailable.
// the code will remove this connection from the list and no further
// attempts will be made
CS_UNAVAIL
};
//-------------------------------------------------------------------------
// Connection parameters for the system & each individual connection, if
// these are changed, call CWebSocket::UpdateParams() to apply the new
// parameters on the system and each connection
//-------------------------------------------------------------------------
struct ConnParams_s
{
ConnParams_s()
@ -34,15 +60,32 @@ public:
laxSSL = 0;
}
// Total amount of buffer size that could be queued up and sent
int32_t bufSize;
// Total amount of time between each connection attempt
float retryTime;
// Maximum number of retries
// NOTE: the initial attempt is not counted as a retry attempt; if this
// field is set to 5, then the code will perform 1 connection attempt +
// 5 retries before giving up and marking this connection as unavailable
int32_t maxRetries;
// Total amount of time in seconds before the connection is timing out
int32_t timeOut;
// Time interval in seconds for the periodical keepalive pong message
int32_t keepAlive;
// Whether to validate the clients certificate, if this is set, no
// validation is performed
int32_t laxSSL;
};
//-------------------------------------------------------------------------
// Represents an individual socket connection
//-------------------------------------------------------------------------
struct ConnContext_s
{
ConnContext_s(const char* const addr)
@ -57,7 +100,7 @@ public:
}
bool Connect(const double queryTime, const ConnParams_s& params);
bool Status(const double queryTime);
bool Process(const double queryTime);
void SetParams(const ConnParams_s& params);
@ -68,7 +111,7 @@ public:
ProtoWebSocketRefT* webSocket;
ConnState_e state;
int tryCount;
int tryCount; // Number of connection attempts
double lastQueryTime;
CUtlString address;
@ -79,13 +122,13 @@ public:
bool Init(const char* const addressList, const ConnParams_s& params, const char*& initError);
void Shutdown();
bool SetupFromList(const char* const addressList);
bool UpdateAddressList(const char* const addressList);
void UpdateParams(const ConnParams_s& params);
void Update();
void DeleteUnavailable();
void DestroyAll();
void DisconnectAll();
void ReconnectAll();
void ClearAll();
@ -98,4 +141,4 @@ private:
CUtlVector<ConnContext_s> m_addressList;
};
#endif // TIER2_WEBSOCKETCREATOR_H
#endif // TIER2_WEBSOCKET_H

View File

@ -24,16 +24,18 @@ CWebSocket::CWebSocket()
//-----------------------------------------------------------------------------
bool CWebSocket::Init(const char* const addressList, const ConnParams_s& params, const char*& initError)
{
Assert(addressList);
if (!NetConnStatus('open', 0, NULL, 0))
{
initError = "Network connection module not initialized";
return false;
}
if (!SetupFromList(addressList))
if (!UpdateAddressList(addressList))
{
initError = (*addressList)
? "Failed to parse address list"
? "Address list is invalid"
: "Address list is empty";
return false;
@ -55,10 +57,12 @@ void CWebSocket::Shutdown()
}
//-----------------------------------------------------------------------------
// Purpose: setup connection list, returns false if connection list is empty
// Purpose: adds comma separated addresses to connection list, returns false if
// connection list is empty
//-----------------------------------------------------------------------------
bool CWebSocket::SetupFromList(const char* const addressList)
bool CWebSocket::UpdateAddressList(const char* const addressList)
{
Assert(addressList);
const CUtlStringList addresses(addressList, ",");
FOR_EACH_VEC(addresses, i)
@ -107,7 +111,7 @@ void CWebSocket::Update()
if (conn.state == CS_CONNECTED || conn.state == CS_LISTENING)
{
conn.Status(queryTime);
conn.Process(queryTime);
continue;
}
@ -138,20 +142,18 @@ void CWebSocket::DeleteUnavailable()
FOR_EACH_VEC_BACK(m_addressList, i)
{
if (m_addressList[i].state == CS_UNAVAIL)
{
m_addressList.FastRemove(i);
}
}
}
//-----------------------------------------------------------------------------
// Purpose: destroy all connections
// Purpose: disconnect all connections
//-----------------------------------------------------------------------------
void CWebSocket::DestroyAll()
void CWebSocket::DisconnectAll()
{
for (ConnContext_s& conn : m_addressList)
{
conn.Destroy();
conn.Disconnect();
}
}
@ -171,7 +173,7 @@ void CWebSocket::ReconnectAll()
//-----------------------------------------------------------------------------
void CWebSocket::ClearAll()
{
DestroyAll();
DisconnectAll();
m_addressList.Purge();
}
@ -180,6 +182,9 @@ void CWebSocket::ClearAll()
//-----------------------------------------------------------------------------
void CWebSocket::SendData(const char* const dataBuf, const int32_t dataSize)
{
Assert(dataBuf);
Assert(dataSize);
if (!IsInitialized())
return;
@ -189,9 +194,7 @@ void CWebSocket::SendData(const char* const dataBuf, const int32_t dataSize)
continue;
if (ProtoWebSocketSend(conn.webSocket, dataBuf, dataSize) < 0)
{
conn.Destroy(); // Reattempt the connection for this socket
}
}
}
@ -244,7 +247,7 @@ bool CWebSocket::ConnContext_s::Connect(const double queryTime, const ConnParams
//-----------------------------------------------------------------------------
// Purpose: check the connection status and destroy if not connected (-1)
//-----------------------------------------------------------------------------
bool CWebSocket::ConnContext_s::Status(const double queryTime)
bool CWebSocket::ConnContext_s::Process(const double queryTime)
{
const int32_t status = ProtoWebSocketStatus(webSocket, 'stat', NULL, 0);
@ -275,14 +278,10 @@ void CWebSocket::ConnContext_s::SetParams(const ConnParams_s& params)
Assert(webSocket);
if (params.timeOut > 0)
{
ProtoWebSocketControl(webSocket, 'time', params.timeOut, 0, NULL);
}
if (params.keepAlive > 0)
{
ProtoWebSocketControl(webSocket, 'keep', params.keepAlive, 0, NULL);
}
ProtoWebSocketControl(webSocket, 'ncrt', params.laxSSL, 0, NULL);
ProtoWebSocketUpdate(webSocket);