// ProtocolStack.h // Declaration of class cProtocolStack #ifndef __PROTOCOLSTACK_H #define __PROTOCOLSTACK_H #include // For assertions #define DEFAULT_HEADER_SIZE 16 #define FRAGMENT_SIZE 448 #define MAX_FRAGMENT_COUNT 1024 #pragma pack( push, 1 ) // The packet header struct cPacketHeader { DWORD m_dwSequence; DWORD m_dwFlags; DWORD m_dwCRC; WORD m_wUnk1; WORD m_wUnk2; WORD m_wTotalSize; WORD m_wUnk3; }; #pragma pack( pop ) class FragmentMask { public: FragmentMask () { ::memset (m_mask, 0, sizeof (m_mask)); m_size = 0; } void SetSize (WORD wSize) { _ASSERTE (wSize < MAX_FRAGMENT_COUNT); m_size = wSize; ::memset (m_mask, 0, sizeof (m_mask)); for (WORD wIndex = 0; wIndex < wSize; ++wIndex) { m_mask[wIndex/32] |= (1L << (wIndex % 32)); } } void GotFragment (WORD wWhich) { _ASSERTE (wWhich < m_size && wWhich >= 0); m_mask[wWhich/32] &= ~(1 << (wWhich % 32)); } bool IsComplete () { for (WORD wLoop = 0; wLoop < (FRAGMENT_SIZE/32); ++wLoop) { if (m_mask[wLoop]) { return false; } } return true; } private: DWORD m_mask[FRAGMENT_SIZE/32]; WORD m_size; }; class cMessageStack { public: #pragma pack( push, 1 ) struct cMessageHeader { DWORD m_dwSequence; DWORD m_dwObjectID; WORD m_wFragmentCount; WORD m_wFragmentLength; WORD m_wFragmentIndex, m_wUnknown1; }; #pragma pack( pop ) class cMessage { protected: // DWORD m_dwFragmentsMask; BYTE *m_pbData; mutable bool m_bOwn; mutable FragmentMask m_FragmentMask; public: cMessage( BYTE *pbData ); cMessage( const cMessage &msg ); ~cMessage(); cMessageHeader *getMessageHeader() const { return reinterpret_cast< cMessageHeader * >( m_pbData ); } cMessage &operator= ( const cMessage &msg ); BYTE *getBody() const { return m_pbData + sizeof( cMessageHeader ); } DWORD getBodyLength() const { return getMessageHeader()->m_wFragmentLength - sizeof( cMessageHeader ); } bool isComplete() const { return m_FragmentMask.IsComplete (); } DWORD getMessageCode() const { return *reinterpret_cast< DWORD * >( m_pbData + sizeof( cMessageHeader ) ); } bool fragmentMatch( BYTE *pFragmentStart ); void insertFragment( BYTE *pFragmentStart ); static DWORD calcMessageLength( BYTE *pbHeader ); }; // Objects wishing to receive class cCallback { public: virtual void onMessage( cMessage & ) = 0; }; private: typedef std::list< cMessage > cMessageList; cCallback *m_pCallback; cMessageList m_messages; public: cMessageStack(); ~cMessageStack(); void start( cCallback * ); void stop(); void processPacket( DWORD dwLength, BYTE *pbPayload ); private: void splitPacket( DWORD dwLength, BYTE *pbPayload ); }; #endif