diff options
Diffstat (limited to 'K2LABI/Common/FlowDecoder')
-rw-r--r-- | K2LABI/Common/FlowDecoder/FlowDecoder.cpp | 205 | ||||
-rw-r--r-- | K2LABI/Common/FlowDecoder/FlowDecoder.h | 54 | ||||
-rw-r--r-- | K2LABI/Common/FlowDecoder/IFlowDecoder.h | 16 |
3 files changed, 275 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; +} diff --git a/K2LABI/Common/FlowDecoder/FlowDecoder.h b/K2LABI/Common/FlowDecoder/FlowDecoder.h new file mode 100644 index 0000000..6f8be64 --- /dev/null +++ b/K2LABI/Common/FlowDecoder/FlowDecoder.h @@ -0,0 +1,54 @@ +#ifndef __FLOW_DECODER_H__ +#define __FLOW_DECODER_H__ + +#include "IFlowDecoder.h" + + +class CFlowDecoder : public IFlowDecoder +{ +public: + CFlowDecoder(); + virtual ~CFlowDecoder() {} + + // Gets called to submit a new package to buffer + void DecodeFlow(BYTE* pBuffer, unsigned long nLen); + virtual void Reset(); + +protected: + void InitializeBuffer(BYTE* pBuffer, unsigned long nLen); + unsigned long GetNumberOfBytesInBuffer() const; + unsigned long GetNumberOfMemoryChunks() const; + bool GetMemoryChunk(unsigned long nNum, BYTE*& pReadPointer, unsigned long& nBytesAvailable) const; + bool AddBytesToBuffer(BYTE* pBuffer, unsigned long nLen); + bool CopyFromBuffer(BYTE* pTarget, unsigned long len) const; + bool RemoveBytesFromBuffer(unsigned long len); + +protected: + enum eStateRetVal + { + E_STATE_NEEDS_MORE_DATA, + E_STATE_GOT_WRONG_DATA, + E_STATE_OK, + E_STATE_UNDEFINED + }; + + bool m_nSynchronized; + + virtual eStateRetVal ReceiveHeader() = 0; + virtual eStateRetVal ReceivePacket() = 0; + +private: + enum eDecoderState + { + E_WAITING_FOR_HEADER, + E_WAITING_FOR_PACKET_DATA, + }; + + unsigned long m_nBytesInBuffer; + BYTE* m_pCurrentReadPointer; + BYTE* m_pBufferStart; + BYTE* m_pBufferEnd; + eDecoderState m_DecoderState; +}; + +#endif // __FLOW_DECODER_H__ diff --git a/K2LABI/Common/FlowDecoder/IFlowDecoder.h b/K2LABI/Common/FlowDecoder/IFlowDecoder.h new file mode 100644 index 0000000..16dae7c --- /dev/null +++ b/K2LABI/Common/FlowDecoder/IFlowDecoder.h @@ -0,0 +1,16 @@ +#ifndef __IFLOWDECODER_H__ +#define __IFLOWDECODER_H__ + +#include "k2l-type.h" + + +class IFlowDecoder +{ +public: + IFlowDecoder() {} + virtual ~IFlowDecoder() {} + + virtual void DecodeFlow(BYTE* pBuffer, unsigned long nLen) = 0; +}; + +#endif // __IFLOWDECODER_H__ |