The base packet type for Rdpeudp.
Inheritance: Microsoft.Protocols.TestTools.StackSdk.BasePDU
示例#1
0
        /// <summary>
        /// Send Data from this specified UDP transport
        /// </summary>
        /// <param name="data">Data to send</param>
        /// <returns>Return true if send success</returns>
        public bool Send(byte[] data)
        {
            if (!Connected)
            {
                return(false);
            }
            List <byte> dataList      = new List <byte>(data);
            int         payloadLength = 0;

            byte[]        packetData;
            RdpeudpPacket packet;

            do
            {
                packet = new RdpeudpPacket();                  // Fill in the common header.
                packet.fecHeader.snSourceAck        = SnSourceAck;
                packet.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
                packet.fecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_DATA | RDPUDP_FLAG.RDPUDP_FLAG_ACK;
                packet.ackVectorHeader = CreateAckVectorHeader();

                packet.sourceHeader = CreateSourcePayloadHeader();   // Generate SourceHeader.

                packetData    = PduMarshaler.Marshal(packet, false); // Measure the header lenght to figure out payload length.
                payloadLength = Math.Min(UUpStreamMtu - packetData.Length, dataList.Count);

                packet.payload = new byte[payloadLength];
                dataList.CopyTo(0, packet.payload, 0, payloadLength);   // Copy the data in to packet payload.

                string str = System.Text.Encoding.ASCII.GetString(packet.payload);
                SendPacket(packet);
                dataList.RemoveRange(0, payloadLength);
            } while (dataList.Count > 0);

            return(true);
        }
示例#2
0
        /// <summary>
        /// Expect a SYN and ACK Packet
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public RdpeudpPacket ExpectSynAndAckPacket(TimeSpan timeout)
        {
            if (Connected)
            {
                return(null);
            }
            DateTime endtime = DateTime.Now + timeout;

            while (DateTime.Now < endtime)
            {
                lock (unProcessedPacketBuffer)
                {
                    for (int i = 0; i < unProcessedPacketBuffer.Count; i++)
                    {
                        RdpeudpPacket eudpPacket = unProcessedPacketBuffer[i];
                        if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN) &&
                            eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK))
                        {
                            unProcessedPacketBuffer.RemoveAt(i);

                            // Analyse the SYN packet.
                            ProcessSynPacket(eudpPacket);

                            return(eudpPacket);
                        }
                    }
                }
                // If not receive a Packet, wait a while
                Thread.Sleep(RdpeudpSocketConfig.ReceivingInterval);
            }
            return(null);
        }
示例#3
0
        /// <summary>
        /// Process Source payload if the packet has source payload data
        /// </summary>
        /// <param name="eudpPacket"></param>
        public void ProcessSourceData(RdpeudpPacket eudpPacket)
        {
            if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA) && !eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC))
            {
                lock (inPacketDic)
                {
                    if (IsInReceiveWindow(eudpPacket.sourceHeader.Value.snSourceStart))
                    {
                        SnSourceAck = Math.Max(SnSourceAck, eudpPacket.sourceHeader.Value.snSourceStart);
                        InPacketState inPacketState = new InPacketState();
                        inPacketState.Packet = eudpPacket;
                        inPacketDic[eudpPacket.sourceHeader.Value.snSourceStart] = inPacketState;

                        UpdateReceiveWindow();
                    }

                    // Increase received source packet numbers not be ack
                    if (sourceNumNotAcked == 0)
                    {
                        ReceiveTimeForFirstNotACKSource = DateTime.Now;
                    }
                    sourceNumNotAcked++;
                }
                // Send ACK diagram if necessary.
                AckPacketReceived();
            }
        }
示例#4
0
        /// <summary>
        /// Method used to process a received packet
        /// </summary>
        /// <param name="packet"></param>
        public void ReceivePacket(RdpeudpPacket eudpPacket)
        {
            // Update last receive time, which is used for keep alive timer
            LastReceiveDiagramTime = DateTime.Now;

            Monitor.Enter(receiveLock);

            if (!connected || !AutoHandle)
            {
                // If connection haven't been setuped, or Auto handle is false, this packet will not be processed automatically by this method.
                // It will buffer it for others to use it.
                lock (unProcessedPacketBuffer) unProcessedPacketBuffer.Add(eudpPacket);
            }
            else
            {
                // Process the received packet
                // In case the advised window size updated
                URemoteAdvisedWindowSize = eudpPacket.fecHeader.uReceiveWindowSize;
                // this value should update when receiving ACK if congestion algorithm is implemented
                USendWindowSize = URemoteAdvisedWindowSize;
                // Process Ack Vector Header if the packet contained
                ProcessAckVectorHeader(eudpPacket);
                // Process Source Data if the packet contained
                ProcessSourceData(eudpPacket);
                // Process FEC Payload data if the packet contained
                ProcessFECPayloadData(eudpPacket);
                // Process RDPUDP_ACK_OF_ACKVECTOR_HEADER Structure if the packet contained
                ProcessAckOfAckVectorHeader(eudpPacket);

                //TODO: Congestion control function
            }
            Monitor.Exit(receiveLock);
        }
示例#5
0
 /// <summary>
 /// Process RDPUDP_ACK_OF_ACKVECTOR_HEADER Structure if the packet have
 /// </summary>
 /// <param name="eudpPacket"></param>
 public void ProcessAckOfAckVectorHeader(RdpeudpPacket eudpPacket)
 {
     if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS))
     {
         InSnAckOfAcksSeqNum = eudpPacket.ackOfAckVector.Value.snAckOfAcksSeqNum;
     }
 }
示例#6
0
        /// <summary>
        /// Send SYN Packet to init a RDPEUDP Connection
        /// </summary>
        /// <param name="initSequenceNumber">Specify a snInitialSequenceNumber</param>
        /// <returns></returns>
        public bool SendSynPacket(uint?initSequenceNumber = null, RDPUDP_PROTOCOL_VERSION?version = null)
        {
            if (Connected)
            {
                return(false);
            }

            RdpeudpPacket synPacket = new RdpeudpPacket();

            synPacket.FecHeader.snSourceAck        = UInt32.MaxValue;
            synPacket.FecHeader.uReceiveWindowSize = UReceiveWindowSize;
            synPacket.FecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_SYN;
            if (this.TransMode == TransportMode.Lossy)
            {
                synPacket.FecHeader.uFlags |= RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY;
            }
            synPacket.SynData = CreateSynData(initSequenceNumber);
            if (version.HasValue)
            {
                synPacket.FecHeader.uFlags |= RDPUDP_FLAG.RDPUDP_FLAG_SYNEX;
                var synDataEx = CreateSynExData((RDPUDP_PROTOCOL_VERSION)version);
                if (version.Value == RDPUDP_PROTOCOL_VERSION.RDPUDP_PROTOCOL_VERSION_3)
                {
                    synDataEx.cookieHash = cookieHash;
                }
                synPacket.SynDataEx = synDataEx;
            }
            SendPacket(synPacket);
            // Set the OutSnResetSeqNum value, number from which the receive thread decoding the state of the send packet.
            OutSnResetSeqNum = synPacket.SynData.Value.snInitialSequenceNumber + 1;
            return(true);
        }
