/// <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> /// 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; }
/// <summary> /// Create RDPUDP_SYNDATAEX_PAYLOAD Structure /// </summary> /// <returns></returns> public RDPUDP_SYNDATAEX_PAYLOAD CreateSynExData(uUdpVer_Values version) { RDPUDP_SYNDATAEX_PAYLOAD SynExData = new RDPUDP_SYNDATAEX_PAYLOAD(); SynExData.uSynExFlags = uSynExFlags_Values.RDPUDP_VERSION_INFO_VALID; //The uUdpVer field MUST be set to the highest RDP-UDP protocol version supported by both endpoints if((version & uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_2) != 0) { SynExData.uUdpVer = uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_2; } else { SynExData.uUdpVer = uUdpVer_Values.RDPUDP_PROTOCOL_VERSION_1; } return SynExData; }
/// <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); }