summaryrefslogtreecommitdiffstats
path: root/K2LABI/Common/FlowDecoder
diff options
context:
space:
mode:
Diffstat (limited to 'K2LABI/Common/FlowDecoder')
-rw-r--r--K2LABI/Common/FlowDecoder/FlowDecoder.cpp205
-rw-r--r--K2LABI/Common/FlowDecoder/FlowDecoder.h54
-rw-r--r--K2LABI/Common/FlowDecoder/IFlowDecoder.h16
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__