示例#7
0
 /// <summary>
 /// Process RDPUDP_FEC_PAYLOAD_HEADER Structure and FEC Payload
 /// </summary>
 /// <param name="eudpPacket"></param>
 public void ProcessFECPayloadData(RdpeudpPacket eudpPacket)
 {
     if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC))
     {
         // TODO: process FEC payload, calculate lost packet with FEC data
         // then use UpdateReceiveWindow function to update window and process received data
     }
 }
示例#8
0
        /// <summary>
        /// Process RDPUDP_ACK_VECTOR_HEADER if the packet contains a RDPUDP_ACK_VECTOR_HEADER
        /// </summary>
        /// <param name="eudpPacket"></param>
        private void ProcessAckVectorHeader(RdpeudpPacket eudpPacket)
        {
            // Update OutSnAckOfAcksSeqNum if necessary
            UpdateOutSnAckOfAcksSeqNum(eudpPacket.fecHeader.snSourceAck);

            if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK) && !eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN))
            {
                //Contains ack, analyze ack value, update outPacketDic, caculate RTT, and move send window
                if (eudpPacket.ackVectorHeader.Value.uAckVectorSize > 0)    // Deal with ack vector.
                {
                    uint currentposition = OutSnAckOfAcksSeqNum;
                    lock (outPacketDic)
                    {
                        foreach (AckVector AckVectorElement in eudpPacket.ackVectorHeader.Value.AckVectorElement)
                        {
                            if (AckVectorElement.State == VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED)
                            {
                                // update outPacketDic only if this vector element is to ack received
                                for (byte i = 0; i < AckVectorElement.Length + 1; i++, currentposition++)
                                {
                                    if (outPacketDic.ContainsKey(currentposition))
                                    {
                                        outPacketDic[currentposition].Acknowledged = true;
                                    }
                                }
                            }
                            else
                            {
                                currentposition = currentposition + AckVectorElement.Length + 1;
                            }
                        }

                        // If this packet is not a delay ack, calculate RTT, only the last acknowleged source packet is used to caculate RTT
                        if (outPacketDic.ContainsKey(currentposition - 1))
                        {
                            if (!eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACKDELAYED) &&
                                !outPacketDic[currentposition - 1].estimatedRTT)                                                               // Also make sure this packet has not been used to estimate RTT. If the packet has been used to estimated RTT, this packet may be a resent ACK for keep alive
                            {
                                RTT = new TimeSpan(RTT.Ticks / 8 * 7 + (DateTime.Now - outPacketDic[currentposition - 1].SendTime).Ticks / 8); // Count the RTT.
                                outPacketDic[currentposition - 1].estimatedRTT = true;
                            }
                        }

                        // Update send window, this method will update outPacketDic
                        UpdateSendWindow();
                    }
                    sendWindowLock.Set();
                }
            }
        }
示例#9
0
        /// <summary>
        /// Establish Connection
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public bool Connect(TimeSpan timeout)
        {
            SendSynPacket();
            RdpeudpPacket eudpPacket = ExpectSynAndAckPacket(timeout);

            if (eudpPacket == null)
            {
                return(false);
            }
            Connected = true;
            this.SendAcKPacket();

            return(true);
        }
示例#10
0
        /// <summary>
        /// Process a Syn Packet
        /// </summary>
        /// <param name="eudpPacket"></param>
        public void ProcessSynPacket(RdpeudpPacket eudpPacket)
        {
            if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN) ||
                eudpPacket.fecHeader.uFlags.Equals(RDPUDP_FLAG.RDPUDP_FLAG_SYN | RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY))    // Make sure this packet is a SYN Packet
            {
                UDownStreamMtu  = (ushort)(Math.Min(Math.Min(eudpPacket.SynData.Value.uUpStreamMtu, UDownStreamMtu), (ushort)1232));
                UUpStreamMtu    = (ushort)(Math.Min(Math.Min(eudpPacket.SynData.Value.uDownStreamMtu, UUpStreamMtu), (ushort)1232));
                USendWindowSize = eudpPacket.fecHeader.uReceiveWindowSize;
                TransMode       = eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY) ? TransportMode.Lossy : TransportMode.Reliable;
                SnSourceAck     = eudpPacket.SynData.Value.snInitialSequenceNumber;

                InSnAckOfAcksSeqNum        = eudpPacket.SynData.Value.snInitialSequenceNumber + 1;
                ReceiveWindowStartPosition = eudpPacket.SynData.Value.snInitialSequenceNumber + 1;
            }
        }
示例#11
0
        /// <summary>
        /// Expect a SYN and ACK Packet
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public RdpeudpPacket ExpectSynAndAckPacket(TimeSpan timeout)
        {
            if (Connected)
            {
                return(null);
            }

            DateTime endtime = DateTime.Now + timeout;

            while (DateTime.Now < endtime)
            {
                // Lock the ReceivePacket method if it is transferring to RDPEUDP2 to avoid processing RDPEUDP2 packets with the RDPEUDP logic.
                lock (receiveLock)
                {
                    for (int i = 0; i < unprocessedPacketBuffer.Count; i++)
                    {
                        RdpeudpPacket eudpPacket = unprocessedPacketBuffer[i];
                        if (eudpPacket.FecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN) &&
                            eudpPacket.FecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK))
                        {
                            unprocessedPacketBuffer.RemoveAt(i);

                            if (eudpPacket.SynDataEx.HasValue)
                            {
                                if (eudpPacket.SynDataEx.Value.uUdpVer == RDPUDP_PROTOCOL_VERSION.RDPUDP_PROTOCOL_VERSION_3)
                                {
                                    upgradedToRdpedup2 = true;
                                    DisposeTimers();
                                    rdpeudp2Handler = new Rdpeudp2ProtocolHandler(AutoHandle, SendBytesByUdp, Close, ReceiveDataOnHigherLayer);
                                    rdpeudp2Handler.SocketConfig.RetransmitDuration    = RTT * 2;
                                    rdpeudp2Handler.SocketConfig.DelayedAckTimeoutInMs = (int)(RTT.TotalMilliseconds / 2);
                                    return(eudpPacket);
                                }
                            }

                            // Analyse the SYN packet.
                            ProcessSynPacket(eudpPacket);

                            return(eudpPacket);
                        }
                    }
                }

                // If not receive a Packet, wait a while
                Thread.Sleep(RdpeudpSocketConfig.ReceivingInterval);
            }
            return(null);
        }
