From f458f2f7ee89e1864bc2d7b9351ffacf775c36b2 Mon Sep 17 00:00:00 2001 From: "Jason Williams (BEARDED XBOX DEV)" Date: Thu, 14 Jun 2018 09:22:23 -0700 Subject: [PATCH 1/9] Minor fix to avoid exception in error parsing case --- .../Exceptions/DevicePortalException.cs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Exceptions/DevicePortalException.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Exceptions/DevicePortalException.cs index 7ecba034..be9154aa 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Exceptions/DevicePortalException.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Exceptions/DevicePortalException.cs @@ -153,18 +153,21 @@ public static async Task CreateAsync( { HttpErrorResponse errorResponse = DevicePortal.ReadJsonStream(dataStream); - error.HResult = errorResponse.ErrorCode; - error.Reason = errorResponse.ErrorMessage; - - // If we didn't get the Hresult and reason from these properties, try the other ones. - if (error.HResult == 0) - { - error.HResult = errorResponse.Code; - } - - if (string.IsNullOrEmpty(error.Reason)) + if (errorResponse != null) { - error.Reason = errorResponse.Reason; + error.HResult = errorResponse.ErrorCode; + error.Reason = errorResponse.ErrorMessage; + + // If we didn't get the Hresult and reason from these properties, try the other ones. + if (error.HResult == 0) + { + error.HResult = errorResponse.Code; + } + + if (string.IsNullOrEmpty(error.Reason)) + { + error.Reason = errorResponse.Reason; + } } } } From 06b65c173bb79890a3134d0e183e211408a50069 Mon Sep 17 00:00:00 2001 From: Jason Williams Date: Thu, 14 Jun 2018 09:25:07 -0700 Subject: [PATCH 2/9] Better app streaming and StyleCop fixes (#283) * Refactored use of async. No tight while-loops but instead using await and continue on background threads. * Remove use of .Wait() to avoid potential deadlocks. increase use of ConfigureAwait, and remove await where not needed * Simplified async code. Instead of forwarding to tasks and have to switch to ui thread, it's easier to just await and continue on the same thread here. * First stab at using a custom http multipart content to avoid large memory consumption when installing large files. * Changed implementation to Explicit * Use proper separation between attachments * Resolve header ordering issue in .NET, and force non-quoted boundary * Boundary fixes. * Update last merge * StyleCop fixups * Added streaming improvements to xbox's loose deploy as well --- .../Settings.StyleCop | 824 ++++++++++++++++++ Samples/SampleWdpClient/Settings.StyleCop | 824 ++++++++++++++++++ Samples/XboxWdpDriver/XboxWdpDriver.csproj | 1 - .../MockDataGenerator.csproj | 1 - .../UnitTestProject/UnitTestProject.csproj | 4 +- .../WDPMockImplementations/RestPost.cs | 18 +- .../Core/AppDeployment.cs | 65 +- .../Core/Power.cs | 2 +- .../DevicePortal.cs | 1 - .../HttpRest/ResponseHelpers.cs | 73 +- .../HttpRest/RestPost.cs | 29 +- .../WindowsDevicePortalWrapper.Shared.shproj | 1 - .../HttpRest/HttpMultipartFileContent.cs | 214 +++++ .../HttpRest/RestPost.cs | 17 +- .../Settings.StyleCop | 2 +- ...evicePortalWrapper.UniversalWindows.csproj | 4 +- .../HttpRest/HttpMultipartFileContent.cs | 141 +++ .../HttpRest/RestPost.cs | 18 +- .../WindowsDevicePortalWrapper.csproj | 4 +- 19 files changed, 2114 insertions(+), 129 deletions(-) create mode 100644 Samples/SampleWdpClient.UniversalWindows/Settings.StyleCop create mode 100644 Samples/SampleWdpClient/Settings.StyleCop create mode 100644 WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.UniversalWindows/HttpRest/HttpMultipartFileContent.cs create mode 100644 WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/HttpMultipartFileContent.cs diff --git a/Samples/SampleWdpClient.UniversalWindows/Settings.StyleCop b/Samples/SampleWdpClient.UniversalWindows/Settings.StyleCop new file mode 100644 index 00000000..6d356bc9 --- /dev/null +++ b/Samples/SampleWdpClient.UniversalWindows/Settings.StyleCop @@ -0,0 +1,824 @@ + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + \ No newline at end of file diff --git a/Samples/SampleWdpClient/Settings.StyleCop b/Samples/SampleWdpClient/Settings.StyleCop new file mode 100644 index 00000000..6d356bc9 --- /dev/null +++ b/Samples/SampleWdpClient/Settings.StyleCop @@ -0,0 +1,824 @@ + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + False + + + + + + + \ No newline at end of file diff --git a/Samples/XboxWdpDriver/XboxWdpDriver.csproj b/Samples/XboxWdpDriver/XboxWdpDriver.csproj index f1cddabb..f4b9e950 100644 --- a/Samples/XboxWdpDriver/XboxWdpDriver.csproj +++ b/Samples/XboxWdpDriver/XboxWdpDriver.csproj @@ -78,7 +78,6 @@ - - + \ No newline at end of file diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/HttpMultipartFileContent.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/HttpMultipartFileContent.cs new file mode 100644 index 00000000..f036ca1f --- /dev/null +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/HttpMultipartFileContent.cs @@ -0,0 +1,141 @@ +//---------------------------------------------------------------------------------------------- +// +// Licensed under the MIT License. See LICENSE.TXT in the project root license information. +// +//---------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.Tools.WindowsDevicePortal +{ + /// + /// This class mimicks , with two main differences + /// 1. Simplifies posting files by taking file names instead of managing streams. + /// 2. Does not quote the boundaries, due to a bug in the device portal + /// + internal sealed class HttpMultipartFileContent : HttpContent + { + /// + /// List of items to transfer + /// + private List items = new List(); + + /// + /// Boundary string + /// + private string boundaryString; + + /// + /// Initializes a new instance of the class. + /// + public HttpMultipartFileContent() : this(Guid.NewGuid().ToString()) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The boundary string for file content. + public HttpMultipartFileContent(string boundary) + { + this.boundaryString = boundary; + Headers.TryAddWithoutValidation("Content-Type", string.Format("multipart/form-data; boundary={0}", this.boundaryString)); + } + + /// + /// Adds a file to the list of items to transfer + /// + /// The name of the file to add + public void Add(string filename) + { + if (filename != null) + { + this.items.Add(filename); + } + } + + /// + /// Adds a range of files to the list of items to transfer + /// + /// List of files to add + public void AddRange(IEnumerable filenames) + { + if (filenames != null) + { + this.items.AddRange(filenames); + } + } + + /// + /// Serializes the stream. + /// + /// Serialized Stream + /// The Transport Context + /// Task tracking progress + protected override async Task SerializeToStreamAsync(Stream outStream, TransportContext context) + { + var boundary = Encoding.ASCII.GetBytes($"--{boundaryString}\r\n"); + var newline = Encoding.ASCII.GetBytes("\r\n"); + foreach (var item in this.items) + { + outStream.Write(boundary, 0, boundary.Length); + var headerdata = GetFileHeader(new FileInfo(item)); + outStream.Write(headerdata, 0, headerdata.Length); + + using (var file = File.OpenRead(item)) + { + await file.CopyToAsync(outStream); + } + + outStream.Write(newline, 0, newline.Length); + await outStream.FlushAsync(); + } + + // Close the installation request data. + boundary = Encoding.ASCII.GetBytes($"--{boundaryString}--\r\n"); + outStream.Write(boundary, 0, boundary.Length); + await outStream.FlushAsync(); + } + + /// + /// Computes required length for the transfer. + /// + /// The computed length value + /// Whether or not the length was successfully computed + protected override bool TryComputeLength(out long length) + { + length = 0; + var boundaryLength = Encoding.ASCII.GetBytes(string.Format("--{0}\r\n", this.boundaryString)).Length; + foreach (var item in this.items) + { + var headerdata = GetFileHeader(new FileInfo(item)); + length += boundaryLength + headerdata.Length + new FileInfo(item).Length + 2; + } + + length += boundaryLength + 2; + return true; + } + + /// + /// Gets the file header for the transfer + /// + /// Information about the file + /// A byte array with the file header information + private static byte[] GetFileHeader(FileInfo info) + { + string contentType = "application/octet-stream"; + if (info.Extension.ToLower() == ".cer") + { + contentType = "application/x-x509-ca-cert"; + } + + return Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{0}\"\r\nContent-Type: {1}\r\n\r\n", info.Name, contentType)); + } + } +} \ No newline at end of file diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs index 069c77fb..e2ad141c 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs @@ -30,8 +30,7 @@ public async Task PostAsync( string requestStreamContentType = null) { StreamContent requestContent = null; - MemoryStream responseDataStream = null; - + if (requestStream != null) { requestContent = new StreamContent(requestStream); @@ -39,6 +38,21 @@ public async Task PostAsync( requestContent.Headers.TryAddWithoutValidation(ContentTypeHeaderName, requestStreamContentType); } + return await this.PostAsync(uri, requestContent); + } + + /// + /// Submits the http post request to the specified uri. + /// + /// The uri to which the post request will be issued. + /// Optional content containing data for the request body. + /// Task tracking the completion of the POST request + public async Task PostAsync( + Uri uri, + HttpContent requestContent) + { + MemoryStream responseDataStream = null; + WebRequestHandler requestSettings = new WebRequestHandler(); requestSettings.UseDefaultCredentials = false; requestSettings.Credentials = this.deviceConnection.Credentials; diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.csproj b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.csproj index 8b614814..c64db6be 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.csproj +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.csproj @@ -57,6 +57,7 @@ + @@ -69,7 +70,6 @@ - - + \ No newline at end of file From 1e2b34258f7888f88cdca26b47dca04425242720 Mon Sep 17 00:00:00 2001 From: Namrata Rajiv Kedia Date: Tue, 24 Jul 2018 08:40:39 -0700 Subject: [PATCH 3/9] softap (#291) --- .../WindowsDevicePortalWrapper.Shared/IoT/IoTOnboarding.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/IoTOnboarding.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/IoTOnboarding.cs index bfd6e21b..0b4b5118 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/IoTOnboarding.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/IoT/IoTOnboarding.cs @@ -55,7 +55,7 @@ public async Task SetSoftApSettingsAsync(string softApStatus, string softApSsid, { await this.PostAsync( SoftAPSettingsApi, - string.Format("SoftApEnabled={0}&SoftApSsid={1}&SoftApPassword={2}", Utilities.Hex64Encode(softApStatus), Utilities.Hex64Encode(softApSsid), Utilities.Hex64Encode(softApPassword))); + string.Format("SoftAPEnabled={0}&SoftApSsid={1}&SoftApPassword={2}", Utilities.Hex64Encode(softApStatus), Utilities.Hex64Encode(softApSsid), Utilities.Hex64Encode(softApPassword))); } /// From aaa43d52ef84955af2af3e8fce1e56d5894964e6 Mon Sep 17 00:00:00 2001 From: Andrey Chistyakov <31440405+AndreyChistyakov@users.noreply.github.com> Date: Fri, 7 Jun 2019 23:33:09 +0100 Subject: [PATCH 4/9] Origin Address changed according MS policies for Device Portal (#297) * Origin Address changed according MS policies for Device Portal * support for non-default port --- .../HttpRest/WebSocket.cs | 9 ++++++++- .../WindowsDevicePortalWrapper/HttpRest/WebSocket.cs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.UniversalWindows/HttpRest/WebSocket.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.UniversalWindows/HttpRest/WebSocket.cs index 64e26ff1..e3fe6618 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.UniversalWindows/HttpRest/WebSocket.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.UniversalWindows/HttpRest/WebSocket.cs @@ -74,7 +74,14 @@ private async Task ConnectInternalAsync( this.websocket.Control.ServerCredential = cred; } - this.websocket.SetRequestHeader("Origin", this.deviceConnection.Connection.AbsoluteUri); + //Origin address must be especially cooked to pass through all Device Portal checks + string OriginAddress = this.deviceConnection.Connection.Scheme + "://" + this.deviceConnection.Connection.Host; + if ((this.deviceConnection.Connection.Scheme == "http" && this.deviceConnection.Connection.Port != 80) || + (this.deviceConnection.Connection.Scheme == "https" && this.deviceConnection.Connection.Port != 443)) + { + OriginAddress += ":" + this.deviceConnection.Connection.Port; + } + this.websocket.SetRequestHeader("Origin", OriginAddress); await this.websocket.ConnectAsync(endpoint); diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/WebSocket.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/WebSocket.cs index 14de4cd4..384cda3a 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/WebSocket.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/WebSocket.cs @@ -73,7 +73,14 @@ private async Task ConnectInternalAsync( this.websocket = new ClientWebSocket(); this.websocket.Options.UseDefaultCredentials = false; this.websocket.Options.Credentials = this.deviceConnection.Credentials; - this.websocket.Options.SetRequestHeader("Origin", this.deviceConnection.Connection.AbsoluteUri); + //Origin address must be especially cooked to pass through all Device Portal checks + string OriginAddress = this.deviceConnection.Connection.Scheme + "://" + this.deviceConnection.Connection.Host; + if((this.deviceConnection.Connection.Scheme == "http" && this.deviceConnection.Connection.Port != 80) || + (this.deviceConnection.Connection.Scheme == "https" && this.deviceConnection.Connection.Port != 443)) + { + OriginAddress += ":" + this.deviceConnection.Connection.Port; + } + this.websocket.Options.SetRequestHeader("Origin", OriginAddress); // There is no way to set a ServerCertificateValidationCallback for a single web socket, hence the workaround. ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors) From 3d83c879f7c277a1aefe74da3ac526f76d2fbee6 Mon Sep 17 00:00:00 2001 From: mgurlitz Date: Wed, 17 Jul 2019 12:10:02 -0700 Subject: [PATCH 5/9] Fix Xbox One platform detection (#298) --- .../Core/OsInformation.cs | 38 +++++++------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs index 9ef6ccb6..110e4b1f 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs @@ -206,8 +206,6 @@ public DevicePortalPlatforms Platform { get { - DevicePortalPlatforms platform = DevicePortalPlatforms.Unknown; - try { // MinnowBoard Max model no. can change based on firmware @@ -216,31 +214,28 @@ public DevicePortalPlatforms Platform return DevicePortalPlatforms.IoTMinnowboardMax; } - switch (this.PlatformName) + // Xbox One platform names may refer to devkit + if (this.PlatformName.Contains("Xbox One")) { - case "Xbox One": - platform = DevicePortalPlatforms.XboxOne; - break; + return DevicePortalPlatforms.XboxOne; + } + switch (this.PlatformName) + { case "SBC": - platform = DevicePortalPlatforms.IoTDragonboard410c; - break; + return DevicePortalPlatforms.IoTDragonboard410c; case "Raspberry Pi 2": - platform = DevicePortalPlatforms.IoTRaspberryPi2; - break; + return DevicePortalPlatforms.IoTRaspberryPi2; case "Raspberry Pi 3": - platform = DevicePortalPlatforms.IoTRaspberryPi3; - break; + return DevicePortalPlatforms.IoTRaspberryPi3; case "Virtual Machine": - platform = DevicePortalPlatforms.VirtualMachine; - break; + return DevicePortalPlatforms.VirtualMachine; default: - platform = (DevicePortalPlatforms)Enum.Parse(typeof(DevicePortalPlatforms), this.PlatformName); - break; + return (DevicePortalPlatforms)Enum.Parse(typeof(DevicePortalPlatforms), this.PlatformName); } } catch @@ -250,20 +245,15 @@ public DevicePortalPlatforms Platform case "Enterprise": case "Home": case "Professional": - platform = DevicePortalPlatforms.Windows; - break; + return DevicePortalPlatforms.Windows; case "Mobile": - platform = DevicePortalPlatforms.Mobile; - break; + return DevicePortalPlatforms.Mobile; default: - platform = DevicePortalPlatforms.Unknown; - break; + return DevicePortalPlatforms.Unknown; } } - - return platform; } } } From 2c67e0b8c9c6a0fbe386142228242671719ae848 Mon Sep 17 00:00:00 2001 From: Andrey Chistyakov <31440405+AndreyChistyakov@users.noreply.github.com> Date: Tue, 3 Dec 2019 17:33:28 +0000 Subject: [PATCH 6/9] Support large files downloading (like crashdumps) from device (#302) * Support HoloLens 2 devices * Delayed HTTP GET operation * Allow unsafe HTTP headers for support large file downloading in Device Portal * Removing unsupported Length parameter from delayed GET buffer * fix unit tests * fix post unexisting file test * support for uploading large files --- .../UnitTestProject/MockHttpResponder.cs | 4 ++ .../Core/OsInformation.cs | 8 +++ .../Core/WindowsErrorReporting.cs | 9 +++- .../DevicePortal.cs | 23 +++++++++ .../HoloLens/MixedRealityCapture.cs | 8 ++- .../HoloLens/PerceptionSimulationPlayback.cs | 2 - .../HoloLens/PerceptionSimulationRecording.cs | 10 ++-- .../HttpRest/ResponseHelpers.cs | 3 +- .../CertificateHandling.cs | 10 ++-- .../HttpRest/RestGet.cs | 50 +++++++++---------- .../HttpRest/RestPost.cs | 2 + 11 files changed, 89 insertions(+), 40 deletions(-) diff --git a/WindowsDevicePortalWrapper/UnitTestProject/MockHttpResponder.cs b/WindowsDevicePortalWrapper/UnitTestProject/MockHttpResponder.cs index d80a2d72..a4a0e6f3 100644 --- a/WindowsDevicePortalWrapper/UnitTestProject/MockHttpResponder.cs +++ b/WindowsDevicePortalWrapper/UnitTestProject/MockHttpResponder.cs @@ -134,6 +134,10 @@ public async Task GetAsync(Uri uri) /// Async task returning the response. public async Task PostAsync(Uri uri, HttpContent content) { + if(content != null) + { + await content.ReadAsByteArrayAsync(); + } Task task = new Task(() => this.HttpStoredResponse(uri, HttpMethods.Post)); task.Start(); diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs index 110e4b1f..f495cc74 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/OsInformation.cs @@ -56,6 +56,11 @@ public enum DevicePortalPlatforms /// HoloLens, + /// + /// HoloLens 2 platform + /// + HoloLens2, + /// /// Xbox One platform /// @@ -234,6 +239,9 @@ public DevicePortalPlatforms Platform case "Virtual Machine": return DevicePortalPlatforms.VirtualMachine; + case "HoloLens 2": + return DevicePortalPlatforms.HoloLens2; + default: return (DevicePortalPlatforms)Enum.Parse(typeof(DevicePortalPlatforms), this.PlatformName); } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/WindowsErrorReporting.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/WindowsErrorReporting.cs index 9124a528..bcd2121d 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/WindowsErrorReporting.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/Core/WindowsErrorReporting.cs @@ -89,8 +89,13 @@ public async Task GetWindowsErrorReportingFileAsync(string user, string byte[] werFile = null; using (Stream stream = await this.GetAsync(uri)) { - werFile = new byte[stream.Length]; - stream.Read(werFile, 0, werFile.Length); + using (MemoryStream outStream = new MemoryStream()) + { + await outStream.CopyToAsync(outStream); + + werFile = new byte[outStream.Length]; + await stream.ReadAsync(werFile, 0, werFile.Length); + } } return werFile; diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/DevicePortal.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/DevicePortal.cs index 259c3a07..2deeda13 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/DevicePortal.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/DevicePortal.cs @@ -11,6 +11,7 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Reflection; #endif // !WINDOWS_UWP #if WINDOWS_UWP using System.Runtime.InteropServices.WindowsRuntime; @@ -61,12 +62,34 @@ public partial class DevicePortal private IDevicePortalConnection deviceConnection; #if !WINDOWS_UWP + // Enable/disable useUnsafeHeaderParsing. + // See https://social.msdn.microsoft.com/Forums/en-US/ff098248-551c-4da9-8ba5-358a9f8ccc57/how-do-i-enable-useunsafeheaderparsing-from-code-net-20?forum=netfxnetcom + private static bool ToggleAllowUnsafeHeaderParsing(bool enable) + { + Type settingsSectionType = Assembly.GetAssembly(typeof(System.Net.Configuration.SettingsSection))?.GetType("System.Net.Configuration.SettingsSectionInternal"); + if (settingsSectionType == null) { return false; } + + object anInstance = settingsSectionType.InvokeMember("Section", BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.NonPublic, null, null, new object[] { }); + if (anInstance == null) { return false; } + + FieldInfo aUseUnsafeHeaderParsing = settingsSectionType.GetField("useUnsafeHeaderParsing", BindingFlags.NonPublic | BindingFlags.Instance); + if (aUseUnsafeHeaderParsing == null) { return false; } + + aUseUnsafeHeaderParsing.SetValue(anInstance, enable); + + return true; + } + /// /// Initializes static members of the class. /// static DevicePortal() { System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; + if (!ToggleAllowUnsafeHeaderParsing(true)) + { + Console.WriteLine("Failed to enable useUnsafeHeaderParsing"); + } } #endif diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/MixedRealityCapture.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/MixedRealityCapture.cs index 848f1458..7f440fc7 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/MixedRealityCapture.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/MixedRealityCapture.cs @@ -207,8 +207,12 @@ public async Task GetMrcFileDataAsync( using (Stream dataStream = await this.GetAsync(uri)) { - dataBytes = new byte[dataStream.Length]; - dataStream.Read(dataBytes, 0, dataBytes.Length); + using (MemoryStream outStream = new MemoryStream()) + { + await dataStream.CopyToAsync(outStream); + dataBytes = new byte[outStream.Length]; + await outStream.ReadAsync(dataBytes, 0, dataBytes.Length); + } } return dataBytes; diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs index 2ce05f07..0529f401 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs @@ -192,8 +192,6 @@ public async Task GetHolographicSimulationP using (Stream dataStream = await this.GetAsync(uri)) { - if ((dataStream != null) && - (dataStream.Length != 0)) { // Try to get the session state. try diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs index a97d11e4..fdb809d3 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs @@ -101,8 +101,6 @@ public async Task StopHolographicSimulationRecordingAsync() using (Stream dataStream = await this.GetAsync(uri)) { - if ((dataStream != null) && - (dataStream.Length != 0)) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationError)); HolographicSimulationError error = null; @@ -123,8 +121,12 @@ public async Task StopHolographicSimulationRecordingAsync() } // Getting here indicates that we have file data to return. - dataBytes = new byte[dataStream.Length]; - dataStream.Read(dataBytes, 0, dataBytes.Length); + using (MemoryStream outStream = new MemoryStream()) + { + await dataStream.CopyToAsync(outStream); + dataBytes = new byte[outStream.Length]; + await outStream.ReadAsync(dataBytes, 0, dataBytes.Length); + } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs index 165a88b8..65b2fa05 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs @@ -43,8 +43,7 @@ public static T ReadJsonStream(Stream dataStream, DataContractJsonSerializerS using (dataStream) { - if ((dataStream != null) && - (dataStream.Length != 0)) + if (dataStream != null) { JsonFormatCheck(dataStream); diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs index 831e5232..20b124a6 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs @@ -40,10 +40,14 @@ public async Task GetRootDeviceCertificateAsync() using (Stream stream = await this.GetAsync(uri)) { - using (BinaryReader reader = new BinaryReader(stream)) + using (MemoryStream outStream = new MemoryStream()) { - byte[] certData = reader.ReadBytes((int)stream.Length); - certificate = new X509Certificate2(certData); + await stream.CopyToAsync(outStream); + using (BinaryReader reader = new BinaryReader(outStream)) + { + byte[] certData = reader.ReadBytes((int)outStream.Length); + certificate = new X509Certificate2(certData); + } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestGet.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestGet.cs index 78dc22a7..616457b6 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestGet.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestGet.cs @@ -24,39 +24,39 @@ public partial class DevicePortal public async Task GetAsync( Uri uri) { - MemoryStream dataStream = null; - - WebRequestHandler handler = new WebRequestHandler(); - handler.UseDefaultCredentials = false; - handler.Credentials = this.deviceConnection.Credentials; - handler.ServerCertificateValidationCallback = this.ServerCertificateValidation; - - using (HttpClient client = new HttpClient(handler)) + HttpClient client = null; + HttpResponseMessage response = null; + try { + WebRequestHandler handler = new WebRequestHandler(); + handler.UseDefaultCredentials = false; + handler.Credentials = this.deviceConnection.Credentials; + handler.ServerCertificateValidationCallback = this.ServerCertificateValidation; + + client = new HttpClient(handler); this.ApplyHttpHeaders(client, HttpMethods.Get); - using (HttpResponseMessage response = await client.GetAsync(uri).ConfigureAwait(false)) + response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false); + if (!response.IsSuccessStatusCode) { - if (!response.IsSuccessStatusCode) - { - throw await DevicePortalException.CreateAsync(response); - } - - this.RetrieveCsrfToken(response); - - using (HttpContent content = response.Content) - { - dataStream = new MemoryStream(); + throw await DevicePortalException.CreateAsync(response); + } - await content.CopyToAsync(dataStream).ConfigureAwait(false); + this.RetrieveCsrfToken(response); - // Ensure we return with the stream pointed at the origin. - dataStream.Position = 0; - } + if (response.Content == null) + { + throw new DevicePortalException(System.Net.HttpStatusCode.NoContent, "", uri); } - } - return dataStream; + return await response.Content.ReadAsStreamAsync(); + } + catch (Exception) + { + response?.Dispose(); + client?.Dispose(); + throw; + } } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs index e2ad141c..5eec2235 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs @@ -60,6 +60,8 @@ public async Task PostAsync( using (HttpClient client = new HttpClient(requestSettings)) { + client.Timeout = TimeSpan.FromMilliseconds(-1); + this.ApplyHttpHeaders(client, HttpMethods.Post); using (HttpResponseMessage response = await client.PostAsync(uri, requestContent).ConfigureAwait(false)) From fc217fac80ba16aca338fa8d8204b4fb1f412e2f Mon Sep 17 00:00:00 2001 From: Andrey Chistyakov <31440405+AndreyChistyakov@users.noreply.github.com> Date: Wed, 29 Jan 2020 01:03:03 +0000 Subject: [PATCH 7/9] Bugfix of launch params reading (#303) --- .../HoloLens/PerceptionSimulationPlayback.cs | 32 +++++++----- .../HoloLens/PerceptionSimulationRecording.cs | 49 ++++++++++--------- .../HttpRest/ResponseHelpers.cs | 32 +++++++----- 3 files changed, 66 insertions(+), 47 deletions(-) diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs index 0529f401..6d3e175b 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs @@ -192,21 +192,27 @@ public async Task GetHolographicSimulationP using (Stream dataStream = await this.GetAsync(uri)) { + using (MemoryStream outStream = new MemoryStream()) { - // Try to get the session state. - try + dataStream.CopyTo(outStream); + if (outStream.Length != 0) { - DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationPlaybackSessionState)); - HolographicSimulationPlaybackSessionState sessionState = (HolographicSimulationPlaybackSessionState)serializer.ReadObject(dataStream); - playbackState = sessionState.State; - } - catch - { - // We did not receive the session state, check to see if we received a simulation error. - dataStream.Position = 0; - DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationError)); - HolographicSimulationError error = (HolographicSimulationError)serializer.ReadObject(dataStream); - throw new InvalidOperationException(error.Reason); + outStream.Seek(0, SeekOrigin.Begin); + // Try to get the session state. + try + { + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationPlaybackSessionState)); + HolographicSimulationPlaybackSessionState sessionState = (HolographicSimulationPlaybackSessionState)serializer.ReadObject(dataStream); + playbackState = sessionState.State; + } + catch + { + // We did not receive the session state, check to see if we received a simulation error. + dataStream.Position = 0; + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationError)); + HolographicSimulationError error = (HolographicSimulationError)serializer.ReadObject(dataStream); + throw new InvalidOperationException(error.Reason); + } } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs index fdb809d3..65bb5cce 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationRecording.cs @@ -101,31 +101,36 @@ public async Task StopHolographicSimulationRecordingAsync() using (Stream dataStream = await this.GetAsync(uri)) { + if (dataStream != null) { - DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationError)); - HolographicSimulationError error = null; - - try - { - // Try to get / interpret an error response. - error = (HolographicSimulationError)serializer.ReadObject(dataStream); - } - catch - { - } - - if (error != null) - { - // We received an error response. - throw new InvalidOperationException(error.Reason); - } - - // Getting here indicates that we have file data to return. using (MemoryStream outStream = new MemoryStream()) { - await dataStream.CopyToAsync(outStream); - dataBytes = new byte[outStream.Length]; - await outStream.ReadAsync(dataBytes, 0, dataBytes.Length); + dataStream.CopyTo(outStream); + if (outStream.Length != 0) + { + outStream.Seek(0, SeekOrigin.Begin); + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationError)); + HolographicSimulationError error = null; + + try + { + // Try to get / interpret an error response. + error = (HolographicSimulationError)serializer.ReadObject(outStream); + } + catch + { + } + + if (error != null) + { + // We received an error response. + throw new InvalidOperationException(error.Reason); + } + + // Getting here indicates that we have file data to return. + dataBytes = new byte[outStream.Length]; + await outStream.ReadAsync(dataBytes, 0, dataBytes.Length); + } } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs index 65b2fa05..15f53259 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HttpRest/ResponseHelpers.cs @@ -45,20 +45,28 @@ public static T ReadJsonStream(Stream dataStream, DataContractJsonSerializerS { if (dataStream != null) { - JsonFormatCheck(dataStream); - - try - { - response = serializer.ReadObject(dataStream); - } - catch (SerializationException) + using (MemoryStream outStream = new MemoryStream()) { - // Assert on serialization failure. - Debug.Assert(false, "Serialization failure encountered. Check DataContract types for a possible mismatch between expectations and reality"); - throw; + dataStream.CopyTo(outStream); + if (outStream.Length != 0) + { + outStream.Seek(0, SeekOrigin.Begin); + JsonFormatCheck(outStream); + + try + { + response = serializer.ReadObject(outStream); + } + catch (SerializationException ex) + { + // Assert on serialization failure. + Debug.Assert(false, "Serialization failure encountered. Check DataContract types for a possible mismatch between expectations and reality"); + throw; + } + + data = (T)response; + } } - - data = (T)response; } } From f9ce07c6674018d1195875f17ba13eba993baf86 Mon Sep 17 00:00:00 2001 From: Andrey Chistyakov <31440405+AndreyChistyakov@users.noreply.github.com> Date: Wed, 29 Jan 2020 19:03:19 +0000 Subject: [PATCH 8/9] Return null instead of empty stream from Post/Delete/Put requests (#306) --- .../HoloLens/PerceptionSimulationPlayback.cs | 39 ++++++++++--------- .../HttpRest/RestDelete.cs | 4 ++ .../HttpRest/RestPost.cs | 4 ++ .../HttpRest/RestPut.cs | 4 ++ 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs index 6d3e175b..70045303 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper.Shared/HoloLens/PerceptionSimulationPlayback.cs @@ -1,4 +1,4 @@ -//---------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------- // // Licensed under the MIT License. See LICENSE.TXT in the project root license information. // @@ -192,26 +192,29 @@ public async Task GetHolographicSimulationP using (Stream dataStream = await this.GetAsync(uri)) { - using (MemoryStream outStream = new MemoryStream()) + if (dataStream != null) { - dataStream.CopyTo(outStream); - if (outStream.Length != 0) + using (MemoryStream outStream = new MemoryStream()) { - outStream.Seek(0, SeekOrigin.Begin); - // Try to get the session state. - try - { - DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationPlaybackSessionState)); - HolographicSimulationPlaybackSessionState sessionState = (HolographicSimulationPlaybackSessionState)serializer.ReadObject(dataStream); - playbackState = sessionState.State; - } - catch + dataStream.CopyTo(outStream); + if (outStream.Length != 0) { - // We did not receive the session state, check to see if we received a simulation error. - dataStream.Position = 0; - DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationError)); - HolographicSimulationError error = (HolographicSimulationError)serializer.ReadObject(dataStream); - throw new InvalidOperationException(error.Reason); + outStream.Seek(0, SeekOrigin.Begin); + // Try to get the session state. + try + { + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationPlaybackSessionState)); + HolographicSimulationPlaybackSessionState sessionState = (HolographicSimulationPlaybackSessionState)serializer.ReadObject(dataStream); + playbackState = sessionState.State; + } + catch + { + // We did not receive the session state, check to see if we received a simulation error. + dataStream.Position = 0; + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HolographicSimulationError)); + HolographicSimulationError error = (HolographicSimulationError)serializer.ReadObject(dataStream); + throw new InvalidOperationException(error.Reason); + } } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestDelete.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestDelete.cs index 12e85497..2cabaa50 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestDelete.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestDelete.cs @@ -54,6 +54,10 @@ public async Task DeleteAsync(Uri uri) // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; + if (dataStream.Length == 0) + { + dataStream = null; + } } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs index 5eec2235..459f01dc 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPost.cs @@ -83,6 +83,10 @@ public async Task PostAsync( // Ensure we return with the stream pointed at the origin. responseDataStream.Position = 0; + if (responseDataStream.Length == 0) + { + responseDataStream = null; + } } } } diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPut.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPut.cs index a85ed32b..24835d3c 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPut.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/HttpRest/RestPut.cs @@ -58,6 +58,10 @@ public async Task PutAsync( // Ensure we return with the stream pointed at the origin. dataStream.Position = 0; + if(dataStream.Length == 0) + { + dataStream = null; + } } } } From 60a10ec2237f60920511598dd7fa0c10169cccf9 Mon Sep 17 00:00:00 2001 From: artsouflMS Date: Mon, 9 Nov 2020 13:57:17 +0000 Subject: [PATCH 9/9] Reset stream on get certificate --- .../WindowsDevicePortalWrapper/CertificateHandling.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs index 20b124a6..23d2107a 100644 --- a/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs +++ b/WindowsDevicePortalWrapper/WindowsDevicePortalWrapper/CertificateHandling.cs @@ -43,6 +43,7 @@ public async Task GetRootDeviceCertificateAsync() using (MemoryStream outStream = new MemoryStream()) { await stream.CopyToAsync(outStream); + outStream.Position = 0; using (BinaryReader reader = new BinaryReader(outStream)) { byte[] certData = reader.ReadBytes((int)outStream.Length);