You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/CrySystem/NotificationNetwork.h

294 lines
8.6 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_CRYSYSTEM_NOTIFICATIONNETWORK_H
#define CRYINCLUDE_CRYSYSTEM_NOTIFICATIONNETWORK_H
#pragma once
#include <IConsole.h>
#include <INotificationNetwork.h>
#include <CryThread.h>
#include <AzCore/Socket/AzSocket_fwd.h>
class CNotificationNetwork;
namespace NotificationNetwork {
// Constants
static const uint32 NN_PACKET_HEADER_LENGTH = 2 * sizeof(uint32) + NN_CHANNEL_NAME_LENGTH_MAX;
static const uint32 NN_PACKET_HEADER_OFFSET_MESSAGE = 0;
static const uint32 NN_PACKET_HEADER_OFFSET_DATA_LENGTH = sizeof(uint32);
static const uint32 NN_PACKET_HEADER_OFFSET_CHANNEL = sizeof(uint32) + sizeof(uint32);
static const char* NN_THREAD_NAME = "NotificationNetwork";
enum EMessage
{
eMessage_DataTransfer = 0xbada2217,
eMessage_ChannelRegister = 0xab4eda30,
eMessage_ChannelUnregister = 0xfa4e3423,
};
// Classes
struct CChannel
{
public:
static bool IsNameValid(const char* name);
public:
CChannel();
CChannel(const char* name);
~CChannel();
public:
void WriteToPacketHeader(void* pPacket) const;
void ReadFromPacketHeader(void* pPacket);
public:
bool operator ==(const CChannel& channel) const;
bool operator !=(const CChannel& channel) const;
private:
char m_name[NN_CHANNEL_NAME_LENGTH_MAX];
};
// TEMP
struct SBuffer
{
uint8* pData;
uint32 length;
CChannel channel;
};
class CListeners
{
public:
CListeners();
~CListeners();
public:
size_t Count() { return m_listeners.size(); }
size_t Count(const CChannel& channel);
CChannel& Channel(size_t index) { return m_listeners[index].second; }
CChannel* Channel(INotificationNetworkListener* pListener);
bool Bind(const CChannel& channel, INotificationNetworkListener* pListener);
bool Remove(INotificationNetworkListener* pListener);
void NotificationPush(const SBuffer& buffer);
void NotificationsProcess();
private:
std::vector< std::pair<INotificationNetworkListener*, CChannel> > m_listeners;
std::queue<SBuffer> m_notifications[2];
std::queue<SBuffer>* m_pNotificationWrite;
std::queue<SBuffer>* m_pNotificationRead;
CryCriticalSection m_notificationCriticalSection;
};
class CConnectionBase
{
public:
CConnectionBase(CNotificationNetwork* pNotificationNetwork);
virtual ~CConnectionBase();
public:
AZSOCKET CreateSocket();
bool Connect(const char* address, uint16 port);
AZSOCKET GetSocket() { return m_socket; }
bool Validate();
bool SendNotification(const CChannel& channel, const void* pBuffer, size_t length);
bool Receive(CListeners& listeners);
bool GetIsConnectedFlag();
bool GetIsFailedToConnectFlag() const;
protected:
CNotificationNetwork* GetNotificationNetwork() { return m_pNotificationNetwork; }
void SetAddress(const char* address, uint16 port);
void SetSocket(AZSOCKET sock) { m_socket = sock; }
bool Send(const void* pBuffer, size_t length);
bool SendMessage(EMessage eMessage, const CChannel& channel, uint32 data);
bool Select_Internal();
void CloseSocket_Internal();
virtual bool OnConnect([[maybe_unused]] bool bConnectionResult) { return true; }
virtual bool OnDisconnect() {return true; }
virtual bool OnMessage([[maybe_unused]] EMessage eMessage, [[maybe_unused]] const CChannel& channel) { return false; }
private:
bool ReceiveMessage(CListeners& listeners);
bool ReceiveNotification(CListeners& listeners);
protected:
CNotificationNetwork* m_pNotificationNetwork;
char m_address[16];
uint16 m_port;
AZSOCKET m_socket;
uint8 m_bufferHeader[NN_PACKET_HEADER_LENGTH];
SBuffer m_buffer;
uint32 m_dataLeft;
volatile bool m_boIsConnected;
volatile bool m_boIsFailedToConnect;
};
class CClient
: public CConnectionBase
, public INotificationNetworkClient
{
public:
typedef std::vector<INotificationNetworkConnectionCallback*> TDNotificationNetworkConnectionCallbacks;
static CClient* Create(CNotificationNetwork* pNotificationNetwork, const char* address, uint16 port);
static CClient* Create(CNotificationNetwork* pNotificationNetwork);
private:
CClient(CNotificationNetwork* pNotificationNetwork);
~CClient();
public:
bool Receive() { return CConnectionBase::Receive(m_listeners); }
void Update();
// CConnectionBase
public:
virtual bool OnConnect(bool bConnectionResult);
virtual bool OnDisconnect();
virtual bool OnMessage(EMessage eMessage, const CChannel& channel);
// INotificationNetworkClient
public:
bool Connect(const char* address, uint16 port);
void Release() { delete this; }
virtual bool ListenerBind(const char* channelName, INotificationNetworkListener* pListener);
virtual bool ListenerRemove(INotificationNetworkListener* pListener);
virtual bool Send(const char* channelName, const void* pBuffer, size_t length);
virtual bool IsConnected() {return CConnectionBase::GetIsConnectedFlag(); }
virtual bool IsFailedToConnect() const{return CConnectionBase::GetIsFailedToConnectFlag(); }
virtual bool RegisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback);
virtual bool UnregisterCallbackListener(INotificationNetworkConnectionCallback* pConnectionCallback);
private:
CListeners m_listeners;
TDNotificationNetworkConnectionCallbacks m_cNotificationNetworkConnectionCallbacks;
CryCriticalSection m_stConnectionCallbacksLock;
};
} // namespace NotificationNetwork
class CNotificationNetwork
: public INotificationNetwork
{
private:
class CConnection
: public NotificationNetwork::CConnectionBase
{
public:
CConnection(CNotificationNetwork* pNotificationNetwork, AZSOCKET sock);
virtual ~CConnection();
public:
bool IsListening(const NotificationNetwork::CChannel& channel);
// CConnectionBase
protected:
virtual bool OnMessage(NotificationNetwork::EMessage eMessage, const NotificationNetwork::CChannel& channel);
private:
std::vector<NotificationNetwork::CChannel> m_listeningChannels;
};
class CThread
: public CryThread<CThread>
{
public:
CThread();
~CThread();
public:
bool Begin(CNotificationNetwork* pNotificationNetwork);
void End();
// CryRunnable
public:
virtual void Run();
private:
CNotificationNetwork* m_pNotificationNetwork;
bool m_bRun;
} m_thread;
public:
static CNotificationNetwork* Create();
public:
CNotificationNetwork();
~CNotificationNetwork();
public:
void ReleaseClients(NotificationNetwork::CClient* pClient);
private:
void ProcessSockets();
// INotificationNetwork
public:
virtual void Release() { delete this; }
virtual INotificationNetworkClient* CreateClient();
virtual INotificationNetworkClient* Connect(const char* address, uint16 port);
virtual size_t GetConnectionCount(const char* channelName);
virtual void Update();
virtual bool ListenerBind(const char* channelName, INotificationNetworkListener* pListener);
virtual bool ListenerRemove(INotificationNetworkListener* pListener);
virtual uint32 Send(const char* channelName, const void* pBuffer, size_t length);
private:
AZSOCKET m_socket;
std::vector<CConnection*> m_connections;
std::vector<NotificationNetwork::CClient*> m_clients;
NotificationNetwork::CListeners m_listeners;
CryCriticalSection m_clientsCriticalSection;
};
#endif // CRYINCLUDE_CRYSYSTEM_NOTIFICATIONNETWORK_H