/// <summary> /// Expect a Tunnel Data from receive buffer /// This method only can be used when autohandle is false /// </summary> /// <param name="timeout"></param> /// <returns></returns> public RDP_TUNNEL_DATA ExpectTunnelData(TimeSpan timeout) { if (!Connected || AutoHandle) { return(null); } DateTime endTime = DateTime.Now + timeout; RDP_TUNNEL_DATA tunnalData = null; while (DateTime.Now < endTime) { if (receiveBuffer.Count > 0) { lock (receiveBuffer) { if (receiveBuffer.Count > 0) { for (int i = 0; i < receiveBuffer.Count; i++) { if (receiveBuffer[i] is RDP_TUNNEL_DATA) { tunnalData = receiveBuffer[i] as RDP_TUNNEL_DATA; receiveBuffer.RemoveAt(i); return(tunnalData); } } } } } Thread.Sleep(waitInterval); } return(null); }
/// <summary> /// Process Auto Detect feature /// </summary> /// <param name="pdu"></param> public override void ProcessSubHeaders(RdpemtBasePDU pdu) { if (pdu == null || pdu.TunnelHeader == null) { return; } if (detectBandwidth) { // if detect device, count bytes bandwidthMeasurePayloadByteCount += ((uint)pdu.TunnelHeader.PayloadLength + pdu.TunnelHeader.HeaderLength); } 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_REQUEST) { uint sequenceNumber = (uint)(RDPTunnelSubHeader.SubHeaderData[1] << 8) + RDPTunnelSubHeader.SubHeaderData[0]; uint responseType = (uint)(RDPTunnelSubHeader.SubHeaderData[3] << 8) + RDPTunnelSubHeader.SubHeaderData[2]; if (responseType == (uint)AUTO_DETECT_REQUEST_TYPE.RDP_BW_START_AFTER_CONNECTTIME_OR_LOSSYUDP || responseType == (uint)AUTO_DETECT_REQUEST_TYPE.RDP_BW_START_AFTER_CONNECTTIME_OR_RELIABLEUDP) { // Start bandwidth detect bandwidthMeasureStartTime = DateTime.Now; bandwidthMeasurePayloadByteCount = 0; detectBandwidth = true; } else if (responseType == (uint)AUTO_DETECT_REQUEST_TYPE.RDP_BW_STOP_AFTER_CONNECTTIME_OR_LOSSYUDP || responseType == (uint)AUTO_DETECT_REQUEST_TYPE.RDP_BW_STOP_AFTER_CONNECTTIME_OR_RELIABLEUDP) { detectBandwidth = false; TimeSpan duration = DateTime.Now - bandwidthMeasureStartTime; this.timeDelta = (uint)duration.TotalMilliseconds; bwStopSequenceNumber = (ushort)sequenceNumber; // Send RDP_BW_RESULTS if (AutoHandle) { byte[] subHeader = GenerateSubHander_BWResult(); List <byte[]> subHeaders = new List <byte[]>(); subHeaders.Add(subHeader); RDP_TUNNEL_DATA tunnelData = CreateTunnelDataPdu(null, subHeaders, RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_RESPONSE); this.SendRdpemtPacket(tunnelData); } } else if (responseType == (uint)AUTO_DETECT_REQUEST_TYPE.RDP_NETCHAR_RESULT_BANDWIDTH_AVERAGERTT || responseType == (uint)AUTO_DETECT_REQUEST_TYPE.RDP_NETCHAR_RESULT_BASERTT_BANDWIDTH_AVERAGERTT) { // Update bandwidth RDP_NETCHAR_RESULT ncRes = RdpemtUtility.ParseRdpNetCharResult(RDPTunnelSubHeader.SubHeaderData); this.bandwidth = ncRes.bandwidth; } } } } }
/// <summary> /// Process Tunnel Data pdu /// </summary> /// <param name="pdu"></param> private void ProcessTunnelData(RDP_TUNNEL_DATA pdu) { if (pdu.HigherLayerData != null && pdu.HigherLayerData.Length > 0) { if (Received != null) { Received(pdu.HigherLayerData); } } }
/// <summary> /// Create Tunnel Data PDU /// </summary> /// <param name="Payload"></param> /// <param name="SubheaderList"></param> /// <returns></returns> public RDP_TUNNEL_DATA CreateTunnelDataPdu(byte[] Payload, List <byte[]> SubheaderList = null, RDP_TUNNEL_SUBHEADER_TYPE_Values subHeaderType = RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_REQUEST) { RDP_TUNNEL_DATA tunnelData = new RDP_TUNNEL_DATA(); tunnelData.TunnelHeader = new RDP_TUNNEL_HEADER(); tunnelData.TunnelHeader.Action = RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_DATA; tunnelData.TunnelHeader.Flags = 0; tunnelData.TunnelHeader.HeaderLength = 4; if (SubheaderList != null && SubheaderList.Count > 0) { tunnelData.TunnelHeader.SubHeaders = new RDP_TUNNEL_SUBHEADER[SubheaderList.Count]; for (int i = 0; i < SubheaderList.Count; i++) { tunnelData.TunnelHeader.SubHeaders[i] = new RDP_TUNNEL_SUBHEADER(); tunnelData.TunnelHeader.SubHeaders[i].SubHeaderLength = (byte)(2 + SubheaderList[i].Length); tunnelData.TunnelHeader.SubHeaders[i].SubHeaderType = subHeaderType; tunnelData.TunnelHeader.SubHeaders[i].SubHeaderData = new byte[SubheaderList[i].Length]; Array.Copy(SubheaderList[i], tunnelData.TunnelHeader.SubHeaders[i].SubHeaderData, SubheaderList[i].Length); tunnelData.TunnelHeader.HeaderLength += tunnelData.TunnelHeader.SubHeaders[i].SubHeaderLength; } } else { tunnelData.TunnelHeader.SubHeaders = null; } if (Payload != null) { tunnelData.TunnelHeader.PayloadLength = (ushort)Payload.Length; tunnelData.HigherLayerData = new byte[Payload.Length]; Array.Copy(Payload, tunnelData.HigherLayerData, Payload.Length); } else { tunnelData.TunnelHeader.PayloadLength = 0; tunnelData.HigherLayerData = null; } return(tunnelData); }
/// <summary> /// Process Tunnel Data pdu /// </summary> /// <param name="pdu"></param> private void ProcessTunnelData(RDP_TUNNEL_DATA pdu) { if(pdu.HigherLayerData != null && pdu.HigherLayerData.Length > 0) { if (Received != null) { Received(pdu.HigherLayerData); } } }
/// <summary> /// Create Tunnel Data PDU /// </summary> /// <param name="Payload"></param> /// <param name="SubheaderList"></param> /// <returns></returns> public RDP_TUNNEL_DATA CreateTunnelDataPdu(byte[] Payload, List<byte[]> SubheaderList = null, RDP_TUNNEL_SUBHEADER_TYPE_Values subHeaderType = RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_REQUEST) { RDP_TUNNEL_DATA tunnelData = new RDP_TUNNEL_DATA(); tunnelData.TunnelHeader = new RDP_TUNNEL_HEADER(); tunnelData.TunnelHeader.Action = RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_DATA; tunnelData.TunnelHeader.Flags = 0; tunnelData.TunnelHeader.HeaderLength = 4; if (SubheaderList != null && SubheaderList.Count > 0) { tunnelData.TunnelHeader.SubHeaders = new RDP_TUNNEL_SUBHEADER[SubheaderList.Count]; for (int i = 0; i < SubheaderList.Count; i++) { tunnelData.TunnelHeader.SubHeaders[i] = new RDP_TUNNEL_SUBHEADER(); tunnelData.TunnelHeader.SubHeaders[i].SubHeaderLength = (byte)(2 + SubheaderList[i].Length); tunnelData.TunnelHeader.SubHeaders[i].SubHeaderType = subHeaderType; tunnelData.TunnelHeader.SubHeaders[i].SubHeaderData = new byte[SubheaderList[i].Length]; Array.Copy(SubheaderList[i], tunnelData.TunnelHeader.SubHeaders[i].SubHeaderData, SubheaderList[i].Length); tunnelData.TunnelHeader.HeaderLength += tunnelData.TunnelHeader.SubHeaders[i].SubHeaderLength; } } else { tunnelData.TunnelHeader.SubHeaders = null; } if (Payload != null) { tunnelData.TunnelHeader.PayloadLength = (ushort)Payload.Length; tunnelData.HigherLayerData = new byte[Payload.Length]; Array.Copy(Payload, tunnelData.HigherLayerData, Payload.Length); } else { tunnelData.TunnelHeader.PayloadLength = 0; tunnelData.HigherLayerData = null; } return tunnelData; }
/// <summary> /// Send data /// </summary> /// <param name="data"></param> public void Send(byte[] data) { RDP_TUNNEL_DATA tunnelData = this.CreateTunnelDataPdu(data, null, RDP_TUNNEL_SUBHEADER_TYPE_Values.TYPE_ID_AUTODETECT_REQUEST); this.SendRdpemtPacket(tunnelData); }
/// <summary> /// Call this method to decode byte array to MS-RDPEMT packets /// </summary> /// <param name="action">The action value in header</param> /// <param name="data">Data in bytes to be decoded</param> /// <returns>The decoded packet</returns> public static RdpemtBasePDU DecodeRdpemtPacket(byte[] data, ref int index) { if (data == null || data.Length - index < 4) { return null; } byte action = (byte)(0xF & data[index]); byte[] payloadLenData = new byte[2]; Array.Copy(data, index + 1, payloadLenData, 0, 2); if (!BitConverter.IsLittleEndian) { // Reverse the sequence if it is not little endian Array.Reverse(payloadLenData); } ushort payloadLength = BitConverter.ToUInt16(payloadLenData, 0); byte headerLength = data[index + 3]; int expectLen = payloadLength + headerLength; if (expectLen > data.Length) { return null; } byte[] toDecodeData = new byte[expectLen]; Array.Copy(data, index, toDecodeData, 0, expectLen); index += expectLen; RdpemtBasePDU rePdu = null; if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATEREQUEST) { RDP_TUNNEL_CREATEREQUEST createReq = new RDP_TUNNEL_CREATEREQUEST(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createReq); if (bResult) { rePdu = createReq; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATERESPONSE) { RDP_TUNNEL_CREATERESPONSE createRes = new RDP_TUNNEL_CREATERESPONSE(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createRes); if (bResult) { rePdu = createRes; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_DATA) { RDP_TUNNEL_DATA tunnelData = new RDP_TUNNEL_DATA(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, tunnelData); if (bResult) { rePdu = tunnelData; } } else { throw new NotSupportedException("Unknow action in RDP_TUNNEL_HEADER:" + action); } if (rePdu == null) { throw new NotSupportedException("Decode for RDPEMT PDU failed, Action:" + action); } return rePdu; }
/// <summary> /// Call this method to decode byte array to MS-RDPEMT packets /// </summary> /// <param name="action">The action value in header</param> /// <param name="data">Data in bytes to be decoded</param> /// <returns>The decoded packet</returns> public static RdpemtBasePDU DecodeRdpemtPacket(byte[] data, ref int index) { if (data == null || data.Length - index < 4) { return(null); } byte action = (byte)(0xF & data[index]); byte[] payloadLenData = new byte[2]; Array.Copy(data, index + 1, payloadLenData, 0, 2); if (!BitConverter.IsLittleEndian) { // Reverse the sequence if it is not little endian Array.Reverse(payloadLenData); } ushort payloadLength = BitConverter.ToUInt16(payloadLenData, 0); byte headerLength = data[index + 3]; int expectLen = payloadLength + headerLength; if (expectLen > data.Length) { return(null); } byte[] toDecodeData = new byte[expectLen]; Array.Copy(data, index, toDecodeData, 0, expectLen); index += expectLen; RdpemtBasePDU rePdu = null; if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATEREQUEST) { RDP_TUNNEL_CREATEREQUEST createReq = new RDP_TUNNEL_CREATEREQUEST(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createReq); if (bResult) { rePdu = createReq; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_CREATERESPONSE) { RDP_TUNNEL_CREATERESPONSE createRes = new RDP_TUNNEL_CREATERESPONSE(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, createRes); if (bResult) { rePdu = createRes; } } else if (action == (byte)RDP_TUNNEL_ACTION_Values.RDPTUNNEL_ACTION_DATA) { RDP_TUNNEL_DATA tunnelData = new RDP_TUNNEL_DATA(); bool bResult = PduMarshaler.Unmarshal(toDecodeData, tunnelData); if (bResult) { rePdu = tunnelData; } } else { throw new NotSupportedException("Unknow action in RDP_TUNNEL_HEADER:" + action); } if (rePdu == null) { throw new NotSupportedException("Decode for RDPEMT PDU failed, Action:" + action); } return(rePdu); }