示例#12
0
        /// <summary>
        /// Send a SYN and ACK diagram
        /// </summary>
        /// <param name="initSequenceNumber">Specify an initial sequence number</param>
        /// <returns></returns>
        public bool SendSynAndAckPacket(uint?initSequenceNumber = null)
        {
            if (Connected)
            {
                return(false);
            }
            RdpeudpPacket SynAndAckPacket = new RdpeudpPacket();

            SynAndAckPacket.fecHeader.snSourceAck        = SnSourceAck;
            SynAndAckPacket.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
            SynAndAckPacket.fecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_SYN | RDPUDP_FLAG.RDPUDP_FLAG_ACK;
            SynAndAckPacket.SynData = CreateSynData(initSequenceNumber);
            SendPacket(SynAndAckPacket);
            // Set the OutSnAckOfAcksSeqNum value, number from which the receive thread decoding the state of the send packet.
            OutSnAckOfAcksSeqNum = SynAndAckPacket.SynData.Value.snInitialSequenceNumber + 1;
            return(true);
        }
示例#13
0
        /// <summary>
        /// Create a RdpeudpServerSocket
        /// The socket can only be created if the RdpeudpServer received corresponding SYN Packet
        /// </summary>
        /// <param name="remoteIP">IP adress</param>
        /// <param name="mode">connection mode</param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public RdpeudpServerSocket CreateSocket(IPAddress remoteIP, TransportMode mode, TimeSpan timeout)
        {
            IPEndPoint    remoteEndPoint;
            RdpeudpPacket synPacket = ExpectSyncPacket(remoteIP, mode, timeout, out remoteEndPoint);

            if (synPacket == null)
            {
                return(null);
            }

            RdpeudpServerSocket serverSock = new RdpeudpServerSocket(mode, remoteEndPoint, AutoHandle, packetsender, this);

            serverSock.ReceivePacket(synPacket);

            serverSocketDic[remoteEndPoint] = serverSock;
            return(serverSock);
        }
示例#14
0
        /// <summary>
        /// Send a RDPEUDP Packet
        /// </summary>
        /// <param name="packet"></param>
        /// <returns></returns>
        public bool SendPacket(RdpeudpPacket packet)
        {
            if (packet.sourceHeader.HasValue && AutoHandle)
            {                                 // Deal with window area.
                OutPacketState packetState = new OutPacketState();
                packetState.Packet       = packet;
                packetState.Acknowledged = false;


                DateTime endTime           = DateTime.Now + this.SocketConfig.Timeout;
                uint     sendWindowsEndPos = SendWindowStartPosition + USendWindowSize;

                while (DateTime.Now < endTime)
                {
                    //If source sequence number is in send slide window, send the packet. Otherwise, wait a sendingInterval
                    if (!IsInSendWindow(packet.sourceHeader.Value.snSourceStart))
                    {
                        sendWindowLock.WaitOne(this.SocketConfig.sendingInterval);
                    }
                    else
                    {
                        break;
                    }
                }
                if (DateTime.Now > endTime)
                {
                    // Time out.
                    return(false);
                }

                packetState.SendTime = DateTime.Now;
                lock (outPacketDic) outPacketDic[packet.sourceHeader.Value.snSourceStart] = packetState;

                // Add RDPUDP_ACK_OF_ACKVECTOR_HEADER Structure if necessary
                UpdateOutSnAckOfAcksSeqNum(packet);
            }

            byte[] data = PduMarshaler.Marshal(packet, false);
            SendBytesByUDP(data);

            // Update Last send time, which is used for keep alive timer
            LastSendDiagramTime = DateTime.Now;

            return(true);
        }
示例#15
0
        /// <summary>
        /// Create Source Packet from byte data
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public RdpeudpPacket CreateSourcePacket(byte[] data)
        {
            if (data == null || data.Length == 0)
            {
                return(null);
            }

            RdpeudpPacket packet = new RdpeudpPacket();                  // Fill in the common header.

            packet.fecHeader.snSourceAck        = SnSourceAck;
            packet.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
            packet.fecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_DATA | RDPUDP_FLAG.RDPUDP_FLAG_ACK;
            packet.ackVectorHeader = CreateAckVectorHeader();

            packet.sourceHeader = CreateSourcePayloadHeader();
            packet.payload      = data;
            return(packet);
        }
示例#16
0
        /// <summary>
        /// Method used to process a received packet
        /// </summary>
        /// <param name="packet"></param>
        public void ReceivePacket(StackPacket packet)
        {
            // Transfer packet to
            RdpeudpPacket eudpPacket = new RdpeudpPacket();

            byte[] packetBytes = packet.ToBytes();
            if (!PduMarshaler.Unmarshal(packetBytes, eudpPacket, false))
            {
                return;
            }

            // ETW Provider Dump Message
            string messageName = "RDPEUDP:ReceivedPDU";

            ExtendedLogger.DumpMessage(messageName, DumpLevel_LayerTLS, eudpPacket.GetType().Name, packetBytes);

            ReceivePacket(eudpPacket);
        }
