summaryrefslogtreecommitdiffstats
path: root/K2LABI/IPC/IPCFlowDecoder.cpp
blob: 6b6ec190f8c4f7d5ea19abc2364f30607c2b4c84 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "windows-adapter.h"
#include "IPCFlowDecoder.h"
#include "Ipc.h"
#include <assert.h>


#define PACKET_BUFFER_SIZE (1 << 18)
#define PACKET_TEST_DEPTH               0

CIPCFlowDecoder::CIPCFlowDecoder(CIpc* pIpc) : CFlowDecoder()
                                                , m_pPacket(new BYTE[PACKET_BUFFER_SIZE])
                                                , m_ValidPacketCount(PACKET_TEST_DEPTH)
                                                , m_ReceiveIndex(0)
                                                , m_pIpc(pIpc)
{
}

CIPCFlowDecoder::~CIPCFlowDecoder()
{
    delete [] m_pPacket;
}

void CIPCFlowDecoder::Reset()
{
    m_ReceiveIndex = 0;
    m_ValidPacketCount = 0;
    this->CFlowDecoder::Reset();
}

CFlowDecoder::eStateRetVal CIPCFlowDecoder::ReceiveHeader()
{
    unsigned long bytesMissingForHeader = sizeof(CIpcPacket) - m_ReceiveIndex;
    unsigned long bytesToAppend         = (bytesMissingForHeader <= GetNumberOfBytesInBuffer() ) ? bytesMissingForHeader : GetNumberOfBytesInBuffer();
    
    if (!CopyFromBuffer(&m_pPacket[m_ReceiveIndex], bytesToAppend) )
        return E_STATE_NEEDS_MORE_DATA;

    m_ReceiveIndex += bytesToAppend;

    if (m_ReceiveIndex < sizeof(CIpcPacket) )
    {
        RemoveBytesFromBuffer(bytesToAppend);
        return E_STATE_NEEDS_MORE_DATA;
    }

    CIpcPacket* pHeader = reinterpret_cast<CIpcPacket*>(m_pPacket);

    if (pHeader->m_head != ABI_IPC_PACKET_HEAD)
    {
        if(m_nSynchronized && m_pIpc)
        {
            //::OutputDebugString("Check: Head wrong\n");
            IIPCListener* listener = m_pIpc->GetListener();

            if(listener)
                listener->OnError(m_pIpc);
        }

        // Something went wrong...
        m_ReceiveIndex = 0;
        m_ValidPacketCount = 0;

        // Remove 1 byte from buffer
        RemoveBytesFromBuffer(1);
        return E_STATE_GOT_WRONG_DATA;
    }

    // We've found a header now check the checksum
    unsigned char checksum = 0;

    // Omit last byte -> checksum!
    for (int i = 0; i < sizeof(CIpcPacket) - 1; i++)
    {
        checksum += m_pPacket[i];
    }

    if (checksum != pHeader->m_hdrCrc)
    {        
        if(m_nSynchronized && m_pIpc)
        {
            //::OutputDebugString("Check: Crc wrong\n");
            IIPCListener* listener = m_pIpc->GetListener();
            if(listener)
                listener->OnError(m_pIpc);
        }
        
        // Something went wrong...
        m_ReceiveIndex = 0;
        m_ValidPacketCount = 0;

        // Remove 1 byte from buffer
        RemoveBytesFromBuffer(1);
        return E_STATE_GOT_WRONG_DATA;
    }
    //if(!m_nSynchronized) ::OutputDebugString("Check: Header correct\n");
    m_nSynchronized = true;

    RemoveBytesFromBuffer(bytesToAppend);

    // Valid header found!!!
    return E_STATE_OK;
}

CFlowDecoder::eStateRetVal CIPCFlowDecoder::ReceivePacket()
{
    unsigned long nLengthOfPacket       = reinterpret_cast<CIpcPacket*>(m_pPacket)->m_length + sizeof(CIpcPacket);
    unsigned long bytesMissingForPacket = nLengthOfPacket - m_ReceiveIndex;
    unsigned long bytesToAppend         = (bytesMissingForPacket > GetNumberOfBytesInBuffer() ) ? GetNumberOfBytesInBuffer() : bytesMissingForPacket;
    
    // Copy buffer... should (must) never fail!
    if (!CopyFromBuffer(&m_pPacket[m_ReceiveIndex], bytesToAppend) )
        return E_STATE_NEEDS_MORE_DATA;
    
    // Accept the data as valid now and go on...
    m_ReceiveIndex += bytesToAppend;

    // Remove bytes from source buffer...
    RemoveBytesFromBuffer(bytesToAppend);

    // Received enough data?
    if (m_ReceiveIndex < nLengthOfPacket)
        return E_STATE_NEEDS_MORE_DATA;

    m_ReceiveIndex = 0;
    
    if (m_ValidPacketCount >= PACKET_TEST_DEPTH)
    {
        // Dispatch Message if there's was no overflow during copy!
        if (m_pIpc)
        {
            m_pIpc->OnPacket(reinterpret_cast<CIpcPacket*>(m_pPacket) );
        }
    }
    else
    {
        m_ValidPacketCount++;
    }

    return E_STATE_OK;
}