The RDPUDP_FEC_PAYLOAD_HEADER structure accompanies every datagram that contains an FEC payload.
Example #1
0
        /// <summary>
        /// Create RDPUDP_FEC_PAYLOAD_HEADER Structure
        /// </summary>
        /// <param name="snSourceStart"></param>
        /// <param name="uSourceRange"></param>
        /// <param name="uFecIndex"></param>
        /// <returns></returns>
        public RDPUDP_FEC_PAYLOAD_HEADER CreateFECPayloadHeader(uint snSourceStart, byte uSourceRange, byte uFecIndex)
        {
            RDPUDP_FEC_PAYLOAD_HEADER fecPayloadHeader = new RDPUDP_FEC_PAYLOAD_HEADER();

            Monitor.Enter(sequenceNumberLock);
            fecPayloadHeader.snCoded = ++CurSnCoded;
            Monitor.Exit(sequenceNumberLock);

            fecPayloadHeader.snSourceStart = snSourceStart;
            fecPayloadHeader.uRange        = uSourceRange;
            fecPayloadHeader.uFecIndex     = uFecIndex;
            fecPayloadHeader.uPadding      = 0x00;

            return(fecPayloadHeader);
        }
        public override bool Decode(PduMarshaler marshaler)
        {
            try
            {
                fecHeader.snSourceAck = marshaler.ReadUInt32();
                fecHeader.uReceiveWindowSize = marshaler.ReadUInt16();
                fecHeader.uFlags = (RDPUDP_FLAG)marshaler.ReadUInt16();

                if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN))
                {
                    RDPUDP_SYNDATA_PAYLOAD synData = new RDPUDP_SYNDATA_PAYLOAD();
                    synData.snInitialSequenceNumber = marshaler.ReadUInt32();
                    synData.uUpStreamMtu = marshaler.ReadUInt16();
                    synData.uDownStreamMtu = marshaler.ReadUInt16();
                    // This datagram MUST be zero-padded to increase the size of this datagram to 1232 bytes.

                    if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_CORRELATION_ID))
                    {
                        RDPUDP_CORRELATION_ID_PAYLOAD correlationId = new RDPUDP_CORRELATION_ID_PAYLOAD();
                        correlationId.uCorrelationId = marshaler.ReadBytes(16);
                        this.CorrelationId = correlationId;
                        correlationId.uReserved = marshaler.ReadBytes(16);
                    }

                    this.padding = marshaler.ReadToEnd();
                    this.SynData = synData;
                    return true;
                }

                if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK))
                {
                    // ACK.
                    RDPUDP_ACK_VECTOR_HEADER ackVector = new RDPUDP_ACK_VECTOR_HEADER();
                    ackVector.uAckVectorSize = marshaler.ReadUInt16();
                    ackVector.AckVectorElement = new AckVector[ackVector.uAckVectorSize];

                    List<byte> ackVecElementList = new List<byte>(marshaler.ReadBytes(ackVector.AckVectorElement.Length));
                    ackVecElementList.Reverse();

                    for (int i = 0; i < ackVector.AckVectorElement.Length; i++)
                    {
                        byte vecByte = ackVecElementList[i];
                        ackVector.AckVectorElement[i].Length = (byte)(0x3F & vecByte);
                        ackVector.AckVectorElement[i].State = (VECTOR_ELEMENT_STATE)(vecByte >> 6);
                    }

                    this.ackVectorHeader = ackVector;

                    // Padding (variable): A variable-sized array, of length zero or more,
                    // such that this structure ends on a DWORD ([MS-DTYP] section 2.2.9) boundary.
                    int padLen = 4 - (2 + ackVector.AckVectorElement.Length) % 4;
                    if (padLen > 0 && padLen != 4)
                    {
                        this.padding = marshaler.ReadBytes(padLen);
                    }

                    // Ack of Acks.
                    if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS))
                    {
                        RDPUDP_ACK_OF_ACKVECTOR_HEADER aoaHeader = new RDPUDP_ACK_OF_ACKVECTOR_HEADER();
                        aoaHeader.snAckOfAcksSeqNum = marshaler.ReadUInt32();
                        this.ackOfAckVector = aoaHeader;
                    }
                }

                if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA))
                {
                    if (!fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC))
                    {
                        // Source Data.
                        RDPUDP_SOURCE_PAYLOAD_HEADER srcHeader = new RDPUDP_SOURCE_PAYLOAD_HEADER();
                        srcHeader.snCoded = marshaler.ReadUInt32();
                        srcHeader.snSourceStart = marshaler.ReadUInt32();
                        this.sourceHeader = srcHeader;
                    }
                    else
                    {
                        // FEC Data.
                        RDPUDP_FEC_PAYLOAD_HEADER fecDataHeader = new RDPUDP_FEC_PAYLOAD_HEADER();
                        fecDataHeader.snCoded =  marshaler.ReadUInt32();
                        fecDataHeader.snSourceStart = marshaler.ReadUInt32();
                        fecDataHeader.uRange = marshaler.ReadByte();
                        fecDataHeader.uFecIndex = marshaler.ReadByte();
                        fecDataHeader.uPadding = marshaler.ReadUInt16();
                        this.fecPayloadHeader = fecDataHeader;
                    }

                    this.payload = marshaler.ReadToEnd();
                }

                return true;
            }
            catch
            {
                return false;
            }
        }
        public override bool Decode(PduMarshaler marshaler)
        {
            try
            {
                fecHeader.snSourceAck        = marshaler.ReadUInt32();
                fecHeader.uReceiveWindowSize = marshaler.ReadUInt16();
                fecHeader.uFlags             = (RDPUDP_FLAG)marshaler.ReadUInt16();

                if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN))
                {
                    RDPUDP_SYNDATA_PAYLOAD synData = new RDPUDP_SYNDATA_PAYLOAD();
                    synData.snInitialSequenceNumber = marshaler.ReadUInt32();
                    synData.uUpStreamMtu            = marshaler.ReadUInt16();
                    synData.uDownStreamMtu          = marshaler.ReadUInt16();
                    // This datagram MUST be zero-padded to increase the size of this datagram to 1232 bytes.

                    if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_CORRELATION_ID))
                    {
                        RDPUDP_CORRELATION_ID_PAYLOAD correlationId = new RDPUDP_CORRELATION_ID_PAYLOAD();
                        correlationId.uCorrelationId = marshaler.ReadBytes(16);
                        this.CorrelationId           = correlationId;
                        correlationId.uReserved      = marshaler.ReadBytes(16);
                    }

                    if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYNEX))
                    {
                        RDPUDP_SYNDATAEX_PAYLOAD synDataEx = new RDPUDP_SYNDATAEX_PAYLOAD();
                        synDataEx.uSynExFlags = (uSynExFlags_Values)marshaler.ReadUInt16();
                        synDataEx.uUdpVer     = (uUdpVer_Values)marshaler.ReadUInt16();
                        this.SynDataEx        = synDataEx;
                    }

                    this.padding = marshaler.ReadToEnd();
                    this.SynData = synData;
                    return(true);
                }


                if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK))
                {
                    // ACK.
                    RDPUDP_ACK_VECTOR_HEADER ackVector = new RDPUDP_ACK_VECTOR_HEADER();
                    ackVector.uAckVectorSize   = marshaler.ReadUInt16();
                    ackVector.AckVectorElement = new AckVector[ackVector.uAckVectorSize];

                    List <byte> ackVecElementList = new List <byte>(marshaler.ReadBytes(ackVector.AckVectorElement.Length));
                    ackVecElementList.Reverse();

                    for (int i = 0; i < ackVector.AckVectorElement.Length; i++)
                    {
                        byte vecByte = ackVecElementList[i];
                        ackVector.AckVectorElement[i].Length = (byte)(0x3F & vecByte);
                        ackVector.AckVectorElement[i].State  = (VECTOR_ELEMENT_STATE)(vecByte >> 6);
                    }

                    this.ackVectorHeader = ackVector;

                    // Padding (variable): A variable-sized array, of length zero or more,
                    // such that this structure ends on a DWORD ([MS-DTYP] section 2.2.9) boundary.
                    int padLen = 4 - (2 + ackVector.AckVectorElement.Length) % 4;
                    if (padLen > 0 && padLen != 4)
                    {
                        this.padding = marshaler.ReadBytes(padLen);
                    }


                    // Ack of Acks.
                    if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS))
                    {
                        RDPUDP_ACK_OF_ACKVECTOR_HEADER aoaHeader = new RDPUDP_ACK_OF_ACKVECTOR_HEADER();
                        aoaHeader.snAckOfAcksSeqNum = marshaler.ReadUInt32();
                        this.ackOfAckVector         = aoaHeader;
                    }
                }

                if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA))
                {
                    if (!fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC))
                    {
                        // Source Data.
                        RDPUDP_SOURCE_PAYLOAD_HEADER srcHeader = new RDPUDP_SOURCE_PAYLOAD_HEADER();
                        srcHeader.snCoded       = marshaler.ReadUInt32();
                        srcHeader.snSourceStart = marshaler.ReadUInt32();
                        this.sourceHeader       = srcHeader;
                    }
                    else
                    {
                        // FEC Data.
                        RDPUDP_FEC_PAYLOAD_HEADER fecDataHeader = new RDPUDP_FEC_PAYLOAD_HEADER();
                        fecDataHeader.snCoded       = marshaler.ReadUInt32();
                        fecDataHeader.snSourceStart = marshaler.ReadUInt32();
                        fecDataHeader.uRange        = marshaler.ReadByte();
                        fecDataHeader.uFecIndex     = marshaler.ReadByte();
                        fecDataHeader.uPadding      = marshaler.ReadUInt16();
                        this.fecPayloadHeader       = fecDataHeader;
                    }

                    this.payload = marshaler.ReadToEnd();
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        /// <summary>
        /// Create RDPUDP_FEC_PAYLOAD_HEADER Structure
        /// </summary>
        /// <param name="snSourceStart"></param>
        /// <param name="uSourceRange"></param>
        /// <param name="uFecIndex"></param>
        /// <returns></returns>
        public RDPUDP_FEC_PAYLOAD_HEADER CreateFECPayloadHeader(uint snSourceStart, byte uSourceRange, byte uFecIndex)
        {
            RDPUDP_FEC_PAYLOAD_HEADER fecPayloadHeader = new RDPUDP_FEC_PAYLOAD_HEADER();

            Monitor.Enter(sequenceNumberLock);
            fecPayloadHeader.snCoded = ++CurSnCoded;
            Monitor.Exit(sequenceNumberLock);

            fecPayloadHeader.snSourceStart = snSourceStart;
            fecPayloadHeader.uRange = uSourceRange;
            fecPayloadHeader.uFecIndex = uFecIndex;
            fecPayloadHeader.uPadding = 0x00;

            return fecPayloadHeader;
        }