private void ParseMessage(Header header, byte[] buffer, int index)
        {
            byte[] message = new byte[HEADER_LENGTH + header.MessageLength];
            Array.Copy(buffer, index, message, 0, message.Length);
            UInt32 actualCrc = CalculateCrc(message);
            UInt32 expectedCrc = (UInt32)Utility.GetLongLE(buffer, index + message.Length, CRC_LENGTH);
            if (actualCrc != expectedCrc) return; //crc is not valid, do not parse

            IParser parser;
            if (_parsers.TryGetValue(header.Type, out parser))
            {
                if (_receiver != null)
                {
                    byte[] body = new byte[header.MessageLength];
                    Array.Copy(message, HEADER_LENGTH, body, 0, body.Length);

                    _receiver.OnMessageReceived(parser.Parse(header, body, actualCrc));
                }
            }
        }
        private Header ParseHeader(byte[] buffer, int index, int messageLength)
        {
            Header header = new Header
            {
                MessageLength = messageLength,
                Type = (MessageTypes)buffer[index + 2], //2 sync bytes
                TimeStamp = Utility.GetTime(buffer, index + 3), //2 sync bytes + 1 message type = 3
                SourceId = Utility.GetLongLE(buffer, index + 9, HEADER_SOURCEID_LENGTH) //2 sync bytes + 1 message type + 6 timestamp = 9
            };

            return header;
        }