diff options
Diffstat (limited to 'K2LABI/Common/FlowDecoder/FlowDecoder.cpp')
-rw-r--r-- | K2LABI/Common/FlowDecoder/FlowDecoder.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/K2LABI/Common/FlowDecoder/FlowDecoder.cpp b/K2LABI/Common/FlowDecoder/FlowDecoder.cpp new file mode 100644 index 0000000..f393416 --- /dev/null +++ b/K2LABI/Common/FlowDecoder/FlowDecoder.cpp @@ -0,0 +1,205 @@ +#include "FlowDecoder.h" +#include <assert.h> +#include <stdio.h> +#include <string.h> + + +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<unsigned long>(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<unsigned long>(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<unsigned long>(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; +} |