示例#17
0
 /// <summary>
 /// Used during sending source packet, Add RDPUDP_ACK_OF_ACKVECTOR_HEADER structure into the packet to update OutSnAckOfAcksSeqNum
 /// </summary>
 /// <param name="eudpPacket">Packet to be sent</param>
 private void UpdateOutSnAckOfAcksSeqNum(RdpeudpPacket eudpPacket)
 {
     if (newOutSnAckOfAcksSeqNum == null &&
         SendWindowStartPosition - 1 - OutSnAckOfAcksSeqNum > this.SocketConfig.changeSnAckOfAcksSeqNumInterval)
     {
         Monitor.Enter(updateAckOfAckLock);
         if (newOutSnAckOfAcksSeqNum == null &&
             SendWindowStartPosition - 1 - OutSnAckOfAcksSeqNum > this.SocketConfig.changeSnAckOfAcksSeqNumInterval)
         {
             newOutSnAckOfAcksSeqNum = SendWindowStartPosition - 1;
             RDPUDP_ACK_OF_ACKVECTOR_HEADER ackOfAckVector = new RDPUDP_ACK_OF_ACKVECTOR_HEADER();
             ackOfAckVector.snAckOfAcksSeqNum = newOutSnAckOfAcksSeqNum.Value;
             eudpPacket.ackOfAckVector        = ackOfAckVector;
             eudpPacket.fecHeader.uFlags      = RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS | eudpPacket.fecHeader.uFlags;
             seqNumofPacketWithAckOfAckVector = eudpPacket.sourceHeader.Value.snSourceStart;
         }
         Monitor.Exit(updateAckOfAckLock);
     }
 }
示例#18
0
        /// <summary>
        /// Establish Connection
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public bool Connect(TimeSpan timeout)
        {
            SendSynPacket();
            RdpeudpPacket eudpPacket = ExpectSynAndAckPacket(timeout);

            if (eudpPacket == null)
            {
                return(false);
            }

            Connected = true;

            if (!upgradedToRdpedup2)
            {
                this.SendAckPacket();
            }

            return(true);
        }
示例#19
0
        public RdpeudpPacket ExpectPacket(TimeSpan timeout)
        {
            DateTime endtime = DateTime.Now + timeout;

            while (DateTime.Now < endtime)
            {
                lock (unProcessedPacketBuffer)
                {
                    if (unProcessedPacketBuffer.Count > 0)
                    {
                        RdpeudpPacket eudpPacket = unProcessedPacketBuffer[0];
                        unProcessedPacketBuffer.RemoveAt(0);
                        return(eudpPacket);
                    }
                }
                // If not receive a Packet, wait a while
                Thread.Sleep(RdpeudpSocketConfig.ReceivingInterval);
            }
            return(null);
        }
示例#20
0
        /// <summary>
        /// Send SYN Packet to init a RDPEUDP Connection
        /// </summary>
        /// <param name="initSequenceNumber">Specify a snInitialSequenceNumber</param>
        /// <returns></returns>
        public bool SendSynPacket(uint?initSequenceNumber = null)
        {
            if (Connected)
            {
                return(false);
            }
            RdpeudpPacket SynAndAckPacket = new RdpeudpPacket();

            SynAndAckPacket.fecHeader.snSourceAck        = UInt32.MaxValue;
            SynAndAckPacket.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
            SynAndAckPacket.fecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_SYN;
            if (this.TransMode == TransportMode.Lossy)
            {
                SynAndAckPacket.fecHeader.uFlags |= RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY;
            }
            SynAndAckPacket.SynData = CreateSynData(initSequenceNumber);
            SendPacket(SynAndAckPacket);
            // Set the OutSnAckOfAcksSeqNum value, number from which the receive thread decoding the state of the send packet.
            OutSnAckOfAcksSeqNum = SynAndAckPacket.SynData.Value.snInitialSequenceNumber + 1;
            return(true);
        }
示例#21
0
        public bool RetransmitPacket(RdpeudpPacket packet)
        {
            if (!connected ||
                packet.sourceHeader == null)
            {
                return(false);
            }

            if (!outPacketDic.ContainsKey(packet.sourceHeader.Value.snSourceStart))
            {
                return(false);
            }

            if (outPacketDic[packet.sourceHeader.Value.snSourceStart].retransmitTimes >= this.SocketConfig.retransmitLimit)
            {
                //If a datagram has been retransmitted four times without a response, the sender terminates the connection
                this.Close();
            }
            RDPUDP_SOURCE_PAYLOAD_HEADER sourceHeader = packet.sourceHeader.Value;

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

            byte[] data = PduMarshaler.Marshal(packet, false);
            SendBytesByUDP(data);

            lock (outPacketDic)         // Deal with outPacketDic and retransmit packet.
            {
                if (outPacketDic.ContainsKey(packet.sourceHeader.Value.snSourceStart))
                {
                    outPacketDic[packet.sourceHeader.Value.snSourceStart].retransmitTimes++;
                    outPacketDic[packet.sourceHeader.Value.snSourceStart].SendTime = DateTime.Now;
                }
            }
            return(true);
        }
示例#22
0
        /// <summary>
        /// Send an ACK Datagrams
        /// </summary>
        /// <returns></returns>
        public bool SendAcKPacket(bool delayACK = false)
        {
            if (!connected)
            {
                return(false);
            }
            RdpeudpPacket AckPacket = new RdpeudpPacket();

            AckPacket.fecHeader.snSourceAck        = SnSourceAck;
            AckPacket.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
            AckPacket.fecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_ACK;

            if (delayACK)
            {
                AckPacket.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_ACK | RDPUDP_FLAG.RDPUDP_FLAG_ACKDELAYED;
            }

            AckPacket.ackVectorHeader = CreateAckVectorHeader();

            SendPacket(AckPacket);

            return(true);
        }
示例#23
0
        /// <summary>
        /// Expect a SYN Packet which is from specific remoteIP using specific connection mode
        /// </summary>
        /// <param name="remoteIP">IP address of remote endpoint</param>
        /// <param name="mode">connection mode</param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public RdpeudpPacket ExpectSyncPacket(IPAddress remoteIP, TransportMode mode, TimeSpan timeout, out IPEndPoint remoteEndPoint)
        {
            remoteEndPoint = null;
            DateTime    endtime    = DateTime.Now + timeout;
            RDPUDP_FLAG expectFlag = RDPUDP_FLAG.RDPUDP_FLAG_SYN;

            if (mode == TransportMode.Lossy)
            {
                expectFlag |= RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY;
            }
            while (DateTime.Now < endtime)
            {
                lock (this.unprocessedPacketBuffer)
                {
                    for (int i = 0; i < unprocessedPacketBuffer.Count; i++)
                    {
                        StackPacketInfo spInfo = unprocessedPacketBuffer[i];
                        remoteEndPoint = spInfo.remoteEndpoint as IPEndPoint;
                        if (remoteEndPoint.Address.Equals(remoteIP))
                        {
                            RdpeudpPacket eudpPacket = new RdpeudpPacket();
                            if (PduMarshaler.Unmarshal(spInfo.packet.ToBytes(), eudpPacket, false))
                            {
                                if (eudpPacket.fecHeader.uFlags.HasFlag(expectFlag))
                                {
                                    unprocessedPacketBuffer.RemoveAt(i);
                                    return(eudpPacket);
                                }
                            }
                        }
                    }
                }
                // If not receive a Packet, wait a while
                Thread.Sleep(RdpeudpSocketConfig.ReceivingInterval);
            }
            return(null);
        }
        /// <summary>
        /// Send a SYN and ACK diagram
        /// </summary>
        /// <param name="initSequenceNumber">Specify an initial sequence number</param>
        /// <returns></returns>
        public bool SendSynAndAckPacket(uint?initSequenceNumber = null, RDPUDP_PROTOCOL_VERSION?version = null)
        {
            if (Connected)
            {
                return(false);
            }

            // Lock the ReceivePacket method if it is transferring to RDPEUDP2 to avoid processing RDPEUDP2 packets with the RDPEUDP logic.
            lock (receiveLock)
            {
                RdpeudpPacket synAndAckPacket = new RdpeudpPacket();
                synAndAckPacket.FecHeader.snSourceAck        = SnSourceAck;
                synAndAckPacket.FecHeader.uReceiveWindowSize = UReceiveWindowSize;
                synAndAckPacket.FecHeader.uFlags             = RDPUDP_FLAG.RDPUDP_FLAG_SYN | RDPUDP_FLAG.RDPUDP_FLAG_ACK;
                if (version.HasValue)
                {
                    synAndAckPacket.FecHeader.uFlags |= RDPUDP_FLAG.RDPUDP_FLAG_SYNEX;
                    synAndAckPacket.SynDataEx         = CreateSynExData((RDPUDP_PROTOCOL_VERSION)version);
                }
                synAndAckPacket.SynData = CreateSynData(initSequenceNumber);
                SendPacket(synAndAckPacket);
                // Set the OutSnResetSeqNum value, number from which the receive thread decoding the state of the send packet.
                OutSnResetSeqNum = synAndAckPacket.SynData.Value.snInitialSequenceNumber + 1;

                if (version.HasValue && version.Value.HasFlag(RDPUDP_PROTOCOL_VERSION.RDPUDP_PROTOCOL_VERSION_3))
                {
                    upgradedToRdpedup2 = true;
                    DisposeTimers();
                    rdpeudp2Handler = new Rdpeudp2ProtocolHandler(AutoHandle, SendBytesByUdp, Close, ReceiveDataOnHigherLayer);
                    rdpeudp2Handler.SocketConfig.RetransmitDuration    = RTT * 2;
                    rdpeudp2Handler.SocketConfig.DelayedAckTimeoutInMs = (int)(RTT.TotalMilliseconds / 2);
                }
            }

            return(true);
        }
示例#25
0
        /// <summary>
        /// Expect an ACK packet
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public RdpeudpPacket ExpectACKPacket(TimeSpan timeout)
        {
            DateTime endtime = DateTime.Now + timeout;

            while (DateTime.Now < endtime)
            {
                lock (unProcessedPacketBuffer)
                {
                    for (int i = 0; i < unProcessedPacketBuffer.Count; i++)
                    {
                        RdpeudpPacket eudpPacket = unProcessedPacketBuffer[i];
                        if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK))
                        {
                            if (!Connected || (eudpPacket.ackVectorHeader.HasValue && eudpPacket.ackVectorHeader.Value.uAckVectorSize > 0))
                            {
                                unProcessedPacketBuffer.RemoveAt(i);
                                return(eudpPacket);
                            }
                        }
                    }
                }
            }
            return(null);
        }
示例#26
0
        /// <summary>
        /// Expect a Syn Packet
        /// </summary>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public RdpeudpPacket ExpectSynPacket(TimeSpan timeout)
        {
            if (Connected)
            {
                return(null);
            }
            DateTime endtime = DateTime.Now + timeout;

            while (DateTime.Now < endtime)
            {
                lock (unProcessedPacketBuffer)
                {
                    for (int i = 0; i < unProcessedPacketBuffer.Count; i++)
                    {
                        RdpeudpPacket eudpPacket = unProcessedPacketBuffer[i];
                        RDPUDP_FLAG   expectFlag = RDPUDP_FLAG.RDPUDP_FLAG_SYN;
                        if (this.TransMode == TransportMode.Lossy)
                        {
                            expectFlag |= RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY;
                        }
                        if (eudpPacket.fecHeader.uFlags.HasFlag(expectFlag))
                        {
                            unProcessedPacketBuffer.RemoveAt(i);

                            // Analyse the SYN packet.
                            ProcessSynPacket(eudpPacket);

                            return(eudpPacket);
                        }
                    }
                }
                // If not receive a Packet, wait a while
                Thread.Sleep(RdpeudpSocketConfig.ReceivingInterval);
            }
            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 Data from this specified UDP transport
        /// </summary>
        /// <param name="data">Data to send</param>
        /// <returns>Return true if send success</returns>
        public bool Send(byte[] data)
        {
            if (!Connected) return false;
            List<byte> dataList = new List<byte>(data);
            int payloadLength = 0;
            byte[] packetData;
            RdpeudpPacket packet;
            do
            {
                packet = new RdpeudpPacket();                  // Fill in the common header.
                packet.fecHeader.snSourceAck = SnSourceAck;
                packet.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
                packet.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_DATA | RDPUDP_FLAG.RDPUDP_FLAG_ACK;
                packet.ackVectorHeader = CreateAckVectorHeader();

                packet.sourceHeader = CreateSourcePayloadHeader();  // Generate SourceHeader.

                packetData = PduMarshaler.Marshal(packet, false);      // Measure the header lenght to figure out payload length.
                payloadLength = Math.Min(UUpStreamMtu - packetData.Length, dataList.Count);

                packet.payload = new byte[payloadLength];
                dataList.CopyTo(0, packet.payload, 0, payloadLength);   // Copy the data in to packet payload.

                string str = System.Text.Encoding.ASCII.GetString(packet.payload);
                SendPacket(packet);
                dataList.RemoveRange(0, payloadLength);

            } while (dataList.Count > 0);

            return true;
        }
        public bool RetransmitPacket(RdpeudpPacket packet)
        {
            if (!connected ||
                packet.sourceHeader == null) return false;

            if (!outPacketDic.ContainsKey(packet.sourceHeader.Value.snSourceStart))
            {
                return false;
            }

            if (outPacketDic[packet.sourceHeader.Value.snSourceStart].retransmitTimes >= this.SocketConfig.retransmitLimit)
            {
                //If a datagram has been retransmitted four times without a response, the sender terminates the connection
                this.Close();
            }
            RDPUDP_SOURCE_PAYLOAD_HEADER sourceHeader = packet.sourceHeader.Value;
            Monitor.Enter(sequenceNumberLock);
            sourceHeader.snCoded = ++CurSnCoded;
            Monitor.Exit(sequenceNumberLock);
            packet.sourceHeader = sourceHeader;

            byte[] data = PduMarshaler.Marshal(packet, false);
            SendBytesByUDP(data);

            lock (outPacketDic)         // Deal with outPacketDic and retransmit packet.
            {
                if (outPacketDic.ContainsKey(packet.sourceHeader.Value.snSourceStart))
                {
                    outPacketDic[packet.sourceHeader.Value.snSourceStart].retransmitTimes++;
                    outPacketDic[packet.sourceHeader.Value.snSourceStart].SendTime = DateTime.Now;
                }
            }
            return true;
        }
        /// <summary>
        /// Send an ACK Datagrams
        /// </summary>
        /// <returns></returns>
        public bool SendAcKPacket(bool delayACK = false)
        {
            if (!connected) return false;
            RdpeudpPacket AckPacket = new RdpeudpPacket();
            AckPacket.fecHeader.snSourceAck = SnSourceAck;
            AckPacket.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
            AckPacket.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_ACK;

            if (delayACK)
            {
                AckPacket.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_ACK | RDPUDP_FLAG.RDPUDP_FLAG_ACKDELAYED;
            }

            AckPacket.ackVectorHeader = CreateAckVectorHeader();

            SendPacket(AckPacket);

            return true;
        }
 public byte[] CreateFECPayload(RdpeudpPacket[] sourcePackets, out byte uFecIndex)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Used during sending source packet, Add RDPUDP_ACK_OF_ACKVECTOR_HEADER structure into the packet to update OutSnAckOfAcksSeqNum 
 /// </summary>
 /// <param name="eudpPacket">Packet to be sent</param>
 private void UpdateOutSnAckOfAcksSeqNum(RdpeudpPacket eudpPacket)
 {
     if (newOutSnAckOfAcksSeqNum == null
         && SendWindowStartPosition - 1 - OutSnAckOfAcksSeqNum > this.SocketConfig.changeSnAckOfAcksSeqNumInterval)
     {
         Monitor.Enter(updateAckOfAckLock);
         if (newOutSnAckOfAcksSeqNum == null
             && SendWindowStartPosition - 1 - OutSnAckOfAcksSeqNum > this.SocketConfig.changeSnAckOfAcksSeqNumInterval)
         {
             newOutSnAckOfAcksSeqNum = SendWindowStartPosition - 1;
             RDPUDP_ACK_OF_ACKVECTOR_HEADER ackOfAckVector = new RDPUDP_ACK_OF_ACKVECTOR_HEADER();
             ackOfAckVector.snAckOfAcksSeqNum = newOutSnAckOfAcksSeqNum.Value;
             eudpPacket.ackOfAckVector = ackOfAckVector;
             eudpPacket.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS | eudpPacket.fecHeader.uFlags;
             seqNumofPacketWithAckOfAckVector = eudpPacket.sourceHeader.Value.snSourceStart;
         }
         Monitor.Exit(updateAckOfAckLock);
     }
 }
        /// <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!");
            }
        }
        /// <summary>
        /// Method used to process a received packet
        /// </summary>
        /// <param name="packet"></param>
        public void ReceivePacket(RdpeudpPacket eudpPacket)
        {
            // Update last receive time, which is used for keep alive timer
            LastReceiveDiagramTime = DateTime.Now;

            Monitor.Enter(receiveLock);

            if (!connected || !AutoHandle)
            {
                // If connection haven't been setuped, or Auto handle is false, this packet will not be processed automatically by this method.
                // It will buffer it for others to use it.
                lock (unProcessedPacketBuffer) unProcessedPacketBuffer.Add(eudpPacket);
            }
            else
            {
                // Process the received packet
                // In case the advised window size updated
                URemoteAdvisedWindowSize = eudpPacket.fecHeader.uReceiveWindowSize;
                // this value should update when receiving ACK if congestion algorithm is implemented
                USendWindowSize = URemoteAdvisedWindowSize;
                // Process Ack Vector Header if the packet contained
                ProcessAckVectorHeader(eudpPacket);
                // Process Source Data if the packet contained
                ProcessSourceData(eudpPacket);
                // Process FEC Payload data if the packet contained
                ProcessFECPayloadData(eudpPacket);
                // Process RDPUDP_ACK_OF_ACKVECTOR_HEADER Structure if the packet contained
                ProcessAckOfAckVectorHeader(eudpPacket);

                //TODO: Congestion control function

            }
            Monitor.Exit(receiveLock);
        }
        /// <summary>
        /// Process a Syn Packet
        /// </summary>
        /// <param name="eudpPacket"></param>
        public void ProcessSynPacket(RdpeudpPacket eudpPacket)
        {
            if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN)
                || eudpPacket.fecHeader.uFlags.Equals(RDPUDP_FLAG.RDPUDP_FLAG_SYN | RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY)) // Make sure this packet is a SYN Packet
            {
                UDownStreamMtu = (ushort)(Math.Min(Math.Min(eudpPacket.SynData.Value.uUpStreamMtu, UDownStreamMtu), (ushort)1232));
                UUpStreamMtu = (ushort)(Math.Min(Math.Min(eudpPacket.SynData.Value.uDownStreamMtu, UUpStreamMtu), (ushort)1232));
                USendWindowSize = eudpPacket.fecHeader.uReceiveWindowSize;
                TransMode = eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY) ? TransportMode.Lossy : TransportMode.Reliable;
                SnSourceAck = eudpPacket.SynData.Value.snInitialSequenceNumber;

                InSnAckOfAcksSeqNum = eudpPacket.SynData.Value.snInitialSequenceNumber + 1;
                ReceiveWindowStartPosition = eudpPacket.SynData.Value.snInitialSequenceNumber + 1;
            }
        }
 /// <summary>
 /// Process RDPUDP_FEC_PAYLOAD_HEADER Structure and FEC Payload
 /// </summary>
 /// <param name="eudpPacket"></param>
 public void ProcessFECPayloadData(RdpeudpPacket eudpPacket)
 {
     if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC))
     {
         // TODO: process FEC payload, calculate lost packet with FEC data
         // then use UpdateReceiveWindow function to update window and process received data
     }
 }
        /// <summary>
        /// Expect a SYN Packet which is from specific remoteIP using specific connection mode
        /// </summary>
        /// <param name="remoteIP">IP address of remote endpoint</param>
        /// <param name="mode">connection mode</param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public RdpeudpPacket ExpectSyncPacket(IPAddress remoteIP, TransportMode mode, TimeSpan timeout, out IPEndPoint remoteEndPoint)
        {
            remoteEndPoint = null;
            DateTime endtime = DateTime.Now + timeout;
            RDPUDP_FLAG expectFlag = RDPUDP_FLAG.RDPUDP_FLAG_SYN;
            if (mode == TransportMode.Lossy)
            {
                expectFlag |= RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY;
            }
            while (DateTime.Now < endtime)
            {
                lock (this.unprocessedPacketBuffer)
                {
                    for (int i = 0; i < unprocessedPacketBuffer.Count; i++)
                    {
                        StackPacketInfo spInfo = unprocessedPacketBuffer[i];
                        remoteEndPoint = spInfo.remoteEndpoint as IPEndPoint;
                        if (remoteEndPoint.Address.Equals(remoteIP))
                        {
                            RdpeudpPacket eudpPacket = new RdpeudpPacket();
                            if (PduMarshaler.Unmarshal(spInfo.packet.ToBytes(), eudpPacket, false))
                            {
                                if (eudpPacket.fecHeader.uFlags.HasFlag(expectFlag))
                                {
                                    unprocessedPacketBuffer.RemoveAt(i);
                                    return eudpPacket;
                                }
                            }
                        }
                    }

                }
                // If not receive a Packet, wait a while
                Thread.Sleep(RdpeudpSocketConfig.ReceivingInterval);
            }
            return null;
        }
 /// <summary>
 /// 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.
 /// </summary>
 public void ProcessSynDataExPayload(RdpeudpPacket eudpPacket)
 {
     if(eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYNEX) && eudpPacket.SynDataEx != null)
     {
         if(eudpPacket.SynDataEx.Value.uUdpVer.HasFlag(uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_2))
         {
             HighestVersion = uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_2;
             return;
         }
     }
     HighestVersion = uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_1;
 }
 /// <summary>
 /// Compute the FEC data with the input sources data arrays. 
 /// </summary>
 /// <param name="sourcePackes">Array of RdpudpPackets used to calculate FEC data</param>
 /// <param name="uFecIndex">This value is generated by the FEC engine</param>
 /// <returns>FEC data.</returns>
 public static byte[] Encode(RdpeudpPacket[] sourcePackes, out byte uFecIndex)
 {
     throw new NotImplementedException();
 }
 public byte[] FECRecover(RdpeudpPacket[] sourcePackets, byte uFecIndex, byte[] fecData, uint targetIndex)
 {
     throw new NotImplementedException();
 }
        /// <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>
        /// 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");
                }

            }
        }
        /// <summary>
        /// Method used to process a received packet
        /// </summary>
        /// <param name="packet"></param>
        public void ReceivePacket(StackPacket packet)
        {
            // Transfer packet to
            RdpeudpPacket eudpPacket = new RdpeudpPacket();
            byte[] packetBytes = packet.ToBytes();
            if (!PduMarshaler.Unmarshal(packetBytes, eudpPacket, false))
            {
                return;
            }

            // ETW Provider Dump Message
            string messageName = "RDPEUDP:ReceivedPDU";
            ExtendedLogger.DumpMessage(messageName, DumpLevel_LayerTLS, eudpPacket.GetType().Name, packetBytes);

            ReceivePacket(eudpPacket);
        }
 /// <summary>
 /// Send a SYN and ACK diagram
 /// </summary>
 /// <param name="initSequenceNumber">Specify an initial sequence number</param>
 /// <returns></returns>
 public bool SendSynAndAckPacket(uint? initSequenceNumber = null, uUdpVer_Values? version = null)
 {
     if (Connected) return false;
     RdpeudpPacket SynAndAckPacket = new RdpeudpPacket();
     SynAndAckPacket.fecHeader.snSourceAck = SnSourceAck;
     SynAndAckPacket.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
     SynAndAckPacket.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_SYN | RDPUDP_FLAG.RDPUDP_FLAG_ACK;
     if(version != null)
     {
         SynAndAckPacket.fecHeader.uFlags |= RDPUDP_FLAG.RDPUDP_FLAG_SYNEX;
         SynAndAckPacket.SynDataEx = CreateSynExData((uUdpVer_Values)version);
     }
     SynAndAckPacket.SynData = CreateSynData(initSequenceNumber);
     SendPacket(SynAndAckPacket);
     // Set the OutSnAckOfAcksSeqNum value, number from which the receive thread decoding the state of the send packet.
     OutSnAckOfAcksSeqNum = SynAndAckPacket.SynData.Value.snInitialSequenceNumber + 1;
     return true;
 }
        /// <summary>
        /// Process Source payload if the packet has source payload data
        /// </summary>
        /// <param name="eudpPacket"></param>
        public void ProcessSourceData(RdpeudpPacket eudpPacket)
        {
            if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA) && !eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC))
            {
                lock (inPacketDic)
                {
                    if(IsInReceiveWindow(eudpPacket.sourceHeader.Value.snSourceStart))
                    {
                        SnSourceAck = Math.Max(SnSourceAck, eudpPacket.sourceHeader.Value.snSourceStart);
                        InPacketState inPacketState = new InPacketState();
                        inPacketState.Packet = eudpPacket;
                        inPacketDic[eudpPacket.sourceHeader.Value.snSourceStart] = inPacketState;

                        UpdateReceiveWindow();
                    }

                    // Increase received source packet numbers not be ack
                    if (sourceNumNotAcked == 0)
                    {
                        ReceiveTimeForFirstNotACKSource = DateTime.Now;
                    }
                    sourceNumNotAcked++;
                }
                // Send ACK diagram if necessary.
                AckPacketReceived();
            }
        }
        /// <summary>
        /// Send a RDPEUDP Packet
        /// </summary>
        /// <param name="packet"></param>
        /// <returns></returns>
        public bool SendPacket(RdpeudpPacket packet)
        {
            if (packet.sourceHeader.HasValue && AutoHandle)
            {                                 // Deal with window area.

                OutPacketState packetState = new OutPacketState();
                packetState.Packet = packet;
                packetState.Acknowledged = false;

                DateTime endTime = DateTime.Now + this.SocketConfig.Timeout;
                uint sendWindowsEndPos = SendWindowStartPosition + USendWindowSize;

                while (DateTime.Now < endTime)
                {
                    //If source sequence number is in send slide window, send the packet. Otherwise, wait a sendingInterval
                    if (!IsInSendWindow(packet.sourceHeader.Value.snSourceStart))
                    {
                        sendWindowLock.WaitOne(this.SocketConfig.sendingInterval);
                    }
                    else
                    {
                        break;
                    }
                }
                if (DateTime.Now > endTime)
                {
                    // Time out.
                    return false;
                }

                packetState.SendTime = DateTime.Now;
                lock (outPacketDic) outPacketDic[packet.sourceHeader.Value.snSourceStart] = packetState;

                // Add RDPUDP_ACK_OF_ACKVECTOR_HEADER Structure if necessary
                UpdateOutSnAckOfAcksSeqNum(packet);

            }

            byte[] data = PduMarshaler.Marshal(packet, false);
            SendBytesByUDP(data);

            // Update Last send time, which is used for keep alive timer
            LastSendDiagramTime = DateTime.Now;

            return true;
        }
        /// <summary>
        /// Process RDPUDP_ACK_VECTOR_HEADER if the packet contains a RDPUDP_ACK_VECTOR_HEADER
        /// </summary>
        /// <param name="eudpPacket"></param>
        private void ProcessAckVectorHeader(RdpeudpPacket eudpPacket)
        {
            // Update OutSnAckOfAcksSeqNum if necessary
            UpdateOutSnAckOfAcksSeqNum(eudpPacket.fecHeader.snSourceAck);

            if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK) && !eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN))
            {
                //Contains ack, analyze ack value, update outPacketDic, caculate RTT, and move send window
                if (eudpPacket.ackVectorHeader.Value.uAckVectorSize > 0)    // Deal with ack vector.
                {
                    uint currentposition = OutSnAckOfAcksSeqNum;
                    lock (outPacketDic)
                    {
                        foreach (AckVector AckVectorElement in eudpPacket.ackVectorHeader.Value.AckVectorElement)
                        {
                            if (AckVectorElement.State == VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED)
                            {
                                // update outPacketDic only if this vector element is to ack received
                                for (byte i = 0; i < AckVectorElement.Length + 1; i++, currentposition++)
                                {
                                    if (outPacketDic.ContainsKey(currentposition))
                                    {
                                        outPacketDic[currentposition].Acknowledged = true;
                                    }
                                }

                            }
                            else
                            {
                                currentposition = currentposition + AckVectorElement.Length + 1;
                            }
                        }

                        // If this packet is not a delay ack, calculate RTT, only the last acknowleged source packet is used to caculate RTT
                        if (outPacketDic.ContainsKey(currentposition - 1))
                        {
                            if (!eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACKDELAYED)
                                && !outPacketDic[currentposition - 1].estimatedRTT) // Also make sure this packet has not been used to estimate RTT. If the packet has been used to estimated RTT, this packet may be a resent ACK for keep alive
                            {
                                RTT = new TimeSpan(RTT.Ticks / 8 * 7 + (DateTime.Now - outPacketDic[currentposition - 1].SendTime).Ticks / 8);  // Count the RTT.
                                outPacketDic[currentposition - 1].estimatedRTT = true;
                            }
                        }

                        // Update send window, this method will update outPacketDic
                        UpdateSendWindow();
                    }
                    sendWindowLock.Set();
                }
            }
        }
        /// <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>
 /// Compute the source data in the specified index.
 /// </summary>
 /// <param name="sourcePackes">Array of RdpudpPackets received.</param>
 /// <param name="uFecIndex">Generated by the FEC engine when encoding</param>
 /// <param name="fecData">Fec data</param>
 /// <param name="targetIdx">The index in which the data to be decoded.</param>
 /// <returns>The target source data.</returns>
 public static byte[] Decode(RdpeudpPacket[] sourcePackets, byte uFecIndex, byte[] fecData, uint targetIdx)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Create Source Packet from byte data
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public RdpeudpPacket CreateSourcePacket(byte[] data)
        {
            if (data == null || data.Length == 0)
            {
                return null;
            }

            RdpeudpPacket packet = new RdpeudpPacket();                  // Fill in the common header.
            packet.fecHeader.snSourceAck = SnSourceAck;
            packet.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
            packet.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_DATA | RDPUDP_FLAG.RDPUDP_FLAG_ACK;
            packet.ackVectorHeader = CreateAckVectorHeader();

            packet.sourceHeader = CreateSourcePayloadHeader();
            packet.payload = data;
            return packet;
        }
 /// <summary>
 /// Send SYN Packet to init a RDPEUDP Connection
 /// </summary>
 /// <param name="initSequenceNumber">Specify a snInitialSequenceNumber</param>
 /// <returns></returns>
 public bool SendSynPacket(uint? initSequenceNumber = null)
 {
     if (Connected) return false;
     RdpeudpPacket SynAndAckPacket = new RdpeudpPacket();
     SynAndAckPacket.fecHeader.snSourceAck = SnSourceAck;
     SynAndAckPacket.fecHeader.uReceiveWindowSize = UReceiveWindowSize;
     SynAndAckPacket.fecHeader.uFlags = RDPUDP_FLAG.RDPUDP_FLAG_SYN;
     if (this.TransMode == TransportMode.Lossy)
     {
         SynAndAckPacket.fecHeader.uFlags |= RDPUDP_FLAG.RDPUDP_FLAG_SYNLOSSY;
     }
     SynAndAckPacket.SynData = CreateSynData(initSequenceNumber);
     SendPacket(SynAndAckPacket);
     // Set the OutSnAckOfAcksSeqNum value, number from which the receive thread decoding the state of the send packet.
     OutSnAckOfAcksSeqNum = SynAndAckPacket.SynData.Value.snInitialSequenceNumber + 1;
     return true;
 }
 /// <summary>
 /// Process RDPUDP_ACK_OF_ACKVECTOR_HEADER Structure if the packet have
 /// </summary>
 /// <param name="eudpPacket"></param>
 public void ProcessAckOfAckVectorHeader(RdpeudpPacket eudpPacket)
 {
     if (eudpPacket.fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS))
     {
         InSnAckOfAcksSeqNum = eudpPacket.ackOfAckVector.Value.snAckOfAcksSeqNum;
     }
 }