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/RemoteCommandHelpers.h

308 lines
8.5 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.
// Description : Remote command system helper classes
#ifndef CRYINCLUDE_CRYSYSTEM_REMOTECOMMANDHELPERS_H
#define CRYINCLUDE_CRYSYSTEM_REMOTECOMMANDHELPERS_H
#pragma once
//------------------------------------------------------------------------
#include "IRemoteCommand.h"
struct IServiceNetworkMessage;
//------------------------------------------------------------------------
// Stream reader for service network message
// Implements automatic byte swapping
class CDataReadStreamFormMessage
: public IDataReadStream
{
private:
const IServiceNetworkMessage* m_pMessage;
const char* m_pData;
uint32 m_offset;
uint32 m_size;
private:
template<typename T>
ILINE void ReadType(void* pData)
{
CRY_ASSERT(m_offset + sizeof(T) < m_size);
const T& readPos = *reinterpret_cast<const T*>(m_pData + m_offset);
*reinterpret_cast<T*>(pData) = readPos;
SwapEndian(*reinterpret_cast<T*>(pData));
m_offset += sizeof(T);
}
public:
CDataReadStreamFormMessage(const IServiceNetworkMessage* message);
virtual ~CDataReadStreamFormMessage();
const uint32 GetOffset() const
{
return m_offset;
}
void SetPosition(uint32 offset)
{
m_offset = offset;
}
public:
// IDataReadStream interface
virtual void Delete();
virtual void Skip(const uint32 size);
virtual void Read(void* pData, const uint32 size);
virtual void Read8(void* pData);
virtual void Read4(void* pData);
virtual void Read2(void* pData);
virtual void Read1(void* pData);
virtual const void* GetPointer();
};
//------------------------------------------------------------------------
// Stream writer that writes into the service network message
class CDataWriteStreamToMessage
: public IDataWriteStream
{
private:
IServiceNetworkMessage* m_pMessage;
char* m_pData;
uint32 m_offset;
uint32 m_size;
private:
template<typename T>
ILINE void WriteType(const void* pData)
{
CRY_ASSERT(m_offset + sizeof(T) < m_size);
T& writePos = *reinterpret_cast<T*>(m_pData + m_offset);
writePos = *reinterpret_cast<const T*>(pData);
SwapEndian(writePos);
m_offset += sizeof(T);
}
public:
CDataWriteStreamToMessage(IServiceNetworkMessage* pMessage);
virtual ~CDataWriteStreamToMessage();
// IDataWriteStream interface implementation
virtual void Delete();
virtual const uint32 GetSize() const;
virtual struct IServiceNetworkMessage* BuildMessage() const;
virtual void CopyToBuffer(void* pData) const;
virtual void Write(const void* pData, const uint32 size);
virtual void Write8(const void* pData);
virtual void Write4(const void* pData);
virtual void Write2(const void* pData);
virtual void Write1(const void* pData);
};
//------------------------------------------------------------------------
/// Stream reader reading from owner memory buffer
class CDataReadStreamMemoryBuffer
: public IDataReadStream
{
private:
const uint32 m_size;
uint8* m_pData;
uint32 m_offset;
public:
// memory is copied!
CDataReadStreamMemoryBuffer(const void* pData, const uint32 size);
virtual ~CDataReadStreamMemoryBuffer();
virtual void Delete();
virtual void Skip(const uint32 size);
virtual void Read8(void* pData);
virtual void Read4(void* pData);
virtual void Read2(void* pData);
virtual void Read1(void* pData);
virtual const void* GetPointer();
virtual void Read(void* pData, const uint32 size);
};
//------------------------------------------------------------------------
// Stream writer that writes into the internal memory buffer
class CDataWriteStreamBuffer
: public IDataWriteStream
{
static const uint32 kStaticPartitionSize = 4096;
private:
// Default (preallocated) partition
char m_defaultPartition[ kStaticPartitionSize ];
// Allocated dynamic partitions
std::vector<char*> m_pPartitions;
// Size of the dynamic message partitions
std::vector<uint32> m_partitionSizes;
// Pointer to current writing position in the current partition
char* m_pCurrentPointer;
// Space left in current partition
uint32 m_leftInPartition;
// Total message size so far
uint32 m_size;
private:
// Directly write typed data into the stream
template<typename T>
ILINE void WriteType(const void* pData)
{
// try to use the faster path if we are not crossing the partition boundary
if (m_leftInPartition >= sizeof(T))
{
// faster case
T& writePos = *reinterpret_cast<T*>(m_pCurrentPointer);
writePos = *reinterpret_cast<const T*>(pData);
SwapEndian(writePos);
m_pCurrentPointer += sizeof(T);
m_leftInPartition -= sizeof(T);
m_size += sizeof(T);
}
else
{
// slower case (more generic)
T tempVal(*reinterpret_cast<const T*>(pData));
SwapEndian(tempVal);
Write(&tempVal, sizeof(tempVal));
}
}
public:
CDataWriteStreamBuffer();
virtual ~CDataWriteStreamBuffer();
// IDataWriteStream interface implementation
virtual void Delete();
virtual const uint32 GetSize() const;
virtual IServiceNetworkMessage* BuildMessage() const;
virtual void CopyToBuffer(void* pData) const;
virtual void Write(const void* pData, const uint32 size);
virtual void Write8(const void* pData);
virtual void Write4(const void* pData);
virtual void Write2(const void* pData);
virtual void Write1(const void* pData);
};
//-----------------------------------------------------------------------------
// Packet header
struct PackedHeader
{
// Estimation (or better yet, exact value) of how much data this header will take when written.
// Please make sure that actual size after serialization is not bigger than this value.
static const uint32 kSerializationSize = sizeof(uint8) + sizeof(uint32) + sizeof(uint32);
// Magic value that identifies command messages vs raw messages
static const uint32 kMagic = 0xABBAF00D;
// Command type
// Keep the values unchanged as this may break the protocol
enum ECommand
{
// Server class list mapping
eCommand_ClassList = 0,
// Command data
eCommand_Command = 1,
// Disconnect signal
eCommand_Disconnect = 2,
// ACK packet
eCommand_ACK = 3,
};
uint32 magic;
uint8 msgType;
uint32 count;
// serialization operator
template< class T >
friend T& operator<<(T& stream, PackedHeader& header)
{
stream << header.magic;
stream << header.msgType;
stream << header.count;
return stream;
}
};
// Header sent with every command
struct CommandHeader
{
uint32 commandId;
uint32 classId;
uint32 size;
CommandHeader()
: commandId(0)
, classId(0)
, size(0)
{}
// serialization operator
template< class T >
friend T& operator<<(T& stream, CommandHeader& header)
{
stream << header.commandId;
stream << header.classId;
stream << header.size;
return stream;
}
};
// General Response/ACK header
struct ResponseHeader
{
uint32 magic;
uint8 msgType;
uint32 lastCommandReceived;
uint32 lastCommandExecuted;
ResponseHeader()
: lastCommandReceived(0)
, lastCommandExecuted(0)
, msgType(PackedHeader::eCommand_ACK)
{}
// serialization operator
template< class T >
friend T& operator<<(T& stream, ResponseHeader& header)
{
stream << header.magic;
stream << header.msgType;
stream << header.lastCommandReceived;
stream << header.lastCommandExecuted;
return stream;
}
};
//-----------------------------------------------------------------------------
#endif // CRYINCLUDE_CRYSYSTEM_REMOTECOMMANDHELPERS_H