#include "FlowDecoder.h" #include #include #include CFlowDecoder::CFlowDecoder() : m_nBytesInBuffer(0) , m_pCurrentReadPointer(0) , m_pBufferStart(0) , m_pBufferEnd(0) , m_DecoderState(E_WAITING_FOR_HEADER) , m_nSynchronized(false) { } void CFlowDecoder::DecodeFlow(BYTE* pBuffer, unsigned long nLen) { if (NULL == pBuffer || 0 ==nLen) return; InitializeBuffer(pBuffer, nLen); // The decoder state machine bool bWaitForNewData = false; //::OutputDebugString(_T("Enter FlowDecoder!\n") ); // Stay in state machine until all data has been consumed and no overflow occured while (!bWaitForNewData) { // Now process data in Buffer switch (m_DecoderState) { case E_WAITING_FOR_HEADER: switch (ReceiveHeader() ) { case E_STATE_NEEDS_MORE_DATA: // We need more data... we do nothing... just wait bWaitForNewData = true; break; case E_STATE_GOT_WRONG_DATA: m_nSynchronized = false; break; case E_STATE_OK: // We found a header... now we wait for the payload m_DecoderState = E_WAITING_FOR_PACKET_DATA; break; default: case E_STATE_UNDEFINED: assert(false); break; } break; case E_WAITING_FOR_PACKET_DATA: switch (ReceivePacket() ) { case E_STATE_NEEDS_MORE_DATA: // We need more data... we do nothing... just wait bWaitForNewData = true; break; case E_STATE_GOT_WRONG_DATA: case E_STATE_OK: // Now we wait for the next header m_DecoderState = E_WAITING_FOR_HEADER; break; default: case E_STATE_UNDEFINED: assert(false); break; } break; default: assert(false); m_DecoderState = E_WAITING_FOR_HEADER; break; } } } void CFlowDecoder::Reset() { InitializeBuffer(0, 0); m_DecoderState = E_WAITING_FOR_HEADER; } void CFlowDecoder::InitializeBuffer(BYTE* pBuffer, unsigned long nLen) { m_nBytesInBuffer = nLen; m_pCurrentReadPointer = pBuffer; m_pBufferStart = pBuffer; m_pBufferEnd = &pBuffer[nLen]; } unsigned long CFlowDecoder::GetNumberOfBytesInBuffer() const { return m_nBytesInBuffer; } unsigned long CFlowDecoder::GetNumberOfMemoryChunks() const { return (&m_pCurrentReadPointer[m_nBytesInBuffer] <= m_pBufferEnd) ? 1 : 2; } bool CFlowDecoder::GetMemoryChunk(unsigned long nNum, BYTE*& pReadPointer, unsigned long& nBytesAvailable) const { // Valid chunk number? if (nNum >= GetNumberOfMemoryChunks() ) return false; // Calculate number of bytes at end of buffer nBytesAvailable = static_cast(m_pBufferEnd - m_pCurrentReadPointer); if (nNum == 0) { pReadPointer = m_pCurrentReadPointer; } else // if (nNum == 1) { pReadPointer = m_pBufferStart; // Reuse already calculated number of bytes at end of buffer to calc number of bytes at start nBytesAvailable = static_cast(m_nBytesInBuffer - nBytesAvailable); } return true; } bool CFlowDecoder::CopyFromBuffer(BYTE* pTarget, unsigned long len) const { if (len > GetNumberOfBytesInBuffer() ) return false; BYTE* pBufferStart; unsigned long nBytesAvailable; // Chunk zero always exists GetMemoryChunk(0, pBufferStart, nBytesAvailable); // Now check if the whole packet is in first chunk; Do we need to get 2nd chunk? if (nBytesAvailable >= len) { // Copy first part ::memcpy(pTarget, pBufferStart, len); } else { // Merge first and 2nd chunk // Copy first part ::memcpy(pTarget, pBufferStart, nBytesAvailable); pTarget = &pTarget[nBytesAvailable]; len -= nBytesAvailable; // Now get 2nd part and merge bool bRetVal = GetMemoryChunk(1, pBufferStart, nBytesAvailable); assert(bRetVal); ::memcpy(pTarget, pBufferStart, len); } return true; } bool CFlowDecoder::RemoveBytesFromBuffer(unsigned long len) { if (len > m_nBytesInBuffer) { assert(false); return false; } if (GetNumberOfMemoryChunks() == 1) { // Advance pointer in chunk 0 m_pCurrentReadPointer = &m_pCurrentReadPointer[len]; } else { // Calculate number of bytes at end of buffer (i.e. chunk 0) unsigned long nBytesAtEnd = static_cast(m_pBufferEnd - m_pCurrentReadPointer); if (len >= nBytesAtEnd) { m_pCurrentReadPointer = &m_pBufferStart[len - nBytesAtEnd]; } else { // Advance pointer in chunk 0 m_pCurrentReadPointer = &m_pCurrentReadPointer[len]; } } m_nBytesInBuffer -= len; assert(m_pCurrentReadPointer >= m_pBufferStart); assert(m_pCurrentReadPointer <= m_pBufferEnd); return true; }