/// <summary> /// Encode NETWORK_DETECTION_RESPONSE /// </summary> /// <param name="sendBuffer"></param> /// <param name="networkDetectionResponse"></param> /// <param name="isSubHeader"></param> internal static void EncodeNetworkDetectionResponse(List <byte> sendBuffer, NETWORK_DETECTION_RESPONSE networkDetectionResponse, bool isSubHeader = false) { if (!isSubHeader) { EncodeStructure(sendBuffer, networkDetectionResponse.headerLength); EncodeStructure(sendBuffer, (byte)networkDetectionResponse.headerTypeId); } EncodeStructure(sendBuffer, networkDetectionResponse.sequenceNumber); EncodeStructure(sendBuffer, (ushort)networkDetectionResponse.responseType); if (networkDetectionResponse.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_RTT_RESPONSE) { //RDP_RTT_RESPONSE } else if (networkDetectionResponse.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_AFTER_CONNECT || networkDetectionResponse.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_DURING_CONNECT) { RDP_BW_RESULTS bwResult = (RDP_BW_RESULTS)networkDetectionResponse; EncodeStructure(sendBuffer, bwResult.timeDelta); EncodeStructure(sendBuffer, bwResult.byteCount); } else if (networkDetectionResponse.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_NETCHAR_SYNC) { RDP_NETCHAR_SYNC sync = (RDP_NETCHAR_SYNC)networkDetectionResponse; EncodeStructure(sendBuffer, sync.bandwidth); EncodeStructure(sendBuffer, sync.rtt); } }
/// <summary> /// Generate sub header Data of BW result /// </summary> /// <param name="sequenceNumber"></param> /// <returns></returns> public byte[] GenerateSubHander_BWResult() { RDP_BW_RESULTS bwresult = RdpbcgrUtility.GenerateBandwidthMeasureResults(AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_AFTER_CONNECT, bwStopSequenceNumber, timeDelta, bandwidthMeasurePayloadByteCount); byte[] subHeaderbytes = RdpbcgrClient.EncodeNetworkDetectionResponse(bwresult, true); return(subHeaderbytes); }
/// <summary> /// Verify RDP Bandwidth Measure Result packet /// </summary> /// <param name="BwResult">RDP Bandwidth Result packet</param> /// <param name="sequenceNumber">The sequence Number</param> private void VerifyTunnelDataPdu_BWResult(RDP_BW_RESULTS BwResult, ushort sequenceNumber) { if (BwResult == null) { Site.Assert.Fail("Not get Bandwidth Measure Result"); } if (BwResult.sequenceNumber != sequenceNumber) { Site.Assert.Fail("Expect sequence Number is {0}, but receive sequence Number: {1}", sequenceNumber, BwResult.sequenceNumber); } }
/// <summary> /// Encode a RDP_BW_RESULTS structure for subheader, don't encode the first two field /// </summary> /// <param name="bwStop"></param> /// <returns></returns> public static byte[] EncodeRdpBWResults(RDP_BW_RESULTS bwRes) { List <byte> bufferList = new List <byte>(); bufferList.AddRange(ToBytes(bwRes.sequenceNumber)); bufferList.AddRange(ToBytes((ushort)bwRes.responseType)); bufferList.AddRange(ToBytes(bwRes.timeDelta)); bufferList.AddRange(ToBytes(bwRes.byteCount)); return(bufferList.ToArray()); }
/// <summary> /// Parse RDP_BW_RESULTS structure from RDPEMT subheader /// </summary> /// <param name="data">Data of subheader, not include first two bytes of Parse RDP_BW_RESULTS</param> /// <returns></returns> public static RDP_BW_RESULTS ParseRdpBWResults(byte[] data) { RDP_BW_RESULTS bwRes = new RDP_BW_RESULTS(); bwRes.sequenceNumber = ParseUInt16(data, 0); bwRes.responseType = (AUTO_DETECT_RESPONSE_TYPE)ParseUInt16(data, 2); int index = 4; bwRes.timeDelta = ParseUInt32(data, index); index += 4; bwRes.byteCount = ParseUInt32(data, index); index += 4; return(bwRes); }
/// <summary> /// Process Auto Detect feature /// </summary> /// <param name="pdu"></param> public override void ProcessSubHeaders(RdpemtBasePDU pdu) { RDP_TUNNEL_SUBHEADER[] RDPTunnelSubHeaders = pdu.TunnelHeader.SubHeaders; if (RDPTunnelSubHeaders != null) { foreach (RDP_TUNNEL_SUBHEADER RDPTunnelSubHeader in RDPTunnelSubHeaders) { if (RDPTunnelSubHeader.SubHeaderType == RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_RESPONSE) { uint responseType = (uint)(RDPTunnelSubHeader.SubHeaderData[3] << 8) + RDPTunnelSubHeader.SubHeaderData[2]; if (responseType == (uint)AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_AFTER_CONNECT) { RDP_BW_RESULTS bwRes = RdpemtUtility.ParseRdpBWResults(RDPTunnelSubHeader.SubHeaderData); this.bandwidth = (bwRes.byteCount * 8) / bwRes.timeDelta; } } } } }
/// <summary> /// Wait for a Tunnel Data PDU with RDP_BW_RESULTS and check its sequenceNumber. /// </summary> /// <param name="requestedProtocol">Which tunnel to be used, reliable or lossy</param> /// <param name="sequenceNumber"></param> /// <param name="timeout"></param> private void WaitForAndCheckTunnelDataPdu_BWResult(Multitransport_Protocol_value requestedProtocol, ushort sequenceNumber, TimeSpan timeout, bool NegiveLossy = false) { bool isReceived = false; TimeSpan leftTime = timeout; DateTime expiratedTime = DateTime.Now + timeout; RDP_BW_RESULTS bwResult = null; RdpemtServer rdpemtServer = rdpemtServerR; if (requestedProtocol == Multitransport_Protocol_value.INITITATE_REQUEST_PROTOCOL_UDPFECL) { rdpemtServer = rdpemtServerL; } while (!isReceived && leftTime.CompareTo(new TimeSpan(0)) > 0) { try { RDP_TUNNEL_DATA tunnelData = rdpemtServer.ExpectTunnelData(leftTime); if (tunnelData != null) { RDP_TUNNEL_SUBHEADER[] SubHeaders = tunnelData.TunnelHeader.SubHeaders; if (SubHeaders != null) { foreach (RDP_TUNNEL_SUBHEADER subHeader in SubHeaders) { if (subHeader.SubHeaderType == RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_RESPONSE) { NETWORK_DETECTION_RESPONSE detectRsp = rdpbcgrServer.ParseNetworkDetectionResponse(subHeader.SubHeaderData, true); { if (detectRsp.responseType == AUTO_DETECT_RESPONSE_TYPE.RDP_BW_RESULTS_AFTER_CONNECT) { bwResult = (RDP_BW_RESULTS)detectRsp; isReceived = true; bwDataStore.byteCount = bwResult.byteCount; bwDataStore.timeDelta = bwResult.timeDelta; Site.Log.Add(LogEntryKind.Comment, "ByteCount: {0} Bytes\tTimeDelta: {1} Milliseconds", bwDataStore.byteCount, bwDataStore.timeDelta); } } } } } } } catch (TimeoutException) { if (NegiveLossy) { Site.Log.Add(LogEntryKind.Comment, "If the sequenceNumber of RDP_BW_STOP is different from that in RDP_BW_START, Client should not send RDP_BW_RESULTS"); } else { Site.Assert.Fail("Timeout when expecting a Tunnel Data PDU with RDP_BW_RESULTS"); } } catch (InvalidOperationException ex) { //break; Site.Log.Add(LogEntryKind.Warning, "Exception thrown out when receiving client PDUs {0}.", ex.Message); } finally { System.Threading.Thread.Sleep(100);//Wait some time for next packet. leftTime = expiratedTime - DateTime.Now; } } if (isReceived) { VerifyTunnelDataPdu_BWResult(bwResult, sequenceNumber); if (NegiveLossy) { Site.Assert.Fail("If the sequenceNumber of RDP_BW_STOP is different from that in RDP_BW_START, Client should not send RDP_BW_RESULTS"); } } else { if (NegiveLossy) { Site.Log.Add(LogEntryKind.Comment, "If the sequenceNumber of RDP_BW_STOP is different from that in RDP_BW_START, Client should not send RDP_BW_RESULTS"); } else { Site.Assert.Fail("Timeout when expecting a Tunnel Data PDU with RDP_BW_RESULTS"); } } }