Esempio n. 1
0
        public void S1_Connection_Keepalive_ClientSendKeepAlive()
        {
            TransportMode[] transportModeArray = new TransportMode[] { TransportMode.Reliable, TransportMode.Lossy };

            CheckPlatformCompatibility(ref transportModeArray);

            CheckSecurityProtocolForMultitransport();

            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            foreach (TransportMode transportMode in transportModeArray)
            {
                DoUntilSucceed(() =>
                {
                    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);
                    return(this.EstablishRdpemtConnection(transportMode, waitTime));
                },
                               this.waitTime * 5,
                               TimeSpan.FromSeconds(0.5),
                               "RDPEMT tunnel creation failed");

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


                this.TestSite.Log.Add(LogEntryKind.Comment, "Expect RDP client to resend the ACK packet to keep alive");
                ackpacket = WaitForACKPacket(transportMode, waitTime);
                Site.Assert.IsNotNull(ackpacket, "Client should resend the ACK packet to keep alive. Transport mode is {0}", transportMode);
            }
        }
        public void S1_Connection_Keepalive_ClientSendKeepAlive()
        {
            CheckSecurityProtocolForMultitransport();

            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, "Expect RDP client to send an ACK packet to keep alive or acknowledge the receipt");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime);
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK to keep alive or acknowledge the receipt of source packet. Transport mode is {0}", transportMode);


                this.TestSite.Log.Add(LogEntryKind.Comment, "Expect RDP client to resend the ACK packet to keep alive");
                ackpacket = WaitForACKPacket(transportMode, waitTime);
                Site.Assert.IsNotNull(ackpacket, "Client should resend the ACK packet to keep alive. 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);
            }
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="eudpSocket">RDPEUDP Socket, which is transport</param>
        public RdpeudpDTLSChannel(RdpeudpSocket eudpSocket)
        {
            if (eudpSocket == null || eudpSocket.TransMode == TransportMode.Reliable)
            {
                throw new NotSupportedException("RdpeudpSocket is null or it is a socket for reliable RDPEUDP connection.");
            }

            this.rdpeudpSocket           = eudpSocket;
            this.rdpeudpSocket.Received += ReceiveBytes;
            isAuthenticated              = false;

            rdpeudpSocket.Disconnected += RdpeudpSocket_Disconnected;

            receivedBuffer = new List <byte[]>();
            toSendBuffer   = new List <byte[]>();

            if (eudpSocket.AutoHandle)
            {
                // Check whether there is packets in unprocessed packet buffer

                RdpeudpPacket packet = eudpSocket.ExpectPacket(shortWaitTime);
                if (packet != null)
                {
                    eudpSocket.ReceivePacket(packet);
                }
            }
        }
        /// <summary>
        /// Expect for a Source Packet.
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param>
        /// <param name="timeout">Wait time</param>
        /// <returns></returns>
        private RdpeudpPacket WaitForSourcePacket(TransportMode udpTransportMode, TimeSpan timeout, uint sequnceNumber = 0)
        {
            RdpeudpSocket rdpeudpSocket = rdpeudpSocketR;

            if (udpTransportMode == TransportMode.Lossy)
            {
                rdpeudpSocket = rdpeudpSocketL;
            }

            DateTime endTime = DateTime.Now + timeout;

            while (DateTime.Now < endTime)
            {
                RdpeudpPacket packet = rdpeudpSocket.ExpectPacket(endTime - DateTime.Now);
                if (packet != null && packet.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA))
                {
                    if (sequnceNumber == 0 || packet.sourceHeader.Value.snSourceStart == sequnceNumber)
                    {
                        return(packet);
                    }
                }
            }

            return(null);
        }
        public void S2_DataTransfer_ClientAckDelay()
        {
            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);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Send three RDPUDP packets, wait {0} ms between each send");
                Thread.Sleep(DelayedACKTimer);
                this.SendNextValidUdpPacket(transportMode);
                Thread.Sleep(DelayedACKTimer);
                this.SendNextValidUdpPacket(transportMode);
                Thread.Sleep(DelayedACKTimer);
                this.SendNextValidUdpPacket(transportMode);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Expect RDP client to send an ACK packet with flag: RDPUDP_FLAG_ACKDELAYED");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime, null, RDPUDP_FLAG.RDPUDP_FLAG_ACKDELAYED);
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK with RDPUDP_FLAG_ACKDELAYED flag. Transport mode is {0}", transportMode);
            }
        }
        private int GetMaxiumPayloadSizeForSourcePacket(int upStreamMtu)
        {
            // Create a fake empty RDPEUDP ACK+SOURCE packet.
            var packet = new RdpeudpPacket();

            packet.fecHeader.snSourceAck = 0;
            packet.fecHeader.uReceiveWindowSize = 0;
            packet.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_DATA | RDPUDP_FLAG.RDPUDP_FLAG_ACK;

            var ackVectorHeader = new RDPUDP_ACK_VECTOR_HEADER();
            ackVectorHeader.uAckVectorSize = 0;
            ackVectorHeader.AckVectorElement = null;
            ackVectorHeader.Padding = null;
            packet.ackVectorHeader = ackVectorHeader;

            var sourceHeader = new RDPUDP_SOURCE_PAYLOAD_HEADER();
            sourceHeader.snCoded = 0;
            sourceHeader.snSourceStart = 0;
            packet.sourceHeader = sourceHeader;

            var size = PduMarshaler.Marshal(packet).Length;

            // Maximum payload size = upstream MTU - empty ACK+SOURCE header size.
            return upStreamMtu - size;

        }
        /// <summary>
        /// Send a udp packet.
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param>
        /// <param name="packet">The packet to send.</param>
        private void SendPacket(TransportMode udpTransportMode, RdpeudpPacket packet)
        {
            RdpeudpSocket rdpeudpSocket = rdpeudpSocketR;
            if (udpTransportMode == TransportMode.Lossy)
            {
                rdpeudpSocket = rdpeudpSocketL;
            }

            rdpeudpSocket.SendPacket(packet);
        }
        /// <summary>
        /// Get the First valid UDP Source Packet.
        /// </summary>
        /// <param name="udpTransportMode"></param>
        /// <returns></returns>
        private RdpeudpPacket GetFirstValidUdpPacket(TransportMode udpTransportMode)
        {
            byte[]        dataToSent  = null;
            RdpeudpPacket firstPacket = null;
            String        certFile;

            PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePath", out certFile);

            String certPwd;

            PtfPropUtility.GetPtfPropertyValue(Site, "CertificatePassword", out certPwd);

            X509Certificate2 cert = new X509Certificate2(certFile, certPwd);

            if (udpTransportMode == TransportMode.Reliable)
            {
                RdpeudpTLSChannel secChannel = new RdpeudpTLSChannel(rdpeudpSocketR);
                secChannel.AuthenticateAsServer(cert);
                RdpeudpPacket packet = rdpeudpSocketR.ExpectPacket(waitTime);
                if (packet.payload != null)
                {
                    rdpeudpSocketR.ProcessSourceData(packet); // Process Source Data to make sure ACK Vector created next is correct
                    secChannel.ReceiveBytes(packet.payload);
                }
                dataToSent = secChannel.GetDataToSent(waitTime);

                // Make sure this test packet does not exceed upstream MTU.
                int maxPayloadsize = GetMaxiumPayloadSizeForSourcePacket(rdpeudpSocketR.UUpStreamMtu);

                dataToSent = dataToSent.Take(maxPayloadsize).ToArray();

                firstPacket = rdpeudpSocketR.CreateSourcePacket(dataToSent);
            }
            else
            {
                RdpeudpDTLSChannel secChannel = new RdpeudpDTLSChannel(rdpeudpSocketL);
                secChannel.AuthenticateAsServer(cert);
                RdpeudpPacket packet = rdpeudpSocketL.ExpectPacket(waitTime);
                if (packet.payload != null)
                {
                    rdpeudpSocketL.ProcessSourceData(packet); // Process Source Data to make sure ACK Vector created next is correct
                    secChannel.ReceiveBytes(packet.payload);
                }
                dataToSent = secChannel.GetDataToSent(waitTime);

                // Make sure this test packet does not exceed upstream MTU.
                int maxPayloadsize = GetMaxiumPayloadSizeForSourcePacket(rdpeudpSocketL.UUpStreamMtu);

                dataToSent = dataToSent.Take(maxPayloadsize).ToArray();

                firstPacket = rdpeudpSocketL.CreateSourcePacket(dataToSent);
            }

            return(firstPacket);
        }
        /// <summary>
        /// Verify an ACK Packet.
        /// </summary>
        /// <param name="ackPacket">The ACK packet.</param>
        private void VerifyACKPacket(RdpeudpPacket ackPacket)
        {
            if (ackPacket == null)
            {
                this.Site.Assert.Fail("The ACK Packet should not be null!");
            }

            if ((ackPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_ACK) == 0)
            {
                this.Site.Assert.Fail("The RDPUDP_FLAG_ACK flag MUST be set in ACK packet!");
            }
        }
        public void S2_DataTransfer_SequenceNumberWrapAround()
        {
            TransportMode[] transportModeArray = new TransportMode[] { TransportMode.Reliable, TransportMode.Lossy };

            CheckPlatformCompatibility(ref transportModeArray);

            CheckSecurityProtocolForMultitransport();

            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            foreach (TransportMode transportMode in transportModeArray)
            {
                DoUntilSucceed(() =>
                {
                    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);
                    return(this.EstablishRdpemtConnection(transportMode, waitTime));
                },
                               this.waitTime * 5,
                               TimeSpan.FromSeconds(0.5),
                               "RDPEMT tunnel creation failed");

                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_CongestionControlTest_ClientReceiveData()
        {
            TransportMode[] transportModeArray = new TransportMode[] { TransportMode.Reliable, TransportMode.Lossy };

            CheckPlatformCompatibility(ref transportModeArray);

            CheckSecurityProtocolForMultitransport();

            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            foreach (TransportMode transportMode in transportModeArray)
            {
                DoUntilSucceed(() =>
                {
                    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);
                    return(this.EstablishRdpemtConnection(transportMode, waitTime));
                },
                               this.waitTime * 5,
                               TimeSpan.FromSeconds(0.5),
                               "RDPEMT tunnel creation failed");

                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 another three RDPUDP packet.");
                this.SendNextValidUdpPacket(transportMode);
                this.SendNextValidUdpPacket(transportMode);
                this.SendNextValidUdpPacket(transportMode);

                // Expect an ACK packet with RDPUDP_FLAG_SYN flag.
                this.TestSite.Log.Add(LogEntryKind.Comment, "expect an ACK packet with RDPUDP_FLAG_SYN flag.");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime, null, RDPUDP_FLAG.RDPUDP_FLAG_CN, 0);
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK packet with RDPUDP_FLAG_SYN flag, transport mode is {0}", transportMode);

                RdpeudpPacket packet = this.GetNextValidUdpPacket(transportMode);
                packet.fecHeader.uFlags = packet.fecHeader.uFlags | RDPUDP_FLAG.RDPUDP_FLAG_CWR;
                this.SendPacket(transportMode, packet);

                // Expect an ACK packet without RDPUDP_FLAG_SYN flag.
                this.TestSite.Log.Add(LogEntryKind.Comment, "expect an ACK packet without RDPUDP_FLAG_SYN flag.");
                ackpacket = WaitForACKPacket(transportMode, waitTime, null, 0, RDPUDP_FLAG.RDPUDP_FLAG_CN);
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK packet without RDPUDP_FLAG_SYN flag, transport mode is {0}", transportMode);
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Verify SYN packet.
        /// </summary>
        /// <param name="synPacket">The SYN packet.</param>
        /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param>
        private void VerifySYNPacket(RdpeudpPacket synPacket, TransportMode udpTransportMode)
        {
            if (synPacket == null)
            {
                this.Site.Assert.Fail("The SYN Packet should not be null!");
            }

            if (synPacket.fecHeader.snSourceAck != uint.MaxValue)
            {
                this.Site.Assert.Fail("The snSourceAck variable MUST be set to -1 (max value of uint)!");
            }

            if ((synPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_SYN) == 0)
            {
                this.Site.Assert.Fail("The RDPUDP_FLAG_SYN flag MUST be set in SYN packet!");
            }

            if (udpTransportMode == TransportMode.Reliable)
            {
                if ((synPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY) == RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY)
                {
                    this.Site.Assert.Fail("The RDPUDP_FLAG_SYNLOSSY flag MUST not be set when choose reliable UDP connection!");
                }
            }
            else
            {
                if ((synPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY) == 0)
                {
                    this.Site.Assert.Fail("The RDPUDP_FLAG_SYNLOSSY flag MUST be set When choose lossy UDP connection!");
                }
            }

            if (synPacket.SynData == null)
            {
                this.Site.Assert.Fail("The SYN Packet should contain a RDPUDP_SYNDATA_PAYLOAD structure!");
            }

            if (synPacket.SynData.Value.uUpStreamMtu > 1232 || synPacket.SynData.Value.uUpStreamMtu < 1132)
            {
                this.Site.Assert.Fail("The uUpStreamMtu field MUST be set to a value in the range of 1132 to 1232.");
            }

            if (synPacket.SynData.Value.uDownStreamMtu > 1232 || synPacket.SynData.Value.uDownStreamMtu < 1132)
            {
                this.Site.Assert.Fail("The uDownStreamMtu field MUST be set to a value in the range of 1132 to 1232.");
            }
        }
        /// <summary>
        /// Get the next valid rdpeudp packet.
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: reliable or Lossy.</param>
        /// <returns>The next valid rdpeudp packet.</returns>
        private RdpeudpPacket GetNextValidUdpPacket(TransportMode udpTransportMode, byte[] data = null)
        {
            /*This function is used to get a valid rdpeudp packet.
             * Using rdpeudpSocket.LossPacket flag to control whether the socket send the packet.
             * First set rdpeudpSocket.LossPacket to true and send a tunnal Data, the socket will store the next packet(RDPEUDP socket which contains the encrypted tunnel data) and doesn't send it.
             * Then get the stored packet and return it.
             */
            RdpemtServer  rdpemtServer  = rdpemtServerR;
            RdpeudpSocket rdpeudpSocket = rdpeudpSocketR;

            if (udpTransportMode == TransportMode.Lossy)
            {
                rdpemtServer  = rdpemtServerL;
                rdpeudpSocket = rdpeudpSocketL;
            }

            if (data == null)
            {
                data = new byte[1000];
            }
            RDP_TUNNEL_DATA tunnelData = rdpemtServer.CreateTunnelDataPdu(data, null);

            byte[] unEncryptData = PduMarshaler.Marshal(tunnelData);
            byte[] encryptData   = null;

            if (udpTransportMode == TransportMode.Reliable)
            {
                RdpeudpTLSChannel secChannel = rdpemtServer.SecureChannel as RdpeudpTLSChannel;
                encryptData = secChannel.Encrypt(unEncryptData);
            }
            else
            {
                RdpeudpDTLSChannel secChannel      = rdpemtServer.SecureChannel as RdpeudpDTLSChannel;
                List <byte[]>      encryptDataList = secChannel.Encrypt(unEncryptData);
                if (encryptDataList != null && encryptDataList.Count > 0)
                {
                    encryptData = encryptDataList[0];
                }
            }

            RdpeudpPacket packet = rdpeudpSocket.CreateSourcePacket(encryptData);

            return(packet);
        }
        /// <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>
        /// Create invalid SYN and ACK Packet
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: reliable or lossy</param>
        /// <param name="invalidType">Invalid type</param>
        /// <param name="initSequenceNumber">init sequence</param>
        /// <returns></returns>
        private RdpeudpPacket CreateInvalidSynAndACKPacket(TransportMode udpTransportMode, SynAndAck_InvalidType invalidType, uint?initSequenceNumber = null)
        {
            RdpeudpServerSocket rdpeudpSocket = rdpeudpSocketR;

            if (udpTransportMode == TransportMode.Lossy)
            {
                rdpeudpSocket = rdpeudpSocketL;
            }

            // Create the SYN and ACK packet.
            RdpeudpPacket SynAndAckPacket = new RdpeudpPacket();

            SynAndAckPacket.fecHeader.snSourceAck        = rdpeudpSocket.SnSourceAck;
            SynAndAckPacket.fecHeader.uReceiveWindowSize = rdpeudpSocket.UReceiveWindowSize;
            SynAndAckPacket.fecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_SYN | RDPUDP_FLAG.RDPUDP_FLAG_ACK;


            RDPUDP_SYNDATA_PAYLOAD SynPayload = rdpeudpSocket.CreateSynData(initSequenceNumber);

            switch (invalidType)
            {
            case SynAndAck_InvalidType.LargerUpStreamMtu:
                SynPayload.uUpStreamMtu = 1232 + 1;
                break;

            case SynAndAck_InvalidType.SamllerUpStreamMtu:
                SynPayload.uUpStreamMtu = 1132 - 1;
                break;

            case SynAndAck_InvalidType.LargerDownStreamMtu:
                SynPayload.uDownStreamMtu = 1232 + 1;
                break;

            case SynAndAck_InvalidType.SamllerDownStreamMtu:
                SynPayload.uDownStreamMtu = 1132 - 1;
                break;
            }

            SynAndAckPacket.SynData = SynPayload;

            return(SynAndAckPacket);
        }
        /// <summary>
        /// Send SYN and ACK packet.
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: Reliable or Lossy</param>
        /// <param name="invalidType">invalid type</param>
        public void SendSynAndAckPacket(TransportMode udpTransportMode, SynAndAck_InvalidType invalidType, uint? initSequenceNumber = null, uUdpVer_Values? uUdpVer = null)
        {
            RdpeudpServerSocket rdpeudpSocket = rdpeudpSocketR;
            if (udpTransportMode == TransportMode.Lossy)
            {
                rdpeudpSocket = rdpeudpSocketL;
            }

            if (invalidType == SynAndAck_InvalidType.None)
            {
                // If invalid type is None, send the packet directly.
                rdpeudpSocket.SendSynAndAckPacket(initSequenceNumber, uUdpVer);
                return;
            }

            // Create the SYN and ACK packet first.
            RdpeudpPacket SynAndAckPacket = CreateInvalidSynAndACKPacket(udpTransportMode, invalidType, initSequenceNumber);

            rdpeudpSocket.SendPacket(SynAndAckPacket);
        }
        public void S2_DataTransfer_CongestionControlTest_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, "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 another three RDPUDP packet.");
                this.SendNextValidUdpPacket(transportMode);
                this.SendNextValidUdpPacket(transportMode);
                this.SendNextValidUdpPacket(transportMode);

                // Expect an ACK packet with RDPUDP_FLAG_SYN flag.
                this.TestSite.Log.Add(LogEntryKind.Comment, "expect an ACK packet with RDPUDP_FLAG_SYN flag.");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime, null, RDPUDP_FLAG.RDPUDP_FLAG_CN, 0);
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK packet with RDPUDP_FLAG_SYN flag, transport mode is {0}", transportMode);

                RdpeudpPacket packet = this.GetNextValidUdpPacket(transportMode);
                packet.fecHeader.uFlags = packet.fecHeader.uFlags | RDPUDP_FLAG.RDPUDP_FLAG_CWR;
                this.SendPacket(transportMode, packet);

                // Expect an ACK packet without RDPUDP_FLAG_SYN flag.
                this.TestSite.Log.Add(LogEntryKind.Comment, "expect an ACK packet without RDPUDP_FLAG_SYN flag.");
                ackpacket = WaitForACKPacket(transportMode, waitTime, null, 0, RDPUDP_FLAG.RDPUDP_FLAG_CN);
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK packet without RDPUDP_FLAG_SYN flag, transport mode is {0}", transportMode);
            }
        }
        public void S2_DataTransfer_ClientAckDelay()
        {
            TransportMode[] transportModeArray = new TransportMode[] { TransportMode.Reliable, TransportMode.Lossy };

            CheckPlatformCompatibility(ref transportModeArray);

            CheckSecurityProtocolForMultitransport();

            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            foreach (TransportMode transportMode in transportModeArray)
            {
                DoUntilSucceed(() =>
                {
                    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);
                    return(this.EstablishRdpemtConnection(transportMode, waitTime));
                },
                               this.waitTime * 5,
                               TimeSpan.FromSeconds(0.5),
                               "RDPEMT tunnel creation failed");


                this.TestSite.Log.Add(LogEntryKind.Comment, "Send three RDPUDP packets, wait {0} ms between each send");
                Thread.Sleep(DelayedACKTimer);
                this.SendNextValidUdpPacket(transportMode);
                Thread.Sleep(DelayedACKTimer);
                this.SendNextValidUdpPacket(transportMode);
                Thread.Sleep(DelayedACKTimer);
                this.SendNextValidUdpPacket(transportMode);

                this.TestSite.Log.Add(LogEntryKind.Comment, "Expect RDP client to send an ACK packet with flag: RDPUDP_FLAG_ACKDELAYED");
                RdpeudpPacket ackpacket = WaitForACKPacket(transportMode, waitTime, null, RDPUDP_FLAG.RDPUDP_FLAG_ACKDELAYED);
                Site.Assert.IsNotNull(ackpacket, "Client should send an ACK with RDPUDP_FLAG_ACKDELAYED flag. Transport mode is {0}", transportMode);
            }
        }
