📄 netmessage.cpp
字号:
// NetMsg.cpp: implementation of the CNetMsg class.
//
// Written by Marat Bedretdinov (maratb@hotmail.com)
// Copyright (c) 2000.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
//
// If the source code in this file is used in any commercial application
// then acknowledgement must be made to the author of this file
// and permissions to use this file are requested from the author
//
// (in whatever form you wish).// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
// It's free - so you get what you pay for.//
#include "stdafx.h"
#include "NetMessage.h"
#include "NetStream.h"
#include "NetConnection.h"
#ifdef _WIN32
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNetObject::CNetObject():
m_pData(0),
m_nSeekRead(0),
m_nSeekWrite(0)
{
}
CNetObject::~CNetObject()
{
// the m_pData is released with the object
EmptyBuffer();
}
void CNetObject::EmptyBuffer()
{
m_nSeekRead = 0;
m_nSeekWrite = 0;
if (m_pData) {
delete (char*)m_pData;
m_pData = 0;
}
}
CNetObject& CNetObject::operator=(const CNetObject& obj)
{
EmptyBuffer();
// if the buffer is empty just copy the member variables
if (!obj.m_pData)
return (*this).operator=(obj);
// reallocate the buffer
AllocateData(obj.GetSize_Write());
// and copy the context
memcpy(m_pData, obj.m_pData, obj.GetSize_Write());
m_nSeekRead = obj.m_nSeekRead;
m_nSeekWrite = obj.m_nSeekWrite;
// copy the member variables
return operator=(obj);
}
bool CNetObject::operator==(const CNetObject& obj)
{
return operator==(obj);
}
void* CNetObject::AllocateData(const ulong nSz /* = 0*/)
{
// delete the data
EmptyBuffer();
// allocate it, using nSz, or GetSize() if nSz == 0
if (nSz)
m_pData = malloc(nSz);
else
m_pData = malloc(GetSize_Write());
// return it
return m_pData;
}
bool CNetObject::IsBufferEmpty() const
{
if (!m_pData) return true;
return false;
}
bool CNetObject::CheckReadBound(ulong nSz) const
{
if (m_nSeekRead + nSz <= GetSize_Read()) return true;
return false;
}
bool CNetObject::CheckWriteBound(ulong nSz) const
{
if (m_nSeekWrite + nSz <= GetSize_Write()) return true;
return false;
}
bool CNetObject::Get(ulong& Out)
{
if (!CheckReadBound(GetSize_ulong())) return false;
memcpy(&Out, (char*)m_pData + m_nSeekRead, GetSize_ulong());
Out = ntohl(Out);
m_nSeekRead += GetSize_ulong();
return true;
}
bool CNetObject::Get(ushort& Out)
{
if (!CheckReadBound(GetSize_ushort())) return false;
memcpy(&Out, (char*)m_pData + m_nSeekRead, GetSize_ushort());
Out = ntohs(Out);
m_nSeekRead += GetSize_ushort();
return true;
}
bool CNetObject::Get(bool& Out)
{
if (!CheckReadBound(GetSize_bool())) return false;
memcpy(&Out, (char*)m_pData + m_nSeekRead, GetSize_bool());
m_nSeekRead += GetSize_bool();
return true;
}
bool CNetObject::Get(string& Out, ulong nSz)
{
if (!CheckReadBound(nSz)) return false;
// the buffer does not have a NULL character
char* pBuff = new char[nSz+1];
memcpy(pBuff, (char*)m_pData + m_nSeekRead, nSz);
// so add it
pBuff[nSz] = NULL;
Out = pBuff;
delete pBuff;
m_nSeekRead += nSz;
return true;
}
bool CNetObject::Get(char* Out, ulong nSz)
{
if (!CheckReadBound(nSz)) return false;
// the buffer does not have a NULL character
char* pBuff = new char[nSz+1];
memcpy(pBuff, (char*)m_pData + m_nSeekRead, nSz);
// so add it
// pBuff[nSz] = NULL;
memcpy(Out, pBuff, nSz);
delete pBuff;
m_nSeekRead += nSz;
return true;
}
bool CNetObject::Put(const ulong In)
{
if (!CheckWriteBound(GetSize_ulong())) return false;
ulong nul = htonl(In);
memcpy((char*)m_pData + m_nSeekWrite, &nul, GetSize_ulong());
m_nSeekWrite += GetSize_ulong();
return true;
}
bool CNetObject::Put(const ushort In)
{
if (!CheckWriteBound(GetSize_ushort())) return false;
ushort nus = htons(In);
memcpy((char*)m_pData + m_nSeekWrite, &nus, GetSize_ushort());
m_nSeekWrite += GetSize_ushort();
return true;
}
bool CNetObject::Put(const bool In)
{
if (!CheckWriteBound(GetSize_bool())) return false;
memcpy((char*)m_pData + m_nSeekWrite, &In, GetSize_bool());
m_nSeekWrite += GetSize_bool();
return true;
}
bool CNetObject::Put(const string& In, ulong nSz)
{
if (!CheckWriteBound(nSz)) return false;
// the NULL character is excluded
memcpy((char*)m_pData + m_nSeekWrite, In.c_str(), nSz);
m_nSeekWrite += nSz;
return true;
}
bool CNetObject::Put(const char* In, ulong nSz)
{
if (!CheckWriteBound(nSz)) return false;
// the NULL character is excluded
memcpy((char*)m_pData + m_nSeekWrite, In, nSz);
m_nSeekWrite += nSz;
return true;
}
////////////////////////// CNetMsgHdr ////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNetMsgHdr::CNetMsgHdr():
CNetObject()
{
m_data.m_strSignature = NET_SIGNATURE;
m_data.m_nHost = 0;
m_data.m_nRemote = 0;
m_data.m_nClassId = 0;
m_data.m_nMsgSize = 0;
}
CNetMsgHdr::CNetMsgHdr(const CNetMsgHdr& obj):
CNetObject()
{
operator=(obj);
}
CNetObject& CNetMsgHdr::operator=(const CNetObject& obj)
{
const CNetMsgHdr& msg = dynamic_cast<const CNetMsgHdr&>(obj);
// copies the MSG structure
m_data.m_strSignature = msg.m_data.m_strSignature;
m_data.m_nHost = msg.m_data.m_nHost;
m_data.m_nRemote = msg.m_data.m_nRemote;
m_data.m_nClassId = msg.m_data.m_nClassId;
m_data.m_nMsgSize = msg.m_data.m_nMsgSize;
return *this;
}
bool CNetMsgHdr::operator==(const CNetObject& obj)
{
const CNetMsgHdr& msg = dynamic_cast<const CNetMsgHdr&>(obj);
// compares the MSG structure
if ( !m_data.m_strSignature.compare(msg.m_data.m_strSignature) &&
m_data.m_nHost == msg.m_data.m_nHost &&
m_data.m_nRemote == msg.m_data.m_nRemote &&
m_data.m_nClassId == msg.m_data.m_nClassId &&
m_data.m_nMsgSize == msg.m_data.m_nMsgSize)
return true;
return false;
}
CNetMsgHdr::~CNetMsgHdr()
{
}
void CNetMsgHdr::Read()
{
if
(
!Get(m_data.m_strSignature, SIGNATURE_SIZE) ||
!Get(m_data.m_nHost) ||
!Get(m_data.m_nRemote) ||
!Get(m_data.m_nClassId) ||
!Get(m_data.m_nMsgSize)
)
// if something went wrong
throw CNetMsgException(ERR_NET_MSG_DATA_CORRUPTED, "void CNetMsgHdr::Read()");
// check the signature
if (m_data.m_strSignature.compare(NET_SIGNATURE))
throw CNetMsgException(ERR_NET_WRONG_SIGNATURE, "void CNetMsgHdr::Read()");
}
void CNetMsgHdr::Write()
{
if
(
!Put(m_data.m_strSignature, SIGNATURE_SIZE) ||
!Put(m_data.m_nHost) ||
!Put(m_data.m_nRemote) ||
!Put(m_data.m_nClassId) ||
!Put(m_data.m_nMsgSize)
)
// if something went wrong
throw CNetMsgException(ERR_NET_MSG_DATA_CORRUPTED, "void CNetMsgHdr::Write()");
}
void CNetMsgHdr::SetHost(const char* strAddr)
{
ulong nAddr = g_addr_stu(strAddr);
m_data.m_nHost = nAddr;
}
void CNetMsgHdr::SetRemote(const char* strAddr)
{
ulong nAddr = g_addr_stu(strAddr);
m_data.m_nRemote = nAddr;
}
void CNetMsgHdr::SetHost(ulong nAddr)
{
m_data.m_nHost = nAddr;
}
void CNetMsgHdr::SetRemote(ulong nAddr)
{
m_data.m_nRemote = nAddr;
}
const string CNetMsgHdr::GetHost() const
{
string strAddr = g_addr_uts(m_data.m_nHost);
return strAddr;
}
const string CNetMsgHdr::GetRemote() const
{
string strAddr = g_addr_uts(m_data.m_nRemote);
return strAddr;
}
void CNetMsgHdr::Dump(ostream& os)
{
// save old seek position
ulong nSavPos = m_nSeekRead;
ulong data = 0;
os << endl << "Start Dump for CNetMsgHdr:" << endl << endl;
os << "Dump for the buffer:" << endl << endl;
if (Get(data))
os << "CNetMsgHdr::m_data::m_strSignature = " << data << ";" << endl;
if (Get(data))
os << "CNetMsgHdr::m_data::m_nHost = " << data << ";" << endl;
if (Get(data))
os << "CNetMsgHdr::m_data::m_nRemote = " << data << ";" << endl;
if (Get(data))
os << "CNetMsgHdr::m_data::m_nClassId = " << data << ";" << endl;
if (Get(data))
os << "CNetMsgHdr::m_data::m_nMsgSize = " << data << ";" << endl;
// restore old seek position
m_nSeekRead = nSavPos;
os << "Dump for the member variables:" << endl << endl;
os << "CNetMsgHdr::m_data::m_strSignature = " << m_data.m_strSignature.c_str() << ";" << endl;
os << "CNetMsgHdr::m_data::m_nHost = " << m_data.m_nHost << ";" << endl;
os << "CNetMsgHdr::m_data::m_nRemote = " << m_data.m_nRemote << ";" << endl;
os << "CNetMsgHdr::m_data::m_nClassId = " << m_data.m_nClassId << ";" << endl;
os << "CNetMsgHdr::m_data::m_nMsgSize = " << m_data.m_nMsgSize << ";" << endl;
os << endl << "End Dump for CNetMsgHdr:" << endl << endl;
}
//////////////////////////// CNetMsg /////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNetMsg::CNetMsg()
{
}
CNetMsg::CNetMsg(const CNetMsg& obj):
CNetObject()
{
operator=(obj);
}
CNetObject& CNetMsg::operator=(const CNetObject& obj)
{
// CNetObject::operator=(obj);
// copies the CNetMsgHdr data and the data buffer
const CNetMsg& msg = dynamic_cast<const CNetMsg&>(obj);
m_header = msg.m_header;
// return operator=(msg);
return *this;
}
bool CNetMsg::operator==(const CNetObject& obj)
{
// compares the CNetMsgHdr data and the data buffers
const CNetMsg& msg = dynamic_cast<const CNetMsg&>(obj);
if (!(m_header == msg.m_header)) return false;
// compare the rest of the message data
return operator==(msg);
}
CNetMsg::~CNetMsg()
{
}
void CNetMsg::EmptyBuffer()
{
CNetObject::EmptyBuffer();
}
/*
void CNetMsg::Read()
{
// read header's data from void*
m_header.Read();
// read message data from void*
ReadBody();
}
*/
// reads m_header from CNetStream*, then creates a message
// and reads data of the message from the stream
void CNetMsg::Read(CNetStream* pStream, CNetMsg*& pMsg)
{
CNetMsgHdr header;
// read the header data. CNetMsgHdr::m_pData now points to the data
pStream->GetConnection()->Read(header.AllocateData(), header.GetSize_Read());
// parse out the member variables from m_pData
header.Read();
// create the message class based on the message class name
pMsg = pStream->CreateMessage(header.GetMSG().m_nClassId);
if (!pMsg)
throw CNetMsgException(ERR_NET_MSG_UKNOWN_TYPE, "CNetMsg* CNetMsg::Read(CNetStream* pStream)");
// release header.m_pData, because if I don't, then the CNetMsgHdr::operator=()
// will allocate a new m_pData for pMsg->m_header::m_pData and copy
// the context. That would be an overkill. I don't need this info anymore,
// since the member variables are properly populated already
header.EmptyBuffer();
// copy header's member variables
pMsg->GetMsgHdr()->operator=(header);
// now read the message body data. CNetMsg[derived]::m_pData now points to the data
pStream->GetConnection()->Read(pMsg->AllocateData(header.GetMsgSize()), header.GetMsgSize());
// parse out the member variables from m_pData
pMsg->ReadBody();
if (pMsg->HasChildren())
pMsg->ReadChildren(pStream);
// release the message's m_Data
pMsg->EmptyBuffer();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -