/// <summary>
 /// Remove a Socket from server
 /// </summary>
 /// <param name="socket"></param>
 public void RemoveSocket(RdpeudpServerSocket socket)
 {
     if (serverSocketDic != null && socket != null)
     {
         if (serverSocketDic.ContainsKey(socket.RemoteEndPoint))
         {
             serverSocketDic.Remove(socket.RemoteEndPoint);
         }
     }
 }
        /// <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>
        /// 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;
        }
        /// <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);
            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;
        }