Esempio n. 20
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="eudpSocket">A RdpeudpSocket used for transport</param>
        public RdpeudpTLSChannel(RdpeudpSocket eudpSocket)
        {
            if (eudpSocket == null || eudpSocket.TransMode == TransportMode.Lossy)
            {
                throw new NotSupportedException("RdpeudpSocket is null or it is a socket for Lossy RDPEUDP connection.");
            }
            this.rdpeudpSocket           = eudpSocket;
            this.rdpeudpSocket.Received += ReceiveBytes;
            innerStream     = new SSLInnerStream();
            isAuthenticated = false;

            if (eudpSocket.AutoHandle)
            {
                // Check whether there is packets in unprocessed packet buffer

                RdpeudpPacket packet = eudpSocket.ExpectPacket(shortWaitTime);
                if (packet != null)
                {
                    eudpSocket.ReceivePacket(packet);
                }
            }
        }
        /// <summary>
        /// Get the First valid UDP Source Packet.
        /// </summary>
        /// <param name="udpTransportMode"></param>
        /// <returns></returns>
        private RdpeudpPacket GetFirstValidUdpPacket(TransportMode udpTransportMode)
        {
            byte[]           dataToSent  = null;
            RdpeudpPacket    firstPacket = null;
            String           certFile    = this.Site.Properties["CertificatePath"];
            String           certPwd     = this.Site.Properties["CertificatePassword"];
            X509Certificate2 cert        = new X509Certificate2(certFile, certPwd);

            if (udpTransportMode == TransportMode.Reliable)
            {
                RdpeudpTLSChannel secChannel = new RdpeudpTLSChannel(rdpeudpSocketR);
                secChannel.AuthenticateAsServer(cert);
                RdpeudpPacket packet = rdpeudpSocketR.ExpectPacket(waitTime);
                if (packet.payload != null)
                {
                    rdpeudpSocketR.ProcessSourceData(packet); // Process Source Data to makesure ACK Vector created next is correct
                    secChannel.ReceiveBytes(packet.payload);
                }
                dataToSent  = secChannel.GetDataToSent(waitTime);
                firstPacket = rdpeudpSocketR.CreateSourcePacket(dataToSent);
            }
            else
            {
                RdpeudpDTLSChannel secChannel = new RdpeudpDTLSChannel(rdpeudpSocketL);
                secChannel.AuthenticateAsServer(cert);
                RdpeudpPacket packet = rdpeudpSocketL.ExpectPacket(waitTime);
                if (packet.payload != null)
                {
                    rdpeudpSocketL.ProcessSourceData(packet); // Process Source Data to makesure ACK Vector created next is correct
                    secChannel.ReceiveBytes(packet.payload);
                }
                dataToSent  = secChannel.GetDataToSent(waitTime);
                firstPacket = rdpeudpSocketL.CreateSourcePacket(dataToSent);
            }

            return(firstPacket);
        }
        public void S2_DataTransfer_RetransmitTest_ClientRetransmit()
        {
            // Record the sequenceNumber of the lost source packet.
            uint   sequenceNumberForLossPacket = 0;
            ushort receiveWindowSize           = 0;

            Site.Log.Add(LogEntryKind.Debug, "Establishing RDP connection ...");
            StartRDPConnection();

            this.TestSite.Log.Add(LogEntryKind.Comment, "Create a reliable UDP connection.");
            this.EstablishUDPConnection(TransportMode.Reliable, waitTime, true);

            this.TestSite.Log.Add(LogEntryKind.Comment, "Send the first RDPEUDP Source packet, but not acknowledge the receipt of the first source packet from client.");
            RdpeudpPacket packet = this.GetFirstValidUdpPacket(TransportMode.Reliable);

            #region Change packet.ackVectorHeader To Not Acknowledge The Receipt

            RDPUDP_ACK_VECTOR_HEADER ackVectorHeader = new RDPUDP_ACK_VECTOR_HEADER();
            ackVectorHeader.AckVectorElement = null;
            ackVectorHeader.uAckVectorSize   = 0;
            packet.ackVectorHeader           = ackVectorHeader;
            sequenceNumberForLossPacket      = packet.fecHeader.snSourceAck;
            receiveWindowSize = packet.fecHeader.uReceiveWindowSize;
            packet.fecHeader.snSourceAck--;

            #endregion Change packet.ackVectorHeader To Not Acknowledge The Receipt

            this.SendPacket(TransportMode.Reliable, packet);

            this.TestSite.Log.Add(LogEntryKind.Comment, "Wait for 200 ms so as to fire the retransmit timer.");
            Thread.Sleep(this.RetransmitTimer);

            this.TestSite.Log.Add(LogEntryKind.Comment, "Wait for the client to resend the lost packet.");
            RdpeudpPacket receivedPacket = this.WaitForSourcePacket(TransportMode.Reliable, waitTime, sequenceNumberForLossPacket);
            Site.Assert.IsNotNull(receivedPacket, "Client should resend the packet if not receiving an ACK for a specified time.");
        }
