/// <summary>
        /// This function deserialize from a byte array and return a new class filled
        /// with the data
        /// </summary>
        /// <param name="data">serialized data that contains the information</param>
        /// <returns>a new class filled with the deserialized data</returns>
        public static DatagramHeader DeSerialize(byte[] data)
        {
            var header = new DatagramHeader();

            using (var m = new MemoryStream(data))
            {
                using (var reader = new BinaryReader(m))
                {
                    header.FDXSignature     = reader.ReadUInt64();
                    header.FDXMajorVersion  = reader.ReadByte();
                    header.FDXMinorVersion  = reader.ReadByte();
                    header.NumberOfCommands = reader.ReadUInt16();
                    header.SequenceNumber   = reader.ReadUInt16();
                }
            }
            return(header);
        }
        public void DispatchDatagram(ref FDXDatagram datagram)
        {
            var lCopy = datagram.Buffer;

            //if the received bytes are too short, skip
            if (lCopy.Length < 16)
            {
                this.OnFormatError("Datagram too short");
                return;
            }

            // extract datagram header information
            var header = DatagramHeader.DeSerialize(lCopy);

            //if the signature doesn't match, skip
            if (header.FDXSignature != FDXHelper.kFDXSignature)
            {
                this.OnFormatError("Signature mismatch");
                return;
            }

            //if the major version doesn't match, skip
            if (header.FDXMajorVersion != FDXHelper.kFDXMajorVersion)
            {
                this.OnFormatError("Incorrect Major version");
                return;
            }

            //if the minor version doesn't match, skip
            if (header.FDXMinorVersion != FDXHelper.kFDXMinorVersion)
            {
                this.OnFormatError("Incorrect Minor Version");
                return;
            }

            //checking the sequence number
            if (header.SequenceNumber == FDXHelperSequenceNumber.kSequenceNumberUnused)
            {
                //we don't use sequence numbering
            }
            else
            {
                // check if the received sequence number is the expected
                if ((header.SequenceNumber & 0x7FFF) != this.mNextExpectedSequenceNumber)
                {
                    this.OnSequenceError(this.mNextExpectedSequenceNumber, header.SequenceNumber);
                }
                // if the session end sequence number arrives, reset the expected sequence number
                else if ((header.SequenceNumber & FDXHelperSequenceNumber.kSequenceNumberSessionEndFlag) != 0)
                {
                    this.mNextExpectedSequenceNumber = FDXHelperSequenceNumber.kSequenceNumberStart;
                }
                else
                {
                    // if expected sequence number matches the received sequence number
                    this.mNextExpectedSequenceNumber = FDXDatagram.IncrementSequenceNumber(header.SequenceNumber);
                }
            }

            //extract the number of commands and set the position
            var numOfCommands       = header.NumberOfCommands;
            var commandPosAndLength = DatagramHeader.Size();

            //create a buffer for the single commands
            var data = new byte[lCopy.Length - commandPosAndLength];

            for (var i = 0; i < numOfCommands; ++i)
            {
                //copy command number i into the buffer
                Array.Copy(lCopy, commandPosAndLength, data, 0, lCopy.Length - commandPosAndLength);

                //extract the header information and copy the data from the buffer into the concrete command
                // buffer
                var cmdHead         = CommandHeader.DeSerialize(data);
                var concreteCommand = new byte[cmdHead.CommandSize];
                Array.Copy(data, 0, concreteCommand, 0, concreteCommand.Length);
                commandPosAndLength += concreteCommand.Length;

                // with the command code we can decide what to do with the received command
                switch (cmdHead.CommandCode)
                {
                case FDXHelperCommandCode.kCommandCodeDataExchange:
                {
                    var cmd = DataExchangeCommand.DeSerialize(concreteCommand);
                    this.OnDataExchange(cmd);
                    break;
                }

                case FDXHelperCommandCode.kCommandCodeStatus:
                {
                    var cmd = StatusCommand.DeSerialize(concreteCommand);
                    this.OnStatus(cmd);
                    break;
                }

                case FDXHelperCommandCode.kCommandCodeSequenceNumberError:
                {
                    var com = SequenceNumberErrorCommand.DeSerialize(concreteCommand);
                    this.OnSequenceError(com.ExpectedSeqNr, com.ReceivedSeqNr);
                    break;
                }
                }
            }
        }