/// <summary> /// Create RDPUDP_ACK_VECTOR_HEADER Structure for packet sending /// </summary> /// <returns></returns> public RDPUDP_ACK_VECTOR_HEADER CreateAckVectorHeader() { RDPUDP_ACK_VECTOR_HEADER ackVectorHeader = new RDPUDP_ACK_VECTOR_HEADER(); if (inPacketDic.Count == 0) { // Not receive any source packet ackVectorHeader.uAckVectorSize = 0; ackVectorHeader.AckVectorElement = null; ackVectorHeader.Padding = null; } else { lock (inPacketDic) { // Generate an ACK header. List <AckVector> ackVectorElements = new List <AckVector>(); VECTOR_ELEMENT_STATE currentState = inPacketDic.ContainsKey(InSnAckOfAcksSeqNum) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED; AckVector ackVectorElement = new AckVector(); ackVectorElement.State = currentState; ackVectorElement.Length = 0; // RLE encoding. for (uint i = InSnAckOfAcksSeqNum + 1; i <= SnSourceAck; i++) { currentState = inPacketDic.ContainsKey(i) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED; // 0x40 is the max length of state length, of which I believe sould be indicate from soket config or types config not hard code here. if (currentState != ackVectorElement.State || ackVectorElement.Length >= 0x40) { // If current state differs from last state, assign a new ack vector. ackVectorElements.Add(ackVectorElement); ackVectorElement = new AckVector(); ackVectorElement.State = currentState; ackVectorElement.Length = 0; } else { // Else count++. ackVectorElement.Length++; } } ackVectorElements.Add(ackVectorElement); ackVectorHeader.uAckVectorSize = (ushort)ackVectorElements.Count; ackVectorHeader.AckVectorElement = ackVectorElements.ToArray(); // ACK Vector created for all received packet, set number of received packets for ACK to 0 sourceNumNotAcked = 0; } } return(ackVectorHeader); }
public override bool Decode(PduMarshaler marshaler) { try { fecHeader.snSourceAck = marshaler.ReadUInt32(); fecHeader.uReceiveWindowSize = marshaler.ReadUInt16(); fecHeader.uFlags = (RDPUDP_FLAG)marshaler.ReadUInt16(); if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN)) { RDPUDP_SYNDATA_PAYLOAD synData = new RDPUDP_SYNDATA_PAYLOAD(); synData.snInitialSequenceNumber = marshaler.ReadUInt32(); synData.uUpStreamMtu = marshaler.ReadUInt16(); synData.uDownStreamMtu = marshaler.ReadUInt16(); // This datagram MUST be zero-padded to increase the size of this datagram to 1232 bytes. if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_CORRELATION_ID)) { RDPUDP_CORRELATION_ID_PAYLOAD correlationId = new RDPUDP_CORRELATION_ID_PAYLOAD(); correlationId.uCorrelationId = marshaler.ReadBytes(16); this.CorrelationId = correlationId; correlationId.uReserved = marshaler.ReadBytes(16); } this.padding = marshaler.ReadToEnd(); this.SynData = synData; return true; } if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK)) { // ACK. RDPUDP_ACK_VECTOR_HEADER ackVector = new RDPUDP_ACK_VECTOR_HEADER(); ackVector.uAckVectorSize = marshaler.ReadUInt16(); ackVector.AckVectorElement = new AckVector[ackVector.uAckVectorSize]; List<byte> ackVecElementList = new List<byte>(marshaler.ReadBytes(ackVector.AckVectorElement.Length)); ackVecElementList.Reverse(); for (int i = 0; i < ackVector.AckVectorElement.Length; i++) { byte vecByte = ackVecElementList[i]; ackVector.AckVectorElement[i].Length = (byte)(0x3F & vecByte); ackVector.AckVectorElement[i].State = (VECTOR_ELEMENT_STATE)(vecByte >> 6); } this.ackVectorHeader = ackVector; // Padding (variable): A variable-sized array, of length zero or more, // such that this structure ends on a DWORD ([MS-DTYP] section 2.2.9) boundary. int padLen = 4 - (2 + ackVector.AckVectorElement.Length) % 4; if (padLen > 0 && padLen != 4) { this.padding = marshaler.ReadBytes(padLen); } // Ack of Acks. if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS)) { RDPUDP_ACK_OF_ACKVECTOR_HEADER aoaHeader = new RDPUDP_ACK_OF_ACKVECTOR_HEADER(); aoaHeader.snAckOfAcksSeqNum = marshaler.ReadUInt32(); this.ackOfAckVector = aoaHeader; } } if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA)) { if (!fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC)) { // Source Data. RDPUDP_SOURCE_PAYLOAD_HEADER srcHeader = new RDPUDP_SOURCE_PAYLOAD_HEADER(); srcHeader.snCoded = marshaler.ReadUInt32(); srcHeader.snSourceStart = marshaler.ReadUInt32(); this.sourceHeader = srcHeader; } else { // FEC Data. RDPUDP_FEC_PAYLOAD_HEADER fecDataHeader = new RDPUDP_FEC_PAYLOAD_HEADER(); fecDataHeader.snCoded = marshaler.ReadUInt32(); fecDataHeader.snSourceStart = marshaler.ReadUInt32(); fecDataHeader.uRange = marshaler.ReadByte(); fecDataHeader.uFecIndex = marshaler.ReadByte(); fecDataHeader.uPadding = marshaler.ReadUInt16(); this.fecPayloadHeader = fecDataHeader; } this.payload = marshaler.ReadToEnd(); } return true; } catch { return false; } }
/// <summary> /// Create RDPUDP_ACK_VECTOR_HEADER Structure for packet sending /// </summary> /// <returns></returns> public RDPUDP_ACK_VECTOR_HEADER CreateAckVectorHeader() { RDPUDP_ACK_VECTOR_HEADER ackVectorHeader = new RDPUDP_ACK_VECTOR_HEADER(); if (inPacketDic.Count == 0) { // Not receive any source packet ackVectorHeader.uAckVectorSize = 0; ackVectorHeader.AckVectorElement = null; ackVectorHeader.Padding = null; } else { lock (inPacketDic) { // Generate an ACK header. List<AckVector> ackVectorElements = new List<AckVector>(); VECTOR_ELEMENT_STATE currentState = inPacketDic.ContainsKey(InSnAckOfAcksSeqNum) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED; AckVector ackVectorElement = new AckVector(); ackVectorElement.State = currentState; ackVectorElement.Length = 0; // RLE encoding. for (uint i = InSnAckOfAcksSeqNum + 1; i <= SnSourceAck; i++) { currentState = inPacketDic.ContainsKey(i) ? VECTOR_ELEMENT_STATE.DATAGRAM_RECEIVED : VECTOR_ELEMENT_STATE.DATAGRAM_NOT_YET_RECEIVED; // 0x40 is the max length of state length, of which I believe sould be indicate from soket config or types config not hard code here. if (currentState != ackVectorElement.State || ackVectorElement.Length >= 0x40) { // If current state differs from last state, assign a new ack vector. ackVectorElements.Add(ackVectorElement); ackVectorElement = new AckVector(); ackVectorElement.State = currentState; ackVectorElement.Length = 0; } else { // Else count++. ackVectorElement.Length++; } } ackVectorElements.Add(ackVectorElement); ackVectorHeader.uAckVectorSize = (ushort)ackVectorElements.Count; ackVectorHeader.AckVectorElement = ackVectorElements.ToArray(); // ACK Vector created for all received packet, set number of received packets for ACK to 0 sourceNumNotAcked = 0; } } return ackVectorHeader; }
public override bool Decode(PduMarshaler marshaler) { try { fecHeader.snSourceAck = marshaler.ReadUInt32(); fecHeader.uReceiveWindowSize = marshaler.ReadUInt16(); fecHeader.uFlags = (RDPUDP_FLAG)marshaler.ReadUInt16(); if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYN)) { RDPUDP_SYNDATA_PAYLOAD synData = new RDPUDP_SYNDATA_PAYLOAD(); synData.snInitialSequenceNumber = marshaler.ReadUInt32(); synData.uUpStreamMtu = marshaler.ReadUInt16(); synData.uDownStreamMtu = marshaler.ReadUInt16(); // This datagram MUST be zero-padded to increase the size of this datagram to 1232 bytes. if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_CORRELATION_ID)) { RDPUDP_CORRELATION_ID_PAYLOAD correlationId = new RDPUDP_CORRELATION_ID_PAYLOAD(); correlationId.uCorrelationId = marshaler.ReadBytes(16); this.CorrelationId = correlationId; correlationId.uReserved = marshaler.ReadBytes(16); } if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_SYNEX)) { RDPUDP_SYNDATAEX_PAYLOAD synDataEx = new RDPUDP_SYNDATAEX_PAYLOAD(); synDataEx.uSynExFlags = (uSynExFlags_Values)marshaler.ReadUInt16(); synDataEx.uUdpVer = (uUdpVer_Values)marshaler.ReadUInt16(); this.SynDataEx = synDataEx; } this.padding = marshaler.ReadToEnd(); this.SynData = synData; return(true); } if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK)) { // ACK. RDPUDP_ACK_VECTOR_HEADER ackVector = new RDPUDP_ACK_VECTOR_HEADER(); ackVector.uAckVectorSize = marshaler.ReadUInt16(); ackVector.AckVectorElement = new AckVector[ackVector.uAckVectorSize]; List <byte> ackVecElementList = new List <byte>(marshaler.ReadBytes(ackVector.AckVectorElement.Length)); ackVecElementList.Reverse(); for (int i = 0; i < ackVector.AckVectorElement.Length; i++) { byte vecByte = ackVecElementList[i]; ackVector.AckVectorElement[i].Length = (byte)(0x3F & vecByte); ackVector.AckVectorElement[i].State = (VECTOR_ELEMENT_STATE)(vecByte >> 6); } this.ackVectorHeader = ackVector; // Padding (variable): A variable-sized array, of length zero or more, // such that this structure ends on a DWORD ([MS-DTYP] section 2.2.9) boundary. int padLen = 4 - (2 + ackVector.AckVectorElement.Length) % 4; if (padLen > 0 && padLen != 4) { this.padding = marshaler.ReadBytes(padLen); } // Ack of Acks. if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_ACK_OF_ACKS)) { RDPUDP_ACK_OF_ACKVECTOR_HEADER aoaHeader = new RDPUDP_ACK_OF_ACKVECTOR_HEADER(); aoaHeader.snAckOfAcksSeqNum = marshaler.ReadUInt32(); this.ackOfAckVector = aoaHeader; } } if (fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_DATA)) { if (!fecHeader.uFlags.HasFlag(RDPUDP_FLAG.RDPUDP_FLAG_FEC)) { // Source Data. RDPUDP_SOURCE_PAYLOAD_HEADER srcHeader = new RDPUDP_SOURCE_PAYLOAD_HEADER(); srcHeader.snCoded = marshaler.ReadUInt32(); srcHeader.snSourceStart = marshaler.ReadUInt32(); this.sourceHeader = srcHeader; } else { // FEC Data. RDPUDP_FEC_PAYLOAD_HEADER fecDataHeader = new RDPUDP_FEC_PAYLOAD_HEADER(); fecDataHeader.snCoded = marshaler.ReadUInt32(); fecDataHeader.snSourceStart = marshaler.ReadUInt32(); fecDataHeader.uRange = marshaler.ReadByte(); fecDataHeader.uFecIndex = marshaler.ReadByte(); fecDataHeader.uPadding = marshaler.ReadUInt16(); this.fecPayloadHeader = fecDataHeader; } this.payload = marshaler.ReadToEnd(); } return(true); } catch { return(false); } }
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."); }