Esempio n. 23
0
        /// <summary>
        /// Establish a UDP connection.
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: Reliable or Lossy.</param>
        /// <param name="timeout">Wait time.</param>
        /// <param name="verifyPacket">Whether verify the received packet.</param>
        /// <returns>The accepted socket.</returns>
        private RdpeudpSocket EstablishUDPConnection(TransportMode udpTransportMode, TimeSpan timeout, bool verifyPacket = false, bool autoHanlde = false)
        {
            // Start UDP listening.
            if (rdpeudpServer == null)
            {
                rdpeudpServer = new RdpeudpServer((IPEndPoint)this.rdpbcgrAdapter.SessionContext.LocalIdentity, autoHanlde);
            }
            if (!rdpeudpServer.Running)
            {
                rdpeudpServer.Start();
            }

            // Send a Server Initiate Multitransport Request PDU.
            byte[] securityCookie = new byte[16];
            Random rnd            = new Random();

            rnd.NextBytes(securityCookie);
            Multitransport_Protocol_value requestedProtocol = Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECR;

            if (udpTransportMode == TransportMode.Lossy)
            {
                requestedProtocol = Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL;
            }
            this.rdpbcgrAdapter.SendServerInitiateMultitransportRequestPDU(++this.multitransportRequestId, requestedProtocol, securityCookie);

            // Create a UDP socket.
            RdpeudpServerSocket rdpudpSocket = rdpeudpServer.CreateSocket(((IPEndPoint)this.rdpbcgrAdapter.SessionContext.Identity).Address, udpTransportMode, timeout);

            if (rdpudpSocket == null)
            {
                this.Site.Assert.Fail("Failed to create a UDP socket for the Client : {0}", ((IPEndPoint)this.rdpbcgrAdapter.SessionContext.Identity).Address);
            }

            if (udpTransportMode == TransportMode.Reliable)
            {
                this.rdpeudpSocketR = rdpudpSocket;
            }
            else
            {
                this.rdpeudpSocketL = rdpudpSocket;
            }

            // Expect a SYN packet.
            RdpeudpPacket synPacket = rdpudpSocket.ExpectSynPacket(timeout);

            if (synPacket == null)
            {
                this.Site.Assert.Fail("Time out when waiting for the SYN packet");
            }

            // Verify the SYN packet.
            if (verifyPacket)
            {
                VerifySYNPacket(synPacket, udpTransportMode);
            }

            // Send a SYN and ACK packet.
            SendSynAndAckPacket(udpTransportMode, SynAndAck_InvalidType.None, initSequenceNumber);


            // Expect an ACK packet or ACK and Source Packet.
            RdpeudpPacket ackPacket = rdpudpSocket.ExpectACKPacket(timeout);

            if (ackPacket == null)
            {
                this.Site.Assert.Fail("Time out when waiting for the ACK packet to response the ACK and SYN packet");
            }

            // Verify the ACK packet.
            if (verifyPacket)
            {
                VerifyACKPacket(ackPacket);
            }

            // If the packet is an ACK and Source Packet, add the source packet to the un-processed packet.
            if (ackPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA))
            {
                byte[]            bytes       = PduMarshaler.Marshal(ackPacket, false);
                RdpeudpBasePacket stackpacket = new RdpeudpBasePacket(bytes);
                rdpudpSocket.ReceivePacket(stackpacket);
            }

            rdpudpSocket.Connected = true;

            return(rdpudpSocket);
        }
        /// <summary>
        /// Verify SYN packet.
        /// </summary>
        /// <param name="synPacket">The SYN packet.</param>
        /// <param name="udpTransportMode">Transport mode: reliable or lossy.</param>
        private void VerifySYNPacket(RdpeudpPacket synPacket, TransportMode udpTransportMode)
        {

            if (synPacket == null)
            {
                this.Site.Assert.Fail("The SYN Packet should not be null!");
            }

            if (synPacket.fecHeader.snSourceAck != uint.MaxValue)
            {
                this.Site.Assert.Fail("The snSourceAck variable MUST be set to -1 (max value of uint)!");
            }

            if ((synPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_SYN) == 0)
            {
                this.Site.Assert.Fail("The RDPUDP_FLAG_SYN flag MUST be set in SYN packet!");
            }

            if (udpTransportMode == TransportMode.Reliable)
            {
                if ((synPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY) == RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY)
                {
                    this.Site.Assert.Fail("The RDPUDP_FLAG_SYNLOSSY flag MUST not be set when choose reliable UDP connection!");
                }
            }
            else
            {
                if ((synPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY) == 0)
                {
                    this.Site.Assert.Fail("The RDPUDP_FLAG_SYNLOSSY flag MUST be set When choose lossy UDP connection!");
                }
            }

            if (synPacket.SynData == null)
            {
                this.Site.Assert.Fail("The SYN Packet should contain a RDPUDP_SYNDATA_PAYLOAD structure!");
            }

            if (synPacket.SynData.Value.uUpStreamMtu > 1232 || synPacket.SynData.Value.uUpStreamMtu < 1132)
            {
                this.Site.Assert.Fail("The uUpStreamMtu field MUST be set to a value in the range of 1132 to 1232.");
            }

            if (synPacket.SynData.Value.uDownStreamMtu > 1232 || synPacket.SynData.Value.uDownStreamMtu < 1132)
            {
                this.Site.Assert.Fail("The uDownStreamMtu field MUST be set to a value in the range of 1132 to 1232.");
            }

            // The RDPUDP_FLAG_SYNEX flag and RDPUDP_SYNDATAEX_PAYLOAD structure should appear at the same time.
            if ((synPacket.SynDataEx == null) ^ ((synPacket.fecHeader.uFlags & RDPUDP_FLAG.RDPUDP_FLAG_SYNEX) == 0))
            {
                this.Site.Assert.Fail("Section 3.1.5.1.1: The RDPUDP_FLAG_SYNEX flag MUST be set only when the RDPUDP_SYNDATAEX_PAYLOAD structure is included. Section 3.1.5.1.1: The RDPUDP_SYNEX_PAYLOAD structure MUST be appended to the UDP datagram if the RDPUDP_FLAG_SYNEX flag is set in uFlags.");
            }

            //Section 3.1.5.1.1: Not appending RDPUDP_SYNDATAEX_PAYLOAD structure implies that RDPUDP_PROTOCOL_VERSION_1 is the highest protocol version supported. 
            if (synPacket.SynDataEx == null)
            {
                this.clientUUdpVer = uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_1;
                this.clientRdpudpVerfionInfoValidFlag = null;
            }
            else
            {
                this.clientUUdpVer = synPacket.SynDataEx.Value.uUdpVer;
                this.clientRdpudpVerfionInfoValidFlag = synPacket.SynDataEx.Value.uSynExFlags;

                //Section 3.1.5.1.1: The RDPUDP_VERSION_INFO_VALID flag MUST be set only if the structure contains a valid RDP-UDP protocol version.
                if (synPacket.SynDataEx.Value.uSynExFlags.HasFlag(uSynExFlags_Values.RDPUDP_VERSION_INFO_VALID) && ((int)synPacket.SynDataEx.Value.uUdpVer & 0xfffc) != 0)
                {
                    this.Site.Assert.Fail("Section 3.1.5.1.1: The RDPUDP_VERSION_INFO_VALID flag MUST be set only if the structure contains a valid RDP-UDP protocol version");
                }

            }
        }
        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);
            }
        }
        /// <summary>
        /// Establish a UDP connection.
        /// </summary>
        /// <param name="udpTransportMode">Transport mode: Reliable or Lossy.</param>
        /// <param name="timeout">Wait time.</param>
        /// <param name="verifyPacket">Whether verify the received packet.</param>
        /// <returns>The accepted socket.</returns>
        private RdpeudpSocket EstablishUDPConnection(TransportMode udpTransportMode, TimeSpan timeout, bool verifyPacket = false, bool autoHanlde = false, uUdpVer_Values? uUdpVer = null)
        {
            // Start UDP listening.
            if (rdpeudpServer == null)
            {
                rdpeudpServer = new RdpeudpServer((IPEndPoint)this.rdpbcgrAdapter.SessionContext.LocalIdentity, autoHanlde);

                rdpeudpServer.UnhandledExceptionReceived += (ex) =>
                {
                    Site.Log.Add(LogEntryKind.Debug, $"Unhandled exception from RdpeudpServer: {ex}");
                };
            }
            if (!rdpeudpServer.Running)
                rdpeudpServer.Start();

            // Send a Server Initiate Multitransport Request PDU.
            byte[] securityCookie = new byte[16];
            Random rnd = new Random();
            rnd.NextBytes(securityCookie);
            Multitransport_Protocol_value requestedProtocol = Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECR;
            if (udpTransportMode == TransportMode.Lossy)
            {
                requestedProtocol = Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL;
            }
            this.rdpbcgrAdapter.SendServerInitiateMultitransportRequestPDU(++this.multitransportRequestId, requestedProtocol, securityCookie);

            // Create a UDP socket.
            RdpeudpServerSocket rdpudpSocket = rdpeudpServer.CreateSocket(((IPEndPoint)this.rdpbcgrAdapter.SessionContext.Identity).Address, udpTransportMode, timeout);
            if (rdpudpSocket == null)
            {
                this.Site.Assert.Fail("Failed to create a UDP socket for the Client : {0}", ((IPEndPoint)this.rdpbcgrAdapter.SessionContext.Identity).Address);
            }

            if (udpTransportMode == TransportMode.Reliable)
            {
                this.rdpeudpSocketR = rdpudpSocket;
            }
            else
            {
                this.rdpeudpSocketL = rdpudpSocket;
            }

            // Expect a SYN packet.
            RdpeudpPacket synPacket = rdpudpSocket.ExpectSynPacket(timeout);
            if (synPacket == null)
            {
                this.Site.Assert.Fail("Time out when waiting for the SYN packet");
            }

            // Verify the SYN packet.
            if (verifyPacket)
            {
                VerifySYNPacket(synPacket, udpTransportMode);
            }

            // Send a SYN and ACK packet.
            if (this.clientRdpudpVerfionInfoValidFlag == uSynExFlags_Values.RDPUDP_VERSION_INFO_VALID)
            {
                //Section 3.1.5.1.3: The uUdpVer field MUST be set to the highest RDP-UDP protocol version supported by both endpoints. 
                uUdpVer = uUdpVer > this.clientUUdpVer ? this.clientUUdpVer : uUdpVer;
                SendSynAndAckPacket(udpTransportMode, SynAndAck_InvalidType.None, initSequenceNumber, uUdpVer);
            }
            else if (this.clientRdpudpVerfionInfoValidFlag == uSynExFlags_Values.None)
            {
                //Section 3.1.5.1.3: The highest version supported by both endpoints, which is RDPUDP_PROTOCOL_VERSION_1 if either this packet or the SYN packet does not specify a version, is the version that MUST be used by both endpoints.
                SendSynAndAckPacket(udpTransportMode, SynAndAck_InvalidType.None, initSequenceNumber, uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_1);
            }
            else
            {
                //Section 3.1.5.1.3: The RDPUDP_SYNEX_PAYLOAD structure (section 2.2.2.9) SHOULD only be present if it is also present in the received SYN packet. 
                // When the 
                SendSynAndAckPacket(udpTransportMode, SynAndAck_InvalidType.None, initSequenceNumber, null);
            }


            // Expect an ACK packet or ACK and Source Packet.
            RdpeudpPacket ackPacket = rdpudpSocket.ExpectACKPacket(timeout);
            if (ackPacket == null)
            {
                this.Site.Assert.Fail("Time out when waiting for the ACK packet to response the ACK and SYN packet");
            }

            // Verify the ACK packet.
            if (verifyPacket)
            {
                VerifyACKPacket(ackPacket);
            }

            // If the packet is an ACK and Source Packet, add the source packet to the un-processed packet.
            if (ackPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA))
            {
                byte[] bytes = PduMarshaler.Marshal(ackPacket, false);
                RdpeudpBasePacket stackpacket = new RdpeudpBasePacket(bytes);
                rdpudpSocket.ReceivePacket(stackpacket);
            }

            rdpudpSocket.Connected = true;

            return rdpudpSocket;
        }