The ACK vector captures the state of the queue of Source Packets at the receiver endpoint.
Exemple #1
0
        /// <summary>
        /// Create RDPUDP_ACK_VECTOR_HEADER Structure for packet sending
        /// </summary>
        /// <returns></returns>
        public RDPUDP_ACK_VECTOR_HEADER CreateAckVectorHeader()
        {
            RDPUDP_ACK_VECTOR_HEADER ackVectorHeader = new RDPUDP_ACK_VECTOR_HEADER();

            if (inPacketDic.Count == 0)
            {
                // Not receive any source packet
                ackVectorHeader.uAckVectorSize   = 0;
                ackVectorHeader.AckVectorElement = null;
                ackVectorHeader.Padding          = null;
            }
            else
            {
                lock (inPacketDic)
                {
                    // Generate an ACK header.
                    List <AckVector>     ackVectorElements = new List <AckVector>();
                    VECTOR_ELEMENT_STATE currentState      = inPacketDic.ContainsKey(InSnAckOfAcksSeqNum) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED;
                    AckVector            ackVectorElement  = new AckVector();
                    ackVectorElement.State  = currentState;
                    ackVectorElement.Length = 0;

                    // RLE encoding.
                    for (uint i = InSnAckOfAcksSeqNum + 1; i <= SnSourceAck; i++)
                    {
                        currentState = inPacketDic.ContainsKey(i) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED;

                        // 0x40 is the max length of state length, of which I believe sould be indicate from soket config or types config not hard code here.
                        if (currentState != ackVectorElement.State || ackVectorElement.Length >= 0x40)
                        {
                            // If current state differs from last state, assign a new ack vector.
                            ackVectorElements.Add(ackVectorElement);
                            ackVectorElement        = new AckVector();
                            ackVectorElement.State  = currentState;
                            ackVectorElement.Length = 0;
                        }
                        else
                        {
                            // Else count++.
                            ackVectorElement.Length++;
                        }
                    }
                    ackVectorElements.Add(ackVectorElement);
                    ackVectorHeader.uAckVectorSize   = (ushort)ackVectorElements.Count;
                    ackVectorHeader.AckVectorElement = ackVectorElements.ToArray();

                    // ACK Vector created for all received packet, set number of received packets for ACK to 0
                    sourceNumNotAcked = 0;
                }
            }

            return(ackVectorHeader);
        }
        /// <summary>
        /// Wait for an ACK packet which meets certain conditions.
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param>
        /// <param name="timeout">Wait time.</param>
        /// <param name="expectAckVectors">Expected ack vectors.</param>
        /// <param name="hasFlag">Flags, which the ACK packet must contain.</param>
        /// <param name="notHasFlag">Flags, which the ACK packet must no contain.</param>
        /// <returns></returns>
        private RdpeudpPacket WaitForACKPacket(TransportMode udpTransportMode, TimeSpan timeout, AckVector[] expectAckVectors = null, RDPUDP_FLAG hasFlag = 0, RDPUDP_FLAG notHasFlag = 0)
        {
            RdpeudpSocket rdpeudpSocket = rdpeudpSocketR;
            if (udpTransportMode == TransportMode.Lossy)
            {
                rdpeudpSocket = rdpeudpSocketL;
            }

            DateTime endTime = DateTime.Now + timeout;

            while (DateTime.Now < endTime)
            {
                RdpeudpPacket ackPacket = rdpeudpSocket.ExpectACKPacket(endTime - DateTime.Now);
                if (ackPacket!=null)
                {
                    if (expectAckVectors != null)
                    {
                        if (!(ackPacket.ackVectorHeader.HasValue && CompareAckVectors(ackPacket.ackVectorHeader.Value.AckVectorElement, expectAckVectors)))
                        {
                            continue;
                        }
                    }
                    if (hasFlag != 0)
                    {
                        if ((ackPacket.fecHeader.uFlags & hasFlag) != hasFlag)
                        {
                            continue;
                        }
                    }
                    if (notHasFlag != 0)
                    {
                        if ((ackPacket.fecHeader.uFlags & notHasFlag) != 0)
                        {
                            continue;
                        }
                    }
                    return ackPacket;
                }
            }

            return null;
        }
        /// <summary>
        /// Compare two AckVectors.
        /// </summary>
        /// <param name="vector1">Ack Vector 1.</param>
        /// <param name="vector2">Ack Vector 2.</param>
        /// <returns></returns>
        private bool CompareAckVectors(AckVector[] vector1, AckVector[] vector2)
        {
            int posForVector1 = 0;
            int posForVector2 = 0;
            int length1 = vector1[posForVector1].Length+1;
            int length2 = vector2[posForVector2].Length+1;
            while (posForVector1 < vector1.Length && posForVector2 < vector2.Length)
            {
                if (vector1[posForVector1].State != vector2[posForVector2].State)
                {
                    return false;
                }

                if (length1 == length2)
                {
                    posForVector1++;
                    posForVector2++;
                    if (!(posForVector1 < vector1.Length && posForVector2 < vector2.Length))
                        break;
                    length1 = vector1[posForVector1].Length+1;
                    length2 = vector2[posForVector2].Length+1;
                }
                else if (length1 > length2)
                {
                    length1 -= length2;
                    posForVector2++;
                    if (!(posForVector1 < vector1.Length && posForVector2 < vector2.Length))
                        break;
                    length2 = vector2[posForVector2].Length + 1;
                }
                else
                {
                    length2 -= length1;
                    posForVector1++;
                    if (!(posForVector1 < vector1.Length && posForVector2 < vector2.Length))
                        break;
                    length1 = vector1[posForVector1].Length + 1;
                }
            }
            if (posForVector1 < vector1.Length || posForVector2 < vector2.Length)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// Create RDPUDP_ACK_VECTOR_HEADER Structure for packet sending
        /// </summary>
        /// <returns></returns>
        public RDPUDP_ACK_VECTOR_HEADER CreateAckVectorHeader()
        {
            RDPUDP_ACK_VECTOR_HEADER ackVectorHeader = new RDPUDP_ACK_VECTOR_HEADER();
            if (inPacketDic.Count == 0)
            {
                // Not receive any source packet
                ackVectorHeader.uAckVectorSize = 0;
                ackVectorHeader.AckVectorElement = null;
                ackVectorHeader.Padding = null;
            }
            else
            {
                lock (inPacketDic)
                {
                    // Generate an ACK header.
                    List<AckVector> ackVectorElements = new List<AckVector>();
                    VECTOR_ELEMENT_STATE currentState = inPacketDic.ContainsKey(InSnAckOfAcksSeqNum) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED;
                    AckVector ackVectorElement = new AckVector();
                    ackVectorElement.State = currentState;
                    ackVectorElement.Length = 0;

                    // RLE encoding.
                    for (uint i = InSnAckOfAcksSeqNum + 1; i <= SnSourceAck; i++)
                    {
                        currentState = inPacketDic.ContainsKey(i) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED;

                        // 0x40 is the max length of state length, of which I believe sould be indicate from soket config or types config not hard code here.
                        if (currentState != ackVectorElement.State || ackVectorElement.Length >= 0x40)
                        {
                            // If current state differs from last state, assign a new ack vector.
                            ackVectorElements.Add(ackVectorElement);
                            ackVectorElement = new AckVector();
                            ackVectorElement.State = currentState;
                            ackVectorElement.Length = 0;
                        }
                        else
                        {
                            // Else count++.
                            ackVectorElement.Length++;
                        }
                    }
                    ackVectorElements.Add(ackVectorElement);
                    ackVectorHeader.uAckVectorSize = (ushort)ackVectorElements.Count;
                    ackVectorHeader.AckVectorElement = ackVectorElements.ToArray();

                    // ACK Vector created for all received packet, set number of received packets for ACK to 0
                    sourceNumNotAcked = 0;
                }
            }

            return ackVectorHeader;
        }
        public void S2_DataTransfer_SequenceNumberWrapAround()
        {
            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            TransportMode[] transportModeArray = new TransportMode[] { TransportMode.Reliable, TransportMode.Lossy };
            foreach (TransportMode transportMode in transportModeArray)
            {
                this.TestSite.Log.Add(LogEntryKind.Comment, "Create a {0} UDP connection.", transportMode);
                initSequenceNumber = uint.MaxValue - 3;
                this.EstablishUDPConnection(transportMode, waitTime, true);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Create a {0} RDPEMT connection.", transportMode);
                this.EstablishRdpemtConnection(transportMode, waitTime);

                if (getSourcePacketSequenceNumber(transportMode) > getSnInitialSequenceNumber(transportMode))
                {
                    this.TestSite.Log.Add(LogEntryKind.Comment, "Not wrap around yet, Send one RDPUDP packet.");
                    this.SendNextValidUdpPacket(transportMode);
                }

                this.TestSite.Log.Add(LogEntryKind.Comment, "Already wrap around, Send three RDPUDP packet again.");
                this.SendNextValidUdpPacket(transportMode);
                this.SendNextValidUdpPacket(transportMode);
                this.SendNextValidUdpPacket(transportMode);

                #region Create Expect Ack Vectors

                List<AckVector> expectedAckVectors = new List<AckVector>();
                AckVector ackVector = new AckVector();
                ackVector.State = VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED;
                ackVector.Length = (byte)(getSourcePacketSequenceNumber(transportMode) + (uint.MaxValue- getSnInitialSequenceNumber(transportMode)));
                expectedAckVectors.Add(ackVector);

                #endregion Create Expect Ack Vectors

                this.TestSite.Log.Add(LogEntryKind.Comment, "Expect RDP client to send an ACK packet to acknowledge the receipt correctly");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime, expectedAckVectors.ToArray());
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK to correctly acknowledge the receipt of source packet. Transport mode is {0}", transportMode);

            }
        }
        public void S2_DataTransfer_AcknowledgeTest_AcknowlegeLossyPackage()
        {
            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            TransportMode[] transportModeArray = new TransportMode[] { TransportMode.Reliable, TransportMode.Lossy };

            foreach (TransportMode transportMode in transportModeArray)
            {
                this.TestSite.Log.Add(LogEntryKind.Comment, "Create a {0} UDP connection.", transportMode);
                this.EstablishUDPConnection(transportMode, waitTime, true);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Create a {0} RDPEMT connection.", transportMode);
                this.EstablishRdpemtConnection(transportMode, waitTime);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Send one RDPUDP packet.");
                this.SendNextValidUdpPacket(transportMode);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Send the second RDPUDP packet, don't really send it, it is as a lost packet");
                RdpeudpPacket losspacket = this.GetNextValidUdpPacket(transportMode);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Send the third and the forth RDPUDP packet.");
                this.SendNextValidUdpPacket(transportMode);
                this.SendNextValidUdpPacket(transportMode);

                #region Create Expect Ack Vectors

                List<AckVector> expectedAckVectors = new List<AckVector>();

                // All packet before the lost one are received.
                AckVector ackVector = new AckVector();
                ackVector.State = VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED;
                ackVector.Length = (byte)(losspacket.sourceHeader.Value.snSourceStart - getSnInitialSequenceNumber(transportMode) - 2);
                expectedAckVectors.Add(ackVector);

                // One packet lost.
                ackVector = new AckVector();
                ackVector.State = VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED;
                ackVector.Length = 0;
                expectedAckVectors.Add(ackVector);

                // Two packet received.
                ackVector = new AckVector();
                ackVector.State = VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED;
                ackVector.Length = 1;
                expectedAckVectors.Add(ackVector);

                #endregion Create Expect Ack Vectors

                // Expect an ACK packet with expected acknowledge information.
                this.TestSite.Log.Add(LogEntryKind.Comment, "expect an ACK packet with expected acknowledge information.");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime, expectedAckVectors.ToArray());
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK to acknowledge the receipt of source packets correctly, transport mode is {0}.", transportMode);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Send the second RDPUDP packet, which is lost before");
                this.SendPacket(transportMode, losspacket);

                #region Create Expect Ack Vectors

                expectedAckVectors.Clear();
                // All packet before the lost one are received.
                ackVector = new AckVector();
                ackVector.State = VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED;
                ackVector.Length = (byte)(losspacket.sourceHeader.Value.snSourceStart - getSnInitialSequenceNumber(transportMode)-2);

                // The lost one and the next two packed are received too.
                ackVector.Length += 3;
                expectedAckVectors.Add(ackVector);

                #endregion

                // Expect an ACK packet with acknowledge all packets recieved.
                this.TestSite.Log.Add(LogEntryKind.Comment, "expect an ACK packet with acknowledge all packets received.");
                ackpacket = WaitForACKPacket(transportMode, waitTime, expectedAckVectors.ToArray());
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK to acknowledge the receipt of source packets correctly, transport mode is {0}.", transportMode);

            }
        }
        public void S2_DataTransfer_ClientReceiveData()
        {
            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            TransportMode[] transportModeArray = new TransportMode[] { TransportMode.Reliable, TransportMode.Lossy };
            foreach (TransportMode transportMode in transportModeArray)
            {
                this.TestSite.Log.Add(LogEntryKind.Comment, "Create a {0} UDP connection.", transportMode);
                this.EstablishUDPConnection(transportMode, waitTime, true);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Send the first RDPEUDP Source packet");
                RdpeudpPacket packet = this.GetFirstValidUdpPacket(transportMode);
                this.SendPacket(transportMode, packet);

                #region Create Expect Ack Vectors

                List<AckVector> expectedAckVectors = new List<AckVector>();
                AckVector ackVector = new AckVector();
                ackVector.State = VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED;
                ackVector.Length = (byte)(packet.sourceHeader.Value.snSourceStart - getSnInitialSequenceNumber(transportMode) - 1);
                expectedAckVectors.Add(ackVector);

                #endregion Create Expect Ack Vectors

                this.TestSite.Log.Add(LogEntryKind.Comment, "Expect RDP client to send an ACK packet to acknowledge the receipt");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime, expectedAckVectors.ToArray());
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK to acknowledge the receipt of source packet. Transport mode is {0}", transportMode);

            }
        }