#include "stdafx.h" #include "NetworkMsgBlock.h" #include #include #include #include #include "GMMemory.h" namespace ClientNet { CNetworkMsgBlock::CNetworkMsgBlock(size_t n) : CMessageBlock(n), m_next(0), m_eMsgType(NET_MSG_FREE), m_dwID(0) { } CNetworkMsgBlock::CNetworkMsgBlock(size_t n, INET_Addr& addr) : CMessageBlock(n), m_dstaddr(addr), m_next(0), m_eMsgType(NET_MSG_FREE), m_dwID(0) { } CNetworkMsgBlock::~CNetworkMsgBlock() { } bool CNetworkMsgBlock::WrapHeader(unsigned short usUsed_In, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In) { char* lpBuffer = rd_ptr(); if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain()) { reinterpret_cast(lpBuffer)->InitPtHead(usUsed_In, cCMD_In, usState_In, usError_In); CXORCrypt::GetInstance().EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0); wr_ptr(usUsed_In); return true; } fprintf(stderr, "CNetworkMsgBlock::WrapHeader - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n", cCMD_In, usUsed_In, capacity()); return false; } bool CNetworkMsgBlock::WrapCryptOld(unsigned short usUsed_In, unsigned char cCMD_In, unsigned long Tick_In) { char* lpBuffer = rd_ptr(); if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain()) { CXORCrypt& Crypt = CXORCrypt::GetInstance(); DWORD dwCodePage = Crypt.GetCodePage(1); if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage)) { PktBase* lpPktBase = reinterpret_cast(lpBuffer); lpPktBase->InitPtHead(usUsed_In, cCMD_In, Tick_In); lpPktBase->SetCodePage(dwCodePage); lpPktBase->SetCrypt(); // Çì´õ ÀÎÄÚµù Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0); wr_ptr(usUsed_In); return true; } } fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n", cCMD_In, usUsed_In, capacity()); return false; } bool CNetworkMsgBlock::WrapCryptOld(unsigned short usUsed_In, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In) { char* lpBuffer = rd_ptr(); if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain()) { CXORCrypt& Crypt = CXORCrypt::GetInstance(); DWORD dwCodePage = Crypt.GetCodePage(1); if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage)) { PktBase* lpPktBase = reinterpret_cast(lpBuffer); lpPktBase->InitPtHead(usUsed_In, cCMD_In, usState_In, usError_In); lpPktBase->SetCodePage(dwCodePage); lpPktBase->SetCrypt(); // Çì´õ ÀÎÄÚµù Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0); wr_ptr(usUsed_In); return true; } } fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n", cCMD_In, usUsed_In, capacity()); return false; } bool CNetworkMsgBlock::WrapCrypt(unsigned short usUsed_In, unsigned char cCMD_In, unsigned long Tick_In) { char* lpBuffer = rd_ptr(); if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain()) { CXORCrypt& Crypt = CXORCrypt::GetInstance(); DWORD dwCodePage = Crypt.GetCodePage(); if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage)) { PktBase* lpPktBase = reinterpret_cast(lpBuffer); lpPktBase->InitPtHead(usUsed_In, cCMD_In, Tick_In); lpPktBase->SetCodePage(dwCodePage); lpPktBase->SetCrypt(); // Çì´õ ÀÎÄÚµù Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0); wr_ptr(usUsed_In); return true; } } fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n", cCMD_In, usUsed_In, capacity()); return false; } bool CNetworkMsgBlock::WrapCrypt(unsigned short usUsed_In, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In) { char* lpBuffer = rd_ptr(); if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain()) { CXORCrypt& Crypt = CXORCrypt::GetInstance(); DWORD dwCodePage = Crypt.GetCodePage(); if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage)) { PktBase* lpPktBase = reinterpret_cast(lpBuffer); lpPktBase->InitPtHead(usUsed_In, cCMD_In, usState_In, usError_In); lpPktBase->SetCodePage(dwCodePage); lpPktBase->SetCrypt(); // Çì´õ ÀÎÄÚµù Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0); wr_ptr(usUsed_In); return true; } } fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n", cCMD_In, usUsed_In, capacity()); return false; } unsigned long CNetworkMsgBlock::GetMinCompressSize(unsigned short usSourceLength) { return usSourceLength + (usSourceLength / 64) + 16 + 3; } bool CNetworkMsgBlock::WrapCompress(char* lpSourceData, unsigned short usSourceLength, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In) { unsigned long dwDstBufferSize = static_cast(remain()); if(usSourceLength < sizeof(PktBase) || PktMaxLen < usSourceLength) { fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Packet wrapping error. CMD:0x%02x, usSourceLength:%d, dwDstBufferSize:%d\n", cCMD_In, usSourceLength, dwDstBufferSize); } else { if(dwDstBufferSize < sizeof(PktBase) || dwDstBufferSize < GetMinCompressSize(usSourceLength)) { fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Too small buffer size. CMD:0x%02x, usSourceLength:%d, dwDstBufferSize:%d\n", cCMD_In, usSourceLength, dwDstBufferSize); } else { char* lpDstBuffer = rd_ptr(); unsigned long dwCompressedSize = dwDstBufferSize - sizeof(PktBase); if(!CMiniLZO::Compress(lpSourceData + sizeof(PktBase), usSourceLength - sizeof(PktBase), lpDstBuffer + sizeof(PktBase), &dwCompressedSize)) { fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Packet Compress failed. CMD:0x%02x, usSourceLength:%d, " "dwDstBufferSize:%d\n", cCMD_In, usSourceLength, dwDstBufferSize); } else { if(dwDstBufferSize <= dwCompressedSize) { fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Compressed size is over than buffer size." "CMD:0x%02x, dwDstBufferSize:%d, dwCompressedSize:%d\n", cCMD_In, dwDstBufferSize, dwCompressedSize); } dwCompressedSize += sizeof(PktBase); PktBase* lpPktDst = reinterpret_cast(lpDstBuffer); lpPktDst->InitPtHead(static_cast(dwCompressedSize), cCMD_In, usState_In, usError_In); lpPktDst->SetCompress(); // ÀÎÄÚµù Çì´õ CXORCrypt::GetInstance().EncodeHeader(lpDstBuffer + 1, sizeof(PktBase) - 1, 0, 0); wr_ptr(dwCompressedSize); return true; } } } return false; } CNetworkMsgQueue::CNetworkMsgQueue() : m_lpListHead(NULL), m_lpListTail(NULL), m_nListNum(0) { } CNetworkMsgQueue::~CNetworkMsgQueue() { clear(); } void CNetworkMsgQueue::clear() { CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(*this); } void CNetworkMsgQueue::Enqueue(CNetworkMsgBlock* lpMsgBlock, bool bPendHead) { if(NULL != lpMsgBlock) { if(m_lpListHead == NULL) { m_lpListHead = m_lpListTail = lpMsgBlock; lpMsgBlock->next(NULL); } else if(!bPendHead) { m_lpListTail->next(lpMsgBlock); m_lpListTail = lpMsgBlock; lpMsgBlock->next(NULL); } else { lpMsgBlock->next(m_lpListHead); m_lpListHead = lpMsgBlock; } ++m_nListNum; } } CNetworkMsgBlock* CNetworkMsgQueue::Dequeue() { CNetworkMsgBlock* lpMsgBlock = NULL; if(m_lpListTail != NULL) { lpMsgBlock = m_lpListHead; m_lpListHead = m_lpListHead->next(); if(m_lpListTail == lpMsgBlock) { m_lpListTail = NULL; } lpMsgBlock->next(NULL); --m_nListNum; } return lpMsgBlock; } CNetworkMsgBlock* CNetworkMsgPool::GetNetworkMsgBlock(unsigned long dwSize, INET_Addr& addr) { MsgBlockLock::Syncronize sync(m_MsgBlockLock); CNetworkMsgBlock* lpMsgBlock = 0; if (m_MsgBlockList.empty()) { lpMsgBlock = new CNetworkMsgBlock(dwSize); } else { lpMsgBlock = m_MsgBlockList.front(); m_MsgBlockList.pop_front(); if (0 != lpMsgBlock) { lpMsgBlock->init(dwSize); } } if (0 != lpMsgBlock && lpMsgBlock->is_valid() && dwSize <= lpMsgBlock->capacity()) { return lpMsgBlock; } delete lpMsgBlock; return 0; } void CNetworkMsgPool::FreeNetworkMsgBlock(CNetworkMsgBlock* lpMsgBlock) { MsgBlockLock::Syncronize sync(m_MsgBlockLock); if (0 != lpMsgBlock) { if (m_MsgBlockList.size() < m_dwMaxBlockNum) { m_MsgBlockList.push_back(lpMsgBlock); } else { delete lpMsgBlock; } } } void CNetworkMsgPool::FreeNetworkMsgBlock(CNetworkMsgQueue& msgQueue) { MsgBlockLock::Syncronize sync(m_MsgBlockLock); CNetworkMsgBlock* lpMsgBlock = 0; while (0 != (lpMsgBlock = msgQueue.Dequeue())) { if (m_MsgBlockList.size() < m_dwMaxBlockNum) { m_MsgBlockList.push_back(lpMsgBlock); } else { delete lpMsgBlock; } } } CNetworkMsgPool& CNetworkMsgPool::GetInstance() { static CNetworkMsgPool msgPool; return msgPool; } CNetworkMsgPool::CNetworkMsgPool() : m_dwMaxBlockNum(50) { } CNetworkMsgPool::~CNetworkMsgPool() { MsgBlockLock::Syncronize sync(m_MsgBlockLock); MsgBlockList::iterator pos = m_MsgBlockList.begin(); MsgBlockList::iterator end = m_MsgBlockList.end(); for(; pos != end; ++pos) { delete *pos; } m_MsgBlockList.clear(); } CLockedMsgQueue::~CLockedMsgQueue() { MsgQueueLock::Syncronize sync(m_MsgQueueLock); m_MessageQueue.clear(); } CNetworkMsgBlock* CLockedMsgQueue::GetMessage() { MsgQueueLock::Syncronize sync(m_MsgQueueLock); return m_MessageQueue.Dequeue(); } void CLockedMsgQueue::GetMessages(CNetworkMsgQueue& msgQueue, DWORD dwItemNum) { CNetworkMsgBlock* lpMsg = 0; MsgQueueLock::Syncronize sync(m_MsgQueueLock); for(DWORD dwCount = 0; dwCount < dwItemNum; ++dwCount) { if(0 != (lpMsg = m_MessageQueue.Dequeue())) { msgQueue.Enqueue(lpMsg); } else { break; } } } void CLockedMsgQueue::PutMessage(CNetworkMsgBlock* lpMsg, bool bPendHead) { MsgQueueLock::Syncronize sync(m_MsgQueueLock); m_MessageQueue.Enqueue(lpMsg, bPendHead); } void CLockedMsgQueue::PutMessages(CNetworkMsgQueue& msgQueue) { CNetworkMsgBlock* lpMsg = 0; MsgQueueLock::Syncronize sync(m_MsgQueueLock); while(0 != (lpMsg = msgQueue.Dequeue())) { m_MessageQueue.Enqueue(lpMsg); } } CUnboundedWaitableMsgQueue::CUnboundedWaitableMsgQueue() { // Create Auto-Reset Event m_hNotEmpty = CreateEvent(0, FALSE, FALSE, 0); } CUnboundedWaitableMsgQueue::~CUnboundedWaitableMsgQueue() { CloseHandle(m_hNotEmpty); } DWORD CUnboundedWaitableMsgQueue::WaitForNotEmptyQueue(DWORD dwMilliseconds) { return WaitForSingleObject(m_hNotEmpty, dwMilliseconds); } CNetworkMsgBlock* CUnboundedWaitableMsgQueue::GetMessage() { MsgQueueLock::Syncronize sync(m_MsgQueueLock); CNetworkMsgBlock* lpMsg = m_MessageQueue.Dequeue(); InternalResetNotEmpty(); return lpMsg; } void CUnboundedWaitableMsgQueue::GetMessages(CNetworkMsgQueue& msgQueue, DWORD dwItemNum) { CNetworkMsgBlock* lpMsg = 0; MsgQueueLock::Syncronize sync(m_MsgQueueLock); for(DWORD dwCount = 0; dwCount < dwItemNum; ++dwCount) { if(0 != (lpMsg = m_MessageQueue.Dequeue())) { msgQueue.Enqueue(lpMsg); } else { break; } } InternalResetNotEmpty(); } void CUnboundedWaitableMsgQueue::PutMessage(CNetworkMsgBlock* lpMsg, bool bPendHead) { MsgQueueLock::Syncronize sync(m_MsgQueueLock); m_MessageQueue.Enqueue(lpMsg, bPendHead); InternalSetNotEmpty(); } void CUnboundedWaitableMsgQueue::PutMessages(CNetworkMsgQueue& msgQueue) { CNetworkMsgBlock* lpMsg = 0; MsgQueueLock::Syncronize sync(m_MsgQueueLock); while(0 != (lpMsg = msgQueue.Dequeue())) { m_MessageQueue.Enqueue(lpMsg); } InternalSetNotEmpty(); } void CUnboundedWaitableMsgQueue::InternalSetNotEmpty() { if(!m_bNotEmpty && 0 != m_MessageQueue.GetQueuedNum()) { SetEvent(m_hNotEmpty); m_bNotEmpty = true; } } void CUnboundedWaitableMsgQueue::InternalResetNotEmpty() { if(m_bNotEmpty && 0 == m_MessageQueue.GetQueuedNum()) { ResetEvent(m_hNotEmpty); m_bNotEmpty = false; } } }