Example #1
0
        /// <summary>
        /// Submits the http get request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the get request will be issued.</param>
        /// <returns>Response data as a stream.</returns>
#pragma warning disable 1998
        private async Task <Stream> GetAsync(Uri uri)
        {
            IBuffer dataBuffer = null;

            HttpBaseProtocolFilter requestSettings = new HttpBaseProtocolFilter();

            requestSettings.AllowUI = false;

            if (this.deviceConnection.Credentials != null)
            {
                requestSettings.ServerCredential          = new PasswordCredential();
                requestSettings.ServerCredential.UserName = this.deviceConnection.Credentials.UserName;
                requestSettings.ServerCredential.Password = this.deviceConnection.Credentials.Password;
            }

            using (HttpClient client = new HttpClient(requestSettings))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Get);
                using (HttpResponseMessage response = await client.GetAsync(uri))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    using (IHttpContent messageContent = response.Content)
                    {
                        dataBuffer = await messageContent.ReadAsBufferAsync();
                    }
                }
            }

            return((dataBuffer != null) ? dataBuffer.AsStream() : null);
        }
Example #2
0
        /// <summary>
        /// Submits the http put request to the specified uri.
        /// </summary>
        /// <param name="client">The HTTP client to use.</param>
        /// <param name="uri">The uri to which the put request will be issued.</param>
        /// <param name="body">The HTTP content comprising the body of the request.</param>
        /// <returns>Task tracking the PUT completion.</returns>
        public static async Task <Stream> PutAsync(
            IHttpClient client,
            Uri uri,
            HttpContent body = null)
        {
            MemoryStream dataStream = null;

            using (HttpResponseMessage response = await client.PutAsync(uri, body).ConfigureAwait(false))
            {
                if (!response.IsSuccessStatusCode)
                {
                    throw await DevicePortalException.CreateAsync(response);
                }

                if (response.Content != null)
                {
                    using (HttpContent content = response.Content)
                    {
                        dataStream = new MemoryStream();

                        await content.CopyToAsync(dataStream).ConfigureAwait(false);

                        // Ensure we return with the stream pointed at the origin.
                        dataStream.Position = 0;
                    }
                }
            }

            return(dataStream);
        }
Example #3
0
        private async Task <HttpResponseMessage> Wrap(HttpMethods method, Func <HttpClient, Task <HttpResponseMessage> > func)
        {
            var handler = new HttpClientHandler
            {
                UseDefaultCredentials = false,
                Credentials           = this.credentials,
                ServerCertificateCustomValidationCallback = this.serverCertificateValidation
            };

            using (HttpClient client = new HttpClient(handler))
            {
                this.ApplyHttpHeaders(client, method);

                HttpResponseMessage response = await func(client).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                {
                    throw await DevicePortalException.CreateAsync(response);
                }

                this.RetrieveCsrfToken(response);

                return(response);
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalException"/> class.
        /// </summary>
        /// <param name="responseMessage">Http response message.</param>
        /// <param name="message">Optional exception message.</param>
        /// <param name="innerException">Optional inner exception.</param>
        /// <returns>async task</returns>
        public static async Task <DevicePortalException> CreateAsync(
            HttpResponseMessage responseMessage,
            string message           = "",
            Exception innerException = null)
        {
            DevicePortalException error = new DevicePortalException(
                responseMessage.StatusCode,
                responseMessage.ReasonPhrase,
                responseMessage.RequestMessage != null ? responseMessage.RequestMessage.RequestUri : null,
                message,
                innerException);

            try
            {
                if (responseMessage.Content != null)
                {
                    Stream dataStream = null;
                    using (HttpContent content = responseMessage.Content)
                    {
                        dataStream = new MemoryStream();

                        await content.CopyToAsync(dataStream).ConfigureAwait(false);

                        // Ensure we point the stream at the origin.
                        dataStream.Position = 0;
                    }

                    if (dataStream != null)
                    {
                        HttpErrorResponse errorResponse = dataStream.ReadJson <HttpErrorResponse>();

                        if (errorResponse != null)
                        {
                            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;
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                // Do nothing if we fail to get additional error details from the response body.
            }

            return(error);
        }
Example #5
0
        /// <summary>
        /// Submits the http post request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the post request will be issued.</param>
        /// <param name="requestStream">Optional stream containing data for the request body.</param>
        /// <param name="requestStreamContentType">The type of that request body data.</param>
        /// <returns>Task tracking the completion of the POST request</returns>
        private async Task <Stream> PostAsync(
            Uri uri,
            Stream requestStream            = null,
            string requestStreamContentType = null)
        {
            StreamContent requestContent = null;
            MemoryStream  dataStream     = null;

            if (requestStream != null)
            {
                requestContent = new StreamContent(requestStream);
                requestContent.Headers.Remove(ContentTypeHeaderName);
                requestContent.Headers.TryAddWithoutValidation(ContentTypeHeaderName, requestStreamContentType);
            }

            WebRequestHandler requestSettings = new WebRequestHandler();

            requestSettings.UseDefaultCredentials = false;
            requestSettings.Credentials           = this.deviceConnection.Credentials;
            requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation;

            using (HttpClient client = new HttpClient(requestSettings))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Post);

                Task <HttpResponseMessage> postTask = TestHelpers.MockHttpResponder.PostAsync(uri, requestContent);
                await postTask.ConfigureAwait(false);

                postTask.Wait();

                using (HttpResponseMessage response = postTask.Result)
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    if (response.Content != null)
                    {
                        using (HttpContent content = response.Content)
                        {
                            dataStream = new MemoryStream();

                            Task copyTask = content.CopyToAsync(dataStream);
                            await copyTask.ConfigureAwait(false);

                            copyTask.Wait();

                            // Ensure we return with the stream pointed at the origin.
                            dataStream.Position = 0;
                        }
                    }
                }
            }

            return(dataStream);
        }
        /// <summary>
        /// Sends a message to the server.
        /// </summary>
        /// <param name="message">The message to send.</param>
        /// <returns>The task of sending the message to the websocket</returns>
        private async Task SendMessageInternalAsync(string message)
        {
            await this.webSocketTask.ConfigureAwait(false);

            this.webSocketTask.Wait();

            using (HttpResponseMessage response = this.webSocketTask.Result)
            {
                if (!response.IsSuccessStatusCode)
                {
                    throw await DevicePortalException.CreateAsync(response);
                }
            }
        }
        /// <summary>
        /// Submits the http post request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the post request will be issued.</param>
        /// <param name="requestStream">Optional stream containing data for the request body.</param>
        /// <param name="requestStreamContentType">The type of that request body data.</param>
        /// <returns>Task tracking the completion of the POST request</returns>
#pragma warning disable 1998
        private async Task <Stream> PostAsync(
            Uri uri,
            Stream requestStream            = null,
            string requestStreamContentType = null)
        {
            HttpStreamContent requestContent = null;
            IBuffer           dataBuffer     = null;

            if (requestStream != null)
            {
                requestContent = new HttpStreamContent(requestStream.AsInputStream());
                requestContent.Headers.Remove(ContentTypeHeaderName);
                requestContent.Headers.TryAppendWithoutValidation(ContentTypeHeaderName, requestStreamContentType);
            }

            HttpBaseProtocolFilter httpFilter = new HttpBaseProtocolFilter();

            httpFilter.AllowUI = false;

            if (this.deviceConnection.Credentials != null)
            {
                httpFilter.ServerCredential          = new PasswordCredential();
                httpFilter.ServerCredential.UserName = this.deviceConnection.Credentials.UserName;
                httpFilter.ServerCredential.Password = this.deviceConnection.Credentials.Password;
            }

            using (HttpClient client = new HttpClient(httpFilter))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Post);
                using (HttpResponseMessage response = await client.PostAsync(uri, requestContent))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    this.RetrieveCsrfToken(response);

                    if (response.Content != null)
                    {
                        using (IHttpContent messageContent = response.Content)
                        {
                            dataBuffer = await messageContent.ReadAsBufferAsync();
                        }
                    }
                }
            }

            return((dataBuffer != null) ? dataBuffer.AsStream() : null);
        }
        /// <summary>
        /// Submits the http post request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the post request will be issued.</param>
        /// <param name="requestContent">Optional content containing data for the request body.</param>
        /// <returns>Task tracking the completion of the POST request</returns>
        public async Task <Stream> PostAsync(
            Uri uri,
            HttpContent requestContent)
        {
            MemoryStream responseDataStream = null;

            WebRequestHandler requestSettings = new WebRequestHandler();

            requestSettings.UseDefaultCredentials = false;
            requestSettings.Credentials           = this.deviceConnection.Credentials;
            requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation;

            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))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    this.RetrieveCsrfToken(response);

                    if (response.Content != null)
                    {
                        using (HttpContent responseContent = response.Content)
                        {
                            responseDataStream = new MemoryStream();

                            await responseContent.CopyToAsync(responseDataStream).ConfigureAwait(false);

                            // Ensure we return with the stream pointed at the origin.
                            responseDataStream.Position = 0;
                            if (responseDataStream.Length == 0)
                            {
                                responseDataStream = null;
                            }
                        }
                    }
                }
            }

            return(responseDataStream);
        }
        /// <summary>
        /// Submits the http delete request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the delete request will be issued.</param>
        /// <returns>Task tracking HTTP completion</returns>
        private async Task <Stream> DeleteAsync(Uri uri)
        {
            MemoryStream dataStream = null;

            WebRequestHandler requestSettings = new WebRequestHandler();

            requestSettings.UseDefaultCredentials = false;
            requestSettings.Credentials           = this.deviceConnection.Credentials;
            requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation;

            using (HttpClient client = new HttpClient(requestSettings))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Delete);

                Task <HttpResponseMessage> deleteTask = TestHelpers.MockHttpResponder.DeleteAsync(uri);
                await deleteTask.ConfigureAwait(false);

                deleteTask.Wait();

                using (HttpResponseMessage response = deleteTask.Result)
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    if (response.Content != null)
                    {
                        using (HttpContent content = response.Content)
                        {
                            dataStream = new MemoryStream();

                            Task copyTask = content.CopyToAsync(dataStream);
                            await copyTask.ConfigureAwait(false);

                            copyTask.Wait();

                            // Ensure we return with the stream pointed at the origin.
                            dataStream.Position = 0;
                        }
                    }
                }
            }

            return(dataStream);
        }
Example #10
0
        /// <summary>
        /// Submits the http put request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the put request will be issued.</param>
        /// <param name="body">The HTTP content comprising the body of the request.</param>
        /// <returns>Task tracking the PUT completion.</returns>
#pragma warning disable 1998
        public async Task <Stream> PutAsync(
            Uri uri,
            IHttpContent body = null)
        {
            IBuffer dataBuffer = null;

            using (var httpFilter = new HttpBaseProtocolFilter())
            {
                httpFilter.AllowUI = false;

                if (this.deviceConnection.Credentials != null)
                {
                    httpFilter.ServerCredential          = new PasswordCredential();
                    httpFilter.ServerCredential.UserName = this.deviceConnection.Credentials.UserName;
                    httpFilter.ServerCredential.Password = this.deviceConnection.Credentials.Password;
                }

                using (HttpClient client = new HttpClient(httpFilter))
                {
                    this.ApplyHttpHeaders(client, HttpMethods.Put);

                    // Send the request
                    using (HttpResponseMessage response = await client.PutAsync(uri, body))
                    {
                        if (!response.IsSuccessStatusCode)
                        {
                            throw await DevicePortalException.CreateAsync(response);
                        }

                        this.RetrieveCsrfToken(response);

                        if (response.Content != null)
                        {
                            using (IHttpContent messageContent = response.Content)
                            {
                                dataBuffer = await messageContent.ReadAsBufferAsync();
                            }
                        }
                    }
                }
            }

            return((dataBuffer != null) ? dataBuffer.AsStream() : null);
        }
        /// <summary>
        /// Submits the http put request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the put request will be issued.</param>
        /// <param name="body">The HTTP content comprising the body of the request.</param>
        /// <returns>Task tracking the PUT completion.</returns>
        private async Task <Stream> PutAsync(
            Uri uri,
            HttpContent body = null)
        {
            MemoryStream dataStream = null;

            WebRequestHandler requestSettings = new WebRequestHandler();

            requestSettings.UseDefaultCredentials = false;
            requestSettings.Credentials           = this.deviceConnection.Credentials;
            requestSettings.ServerCertificateValidationCallback = this.ServerCertificateValidation;

            using (HttpClient client = new HttpClient(requestSettings))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Put);

                // Send the request
                using (HttpResponseMessage response = await client.PutAsync(uri, body).ConfigureAwait(false))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    this.RetrieveCsrfToken(response);

                    if (response.Content != null)
                    {
                        using (HttpContent content = response.Content)
                        {
                            dataStream = new MemoryStream();

                            await content.CopyToAsync(dataStream).ConfigureAwait(false);

                            // Ensure we return with the stream pointed at the origin.
                            dataStream.Position = 0;
                        }
                    }
                }
            }

            return(dataStream);
        }
#pragma warning restore 1998

        /// <summary>
        /// Starts listening for messages from the websocket.
        /// Once they are received they are parsed and the WebSocketMessageReceived event is raised.
        /// </summary>
        /// <returns>The task of listening for messages from the websocket.</returns>
        private async Task StartListeningForMessagesInternalAsync()
        {
            this.IsListeningForMessages   = true;
            this.keepListeningForMessages = true;

            try
            {
                while (this.keepListeningForMessages)
                {
                    await this.webSocketTask.ConfigureAwait(false);

                    using (HttpResponseMessage response = this.webSocketTask.Result)
                    {
                        if (!response.IsSuccessStatusCode)
                        {
                            throw await DevicePortalException.CreateAsync(response);
                        }

                        using (HttpContent content = response.Content)
                        {
                            MemoryStream dataStream = new MemoryStream();

                            await content.CopyToAsync(dataStream).ConfigureAwait(false);

                            // Ensure we return with the stream pointed at the origin.
                            dataStream.Position = 0;

                            this.ConvertStreamToMessage(dataStream);
                        }
                    }
                }
            }
            catch
            {
            }
            finally
            {
                this.stoppedReceivingMessages.Set();
                this.IsListeningForMessages = false;
            }
        }
Example #13
0
        /// <summary>
        /// Submits the http get request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the get request will be issued.</param>
        /// <returns>Response data as a stream.</returns>
        public async Task <Stream> GetAsync(
            Uri uri)
        {
            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);

                response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                {
                    throw await DevicePortalException.CreateAsync(response);
                }

                this.RetrieveCsrfToken(response);

                if (response.Content == null)
                {
                    throw new DevicePortalException(System.Net.HttpStatusCode.NoContent, "", uri);
                }

                return(await response.Content.ReadAsStreamAsync());
            }
            catch (Exception)
            {
                response?.Dispose();
                client?.Dispose();
                throw;
            }
        }
Example #14
0
        /// <summary>
        /// Submits the http get request to the specified uri.
        /// </summary>
        /// <param name="uri">The uri to which the get request will be issued.</param>
        /// <returns>Response data as a stream.</returns>
        private async Task <Stream> 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))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Get);

                using (HttpResponseMessage response = await client.GetAsync(uri).ConfigureAwait(false))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }

                    using (HttpContent content = response.Content)
                    {
                        dataStream = new MemoryStream();

                        await content.CopyToAsync(dataStream).ConfigureAwait(false);

                        // Ensure we return with the stream pointed at the origin.
                        dataStream.Position = 0;
                    }
                }
            }

            return(dataStream);
        }
Example #15
0
        /// <summary>
        /// Gets the status of a pending or most recent installation, if any.
        /// </summary>
        /// <returns>The status</returns>
        public async Task <ApplicationInstallStatus> GetInstallStatusAsync()
        {
            ApplicationInstallStatus status = ApplicationInstallStatus.None;

            Uri uri = Utilities.BuildEndpoint(
                this.deviceConnection.Connection,
                InstallStateApi);

            WebRequestHandler handler = new WebRequestHandler();

            handler.UseDefaultCredentials = false;
            handler.Credentials           = this.deviceConnection.Credentials;
            handler.ServerCertificateValidationCallback = this.ServerCertificateValidation;

            using (HttpClient client = new HttpClient(handler))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Get);
                using (HttpResponseMessage response = await client.GetAsync(uri).ConfigureAwait(false))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            // Status code: 200
                            if (response.Content == null)
                            {
                                status = ApplicationInstallStatus.Completed;
                            }
                            else
                            {
                                // If we have a response body, it's possible this was an error
                                // (even though we got an HTTP 200).
                                Stream dataStream = null;
                                using (HttpContent content = response.Content)
                                {
                                    dataStream = new MemoryStream();

                                    await content.CopyToAsync(dataStream).ConfigureAwait(false);

                                    // Ensure we point the stream at the origin.
                                    dataStream.Position = 0;
                                }

                                if (dataStream != null)
                                {
                                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                                    HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream);

                                    if (errorResponse.Success)
                                    {
                                        status = ApplicationInstallStatus.Completed;
                                    }
                                    else
                                    {
                                        throw new DevicePortalException(response.StatusCode, errorResponse, uri);
                                    }
                                }
                                else
                                {
                                    throw new DevicePortalException(response.StatusCode, "Failed to deserialize GetInstallStatus response.");
                                }
                            }
                        }
                        else if (response.StatusCode == HttpStatusCode.NoContent)
                        {
                            // Status code: 204
                            status = ApplicationInstallStatus.InProgress;
                        }
                    }
                    else
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }
                }
            }

            return(status);
        }
        /// <summary>
        /// API for getting installation status.
        /// </summary>
        /// <returns>The status</returns>
#pragma warning disable 1998
        public async Task <ApplicationInstallStatus> GetInstallStatusAsync()
        {
            ApplicationInstallStatus status = ApplicationInstallStatus.None;

            Uri uri = Utilities.BuildEndpoint(
                this.deviceConnection.Connection,
                InstallStateApi);

            HttpBaseProtocolFilter httpFilter = new HttpBaseProtocolFilter();

            httpFilter.AllowUI = false;

            if (this.deviceConnection.Credentials != null)
            {
                httpFilter.ServerCredential          = new PasswordCredential();
                httpFilter.ServerCredential.UserName = this.deviceConnection.Credentials.UserName;
                httpFilter.ServerCredential.Password = this.deviceConnection.Credentials.Password;
            }

            using (HttpClient client = new HttpClient(httpFilter))
            {
                this.ApplyHttpHeaders(client, HttpMethods.Get);

                using (HttpResponseMessage response = await client.GetAsync(uri))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        if (response.StatusCode == HttpStatusCode.Ok)
                        {
                            // Status code: 200
                            if (response.Content != null)
                            {
                                Stream dataStream = null;

                                IBuffer dataBuffer = null;
                                using (IHttpContent messageContent = response.Content)
                                {
                                    dataBuffer = await messageContent.ReadAsBufferAsync();

                                    if (dataBuffer != null)
                                    {
                                        dataStream = dataBuffer.AsStream();
                                    }
                                }

                                if (dataStream != null)
                                {
                                    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                                    HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(dataStream);

                                    if (errorResponse.Success)
                                    {
                                        status = ApplicationInstallStatus.Completed;
                                    }
                                    else
                                    {
                                        throw new DevicePortalException(response.StatusCode, errorResponse, uri);
                                    }
                                }
                                else
                                {
                                    throw new DevicePortalException(HttpStatusCode.Conflict, "Failed to deserialize GetInstallStatus response.");
                                }
                            }
                        }
                        else if (response.StatusCode == HttpStatusCode.NoContent)
                        {
                            // Status code: 204
                            status = ApplicationInstallStatus.InProgress;
                        }
                    }
                    else
                    {
                        throw await DevicePortalException.CreateAsync(response);
                    }
                }
            }

            return(status);
        }
Example #17
0
        /// <summary>
        /// Installs an application
        /// </summary>
        /// <param name="appName">Friendly name (ex: Hello World) of the application. If this parameter is not provided, the name of the package is assumed to be the app name.</param>
        /// <param name="packageFileName">Full name of the application package file.</param>
        /// <param name="dependencyFileNames">List containing the full names of any required dependency files.</param>
        /// <param name="certificateFileName">Full name of the optional certificate file.</param>
        /// <param name="stateCheckIntervalMs">How frequently we should check the installation state.</param>
        /// <param name="timeoutInMinutes">Operation timeout.</param>
        /// <param name="uninstallPreviousVersion">Indicate whether or not the previous app version should be uninstalled prior to installing.</param>
        /// <remarks>InstallApplication sends ApplicationInstallStatus events to indicate the current progress in the installation process.
        /// Some applications may opt to not register for the AppInstallStatus event and await on InstallApplication.</remarks>
        /// <returns>Task for tracking completion of install initialization.</returns>
        public async Task InstallApplication(
            string appName,
            string packageFileName,
            List <string> dependencyFileNames,
            string certificateFileName    = null,
            short stateCheckIntervalMs    = 500,
            short timeoutInMinutes        = 15,
            bool uninstallPreviousVersion = true)
        {
            string installPhaseDescription = string.Empty;

            try
            {
                FileInfo packageFile = new FileInfo(packageFileName);

                // If appName was not provided, use the package file name
                if (string.IsNullOrEmpty(appName))
                {
                    appName = packageFile.Name;
                }

                // Uninstall the application's previous version, if one exists.
                if (uninstallPreviousVersion)
                {
                    installPhaseDescription = string.Format("Uninstalling any previous version of {0}", appName);
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.InProgress,
                        ApplicationInstallPhase.UninstallingPreviousVersion,
                        installPhaseDescription);
                    AppPackages installedApps = await this.GetInstalledAppPackages();

                    foreach (PackageInfo package in installedApps.Packages)
                    {
                        if (package.Name == appName)
                        {
                            await this.UninstallApplication(package.FullName);

                            break;
                        }
                    }
                }

                // Create the API endpoint and generate a unique boundary string.
                Uri    uri;
                string boundaryString;
                this.CreateAppInstallEndpointAndBoundaryString(
                    packageFile.Name,
                    out uri,
                    out boundaryString);

                using (MemoryStream dataStream = new MemoryStream())
                {
                    byte[] data;

                    // Copy the application package.
                    installPhaseDescription = string.Format("Copying: {0}", packageFile.Name);
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.InProgress,
                        ApplicationInstallPhase.CopyingFile,
                        installPhaseDescription);
                    data = Encoding.ASCII.GetBytes(string.Format("--{0}\r\n", boundaryString));
                    dataStream.Write(data, 0, data.Length);
                    CopyFileToRequestStream(packageFile, dataStream);

                    // Copy dependency files, if any.
                    foreach (string dependencyFile in dependencyFileNames)
                    {
                        FileInfo fi = new FileInfo(dependencyFile);
                        installPhaseDescription = string.Format("Copying: {0}", fi.Name);
                        this.SendAppInstallStatus(
                            ApplicationInstallStatus.InProgress,
                            ApplicationInstallPhase.CopyingFile,
                            installPhaseDescription);
                        data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}\r\n", boundaryString));
                        dataStream.Write(data, 0, data.Length);
                        CopyFileToRequestStream(fi, dataStream);
                    }

                    // Copy the certificate file, if provided.
                    if (!string.IsNullOrEmpty(certificateFileName))
                    {
                        FileInfo fi = new FileInfo(certificateFileName);
                        installPhaseDescription = string.Format("Copying: {0}", fi.Name);
                        this.SendAppInstallStatus(
                            ApplicationInstallStatus.InProgress,
                            ApplicationInstallPhase.CopyingFile,
                            installPhaseDescription);
                        data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}\r\n", boundaryString));
                        dataStream.Write(data, 0, data.Length);
                        CopyFileToRequestStream(fi, dataStream);
                    }

                    // Close the installation request data.
                    data = Encoding.ASCII.GetBytes(string.Format("\r\n--{0}--\r\n", boundaryString));
                    dataStream.Write(data, 0, data.Length);

                    dataStream.Position = 0;

                    string contentType = string.Format("multipart/form-data; boundary={0}", boundaryString);

                    // Make the HTTP request.
                    await this.Post(uri, dataStream, contentType);
                }

                // Poll the status until complete.
                ApplicationInstallStatus status = ApplicationInstallStatus.InProgress;
                do
                {
                    installPhaseDescription = string.Format("Installing {0}", appName);
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.InProgress,
                        ApplicationInstallPhase.Installing,
                        installPhaseDescription);

                    await Task.Delay(TimeSpan.FromMilliseconds(stateCheckIntervalMs));

                    status = await this.GetInstallStatus();
                }while (status == ApplicationInstallStatus.InProgress);

                installPhaseDescription = string.Format("{0} installed successfully", appName);
                this.SendAppInstallStatus(
                    ApplicationInstallStatus.Completed,
                    ApplicationInstallPhase.Idle,
                    installPhaseDescription);
            }
            catch (Exception e)
            {
                DevicePortalException dpe = e as DevicePortalException;

                if (dpe != null)
                {
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.Failed,
                        ApplicationInstallPhase.Idle,
                        string.Format("Failed to install {0}: {1}", appName, dpe.Reason));
                }
                else
                {
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.Failed,
                        ApplicationInstallPhase.Idle,
                        string.Format("Failed to install {0}: {1}", appName, installPhaseDescription));
                }
            }
        }
Example #18
0
        /// <summary>
        /// Installs an application
        /// </summary>
        /// <param name="appName">Friendly name (ex: Hello World) of the application. If this parameter is not provided, the name of the package is assumed to be the app name.</param>
        /// <param name="packageFileName">Full name of the application package file.</param>
        /// <param name="dependencyFileNames">List containing the full names of any required dependency files.</param>
        /// <param name="certificateFileName">Full name of the optional certificate file.</param>
        /// <param name="stateCheckIntervalMs">How frequently we should check the installation state.</param>
        /// <param name="timeoutInMinutes">Operation timeout.</param>
        /// <param name="uninstallPreviousVersion">Indicate whether or not the previous app version should be uninstalled prior to installing.</param>
        /// <remarks>InstallApplication sends ApplicationInstallStatus events to indicate the current progress in the installation process.
        /// Some applications may opt to not register for the AppInstallStatus event and await on InstallApplication.</remarks>
        /// <returns>Task for tracking completion of install initialization.</returns>
        public async Task InstallApplicationAsync(
            string appName,
            string packageFileName,
            List <string> dependencyFileNames,
            string certificateFileName    = null,
            short stateCheckIntervalMs    = 500,
            short timeoutInMinutes        = 15,
            bool uninstallPreviousVersion = true)
        {
            string installPhaseDescription = string.Empty;

            try
            {
                FileInfo packageFile = new FileInfo(packageFileName);

                // If appName was not provided, use the package file name
                if (string.IsNullOrEmpty(appName))
                {
                    appName = packageFile.Name;
                }

                // Uninstall the application's previous version, if one exists.
                if (uninstallPreviousVersion)
                {
                    installPhaseDescription = string.Format("Uninstalling any previous version of {0}", appName);
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.InProgress,
                        ApplicationInstallPhase.UninstallingPreviousVersion,
                        installPhaseDescription);
                    AppPackages installedApps = await this.GetInstalledAppPackagesAsync();

                    foreach (PackageInfo package in installedApps.Packages)
                    {
                        if (package.Name == appName)
                        {
                            await this.UninstallApplicationAsync(package.FullName);

                            break;
                        }
                    }
                }

                // Create the API endpoint and generate a unique boundary string.
                Uri    uri;
                string boundaryString;
                this.CreateAppInstallEndpointAndBoundaryString(
                    packageFile.Name,
                    out uri,
                    out boundaryString);

                installPhaseDescription = string.Format("Copying: {0}", packageFile.Name);
                this.SendAppInstallStatus(
                    ApplicationInstallStatus.InProgress,
                    ApplicationInstallPhase.CopyingFile,
                    installPhaseDescription);

                var content = new HttpMultipartFileContent();
                await content.Add(packageFile.FullName);

                await content.AddRange(dependencyFileNames);

                await content.Add(certificateFileName);

                await this.PostAsync(uri, content);

                // Poll the status until complete.
                ApplicationInstallStatus status = ApplicationInstallStatus.InProgress;
                do
                {
                    installPhaseDescription = string.Format("Installing {0}", appName);
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.InProgress,
                        ApplicationInstallPhase.Installing,
                        installPhaseDescription);

                    await Task.Delay(TimeSpan.FromMilliseconds(stateCheckIntervalMs));

                    status = await this.GetInstallStatusAsync().ConfigureAwait(false);
                }while (status == ApplicationInstallStatus.InProgress);

                installPhaseDescription = string.Format("{0} installed successfully", appName);
                this.SendAppInstallStatus(
                    ApplicationInstallStatus.Completed,
                    ApplicationInstallPhase.Idle,
                    installPhaseDescription);
            }
            catch (Exception e)
            {
                DevicePortalException dpe = e as DevicePortalException;

                if (dpe != null)
                {
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.Failed,
                        ApplicationInstallPhase.Idle,
                        string.Format("Failed to install {0}: {1}", appName, dpe.Reason));
                }
                else
                {
                    this.SendAppInstallStatus(
                        ApplicationInstallStatus.Failed,
                        ApplicationInstallPhase.Idle,
                        string.Format("Failed to install {0}: {1}", appName, installPhaseDescription));
                }
            }
        }
Example #19
0
        /// <summary>
        /// Connects to the device pointed to by IDevicePortalConnection provided in the constructor.
        /// </summary>
        /// <param name="ssid">Optional network SSID.</param>
        /// <param name="ssidKey">Optional network key.</param>
        /// <param name="updateConnection">Indicates whether we should update this connection's IP address after connecting.</param>
        /// <param name="rawManualCertificate">Allows specifying the raw certificate manually. This allows loading it from a local file or loading an override for a web proxy.</param>
        /// <remarks>Connect sends ConnectionStatus events to indicate the current progress in the connection process.
        /// Some applications may opt to not register for the ConnectionStatus event and await on Connect.</remarks>
        /// <returns>Task for tracking the connect.</returns>
        public async Task Connect(
            string ssid                 = null,
            string ssidKey              = null,
            bool updateConnection       = true,
            byte[] rawManualCertificate = null)
        {
#if WINDOWS_UWP
            this.ConnectionHttpStatusCode = HttpStatusCode.Ok;
#else
            this.ConnectionHttpStatusCode = HttpStatusCode.OK;
#endif // WINDOWS_UWP
            string connectionPhaseDescription = string.Empty;

            try
            {
                // Get the device certificate
                bool certificateAcquired = false;

                if (rawManualCertificate == null)
                {
                    try
                    {
                        connectionPhaseDescription = "Acquiring device certificate";
                        this.SendConnectionStatus(
                            DeviceConnectionStatus.Connecting,
                            DeviceConnectionPhase.AcquiringCertificate,
                            connectionPhaseDescription);

                        this.deviceConnection.SetDeviceCertificate(await this.GetDeviceCertificate());

                        certificateAcquired = true;
                    }
                    catch
                    {
                        // This device does not support the root certificate endpoint.
                        this.SendConnectionStatus(
                            DeviceConnectionStatus.Connecting,
                            DeviceConnectionPhase.AcquiringCertificate,
                            "No device certificate available");
                    }
                }
                else
                {
#if WINDOWS_UWP
                    this.deviceConnection.SetDeviceCertificate(new Certificate(rawManualCertificate.AsBuffer()));
#else
                    this.deviceConnection.SetDeviceCertificate(new X509Certificate2(rawManualCertificate));
#endif // WINDOWS_UWP

                    certificateAcquired = true;
                }

                // Get the device family and operating system information.
                connectionPhaseDescription = "Requesting operating system information";
                this.SendConnectionStatus(
                    DeviceConnectionStatus.Connecting,
                    DeviceConnectionPhase.RequestingOperatingSystemInformation,
                    connectionPhaseDescription);
                this.deviceConnection.Family = await this.GetDeviceFamily();

                this.deviceConnection.OsInfo = await this.GetOperatingSystemInformation();

                // Default to using HTTPS if we were successful in acquiring the device's root certificate.
                bool requiresHttps = certificateAcquired;

                // HoloLens is the only device that supports the GetIsHttpsRequired method.
                if (this.deviceConnection.OsInfo.Platform == DevicePortalPlatforms.HoloLens)
                {
                    // Check to see if HTTPS is required to communicate with this device.
                    connectionPhaseDescription = "Checking secure connection requirements";
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.DeterminingConnectionRequirements,
                        connectionPhaseDescription);
                    requiresHttps = await this.GetIsHttpsRequired();
                }

                // Connect the device to the specified network.
                if (!string.IsNullOrWhiteSpace(ssid))
                {
                    connectionPhaseDescription = string.Format("Connecting to {0} network", ssid);
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.ConnectingToTargetNetwork,
                        connectionPhaseDescription);
                    WifiInterfaces wifiInterfaces = await this.GetWifiInterfaces();

                    // TODO - consider what to do if there is more than one wifi interface on a device
                    await this.ConnectToWifiNetwork(wifiInterfaces.Interfaces[0].Guid, ssid, ssidKey);
                }

                // Get the device's IP configuration and update the connection as appropriate.
                if (updateConnection)
                {
                    connectionPhaseDescription = "Updating device connection";
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.UpdatingDeviceAddress,
                        connectionPhaseDescription);
                    this.deviceConnection.UpdateConnection(await this.GetIpConfig(), requiresHttps);
                }

                this.SendConnectionStatus(
                    DeviceConnectionStatus.Connected,
                    DeviceConnectionPhase.Idle,
                    "Device connection established");
            }
            catch (Exception e)
            {
                DevicePortalException dpe = e as DevicePortalException;

                if (dpe != null)
                {
                    this.ConnectionHttpStatusCode = dpe.StatusCode;
                }
                else
                {
                    this.ConnectionHttpStatusCode = HttpStatusCode.Conflict;
                }

                this.SendConnectionStatus(
                    DeviceConnectionStatus.Failed,
                    DeviceConnectionPhase.Idle,
                    string.Format("Device connection failed: {0}", connectionPhaseDescription));
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DevicePortalException"/> class.
        /// </summary>
        /// <param name="responseMessage">Http response message.</param>
        /// <param name="message">Optional exception message.</param>
        /// <param name="innerException">Optional inner exception.</param>
        /// <returns>async task</returns>
        public static async Task <DevicePortalException> CreateAsync(
            HttpResponseMessage responseMessage,
            string message           = "",
            Exception innerException = null)
        {
            DevicePortalException error = new DevicePortalException(
                responseMessage.StatusCode,
                responseMessage.ReasonPhrase,
                responseMessage.RequestMessage != null ? responseMessage.RequestMessage.RequestUri : null,
                message,
                innerException);

            try
            {
                if (responseMessage.Content != null)
                {
                    Stream dataStream = null;
#if !WINDOWS_UWP
                    using (HttpContent content = responseMessage.Content)
                    {
                        dataStream = new MemoryStream();

                        await content.CopyToAsync(dataStream).ConfigureAwait(false);

                        // Ensure we point the stream at the origin.
                        dataStream.Position = 0;
                    }
#else // WINDOWS_UWP
                    IBuffer dataBuffer = null;
                    using (IHttpContent messageContent = responseMessage.Content)
                    {
                        dataBuffer = await messageContent.ReadAsBufferAsync();

                        if (dataBuffer != null)
                        {
                            dataStream = dataBuffer.AsStream();
                        }
                    }
#endif  // WINDOWS_UWP

                    if (dataStream != null)
                    {
                        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(HttpErrorResponse));

                        HttpErrorResponse errorResponse = (HttpErrorResponse)serializer.ReadObject(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))
                        {
                            error.Reason = errorResponse.Reason;
                        }

                        dataStream.Dispose();
                    }
                }
            }
            catch (Exception)
            {
                // Do nothing if we fail to get additional error details from the response body.
            }

            return(error);
        }
Example #21
0
        /// <summary>
        /// Connects to the device pointed to by IDevicePortalConnection provided in the constructor.
        /// </summary>
        /// <param name="ssid">Optional network SSID.</param>
        /// <param name="ssidKey">Optional network key.</param>
        /// <param name="updateConnection">Indicates whether we should update this connection's IP address after connecting.</param>
        /// <remarks>Connect sends ConnectionStatus events to indicate the current progress in the connection process.
        /// Some applications may opt to not register for the ConnectionStatus event and await on Connect.</remarks>
        /// <returns>Task for tracking the connect.</returns>
        public async Task Connect(
            string ssid           = null,
            string ssidKey        = null,
            bool updateConnection = true)
        {
#if WINDOWS_UWP
            this.ConnectionHttpStatusCode = HttpStatusCode.Ok;
#else
            this.ConnectionHttpStatusCode = HttpStatusCode.OK;
#endif // WINDOWS_UWP
            string connectionPhaseDescription = string.Empty;

            try
            {
                // Get the device family and operating system information.
                connectionPhaseDescription = "Requesting operating system information";
                this.SendConnectionStatus(
                    DeviceConnectionStatus.Connecting,
                    DeviceConnectionPhase.RequestingOperatingSystemInformation,
                    connectionPhaseDescription);
                this.deviceConnection.Family = await this.GetDeviceFamily();

                this.deviceConnection.OsInfo = await this.GetOperatingSystemInformation();

                // Default to using HTTPS.
                bool requiresHttps = true;

                // HoloLens is the only device that supports the GetIsHttpsRequired method.
                if (this.deviceConnection.OsInfo.Platform == DevicePortalPlatforms.HoloLens)
                {
                    // Check to see if HTTPS is required to communicate with this device.
                    connectionPhaseDescription = "Checking secure connection requirements";
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.DeterminingConnectionRequirements,
                        connectionPhaseDescription);
                    requiresHttps = await this.GetIsHttpsRequired();
                }

                // Connect the device to the specified network.
                if (!string.IsNullOrWhiteSpace(ssid))
                {
                    connectionPhaseDescription = string.Format("Connecting to {0} network", ssid);
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.ConnectingToTargetNetwork,
                        connectionPhaseDescription);
                    WifiInterfaces wifiInterfaces = await this.GetWifiInterfaces();

                    // TODO - consider what to do if there is more than one wifi interface on a device
                    await this.ConnectToWifiNetwork(wifiInterfaces.Interfaces[0].Guid, ssid, ssidKey);
                }

                // Get the device's IP configuration and update the connection as appropriate.
                if (updateConnection)
                {
                    connectionPhaseDescription = "Updating device connection";
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.UpdatingDeviceAddress,
                        connectionPhaseDescription);
                    this.deviceConnection.UpdateConnection(await this.GetIpConfig(), requiresHttps);
                }

                this.SendConnectionStatus(
                    DeviceConnectionStatus.Connected,
                    DeviceConnectionPhase.Idle,
                    "Device connection established");
            }
            catch (Exception e)
            {
                DevicePortalException dpe = e as DevicePortalException;

                if (dpe != null)
                {
                    this.ConnectionHttpStatusCode    = dpe.StatusCode;
                    this.ConnectionFailedDescription = dpe.Message;
                }
                else
                {
                    this.ConnectionHttpStatusCode = HttpStatusCode.Conflict;

                    // Get to the innermost exception for our return message.
                    Exception innermostException = e;
                    while (innermostException.InnerException != null)
                    {
                        innermostException = innermostException.InnerException;
                    }

                    this.ConnectionFailedDescription = innermostException.Message;
                }

                this.SendConnectionStatus(
                    DeviceConnectionStatus.Failed,
                    DeviceConnectionPhase.Idle,
                    string.Format("Device connection failed: {0}, {1}", connectionPhaseDescription, this.ConnectionFailedDescription));
            }
        }
Example #22
0
        /// <summary>
        /// Connects to the device pointed to by IDevicePortalConnection provided in the constructor.
        /// </summary>
        /// <param name="ssid">Optional network SSID.</param>
        /// <param name="ssidKey">Optional network key.</param>
        /// <param name="updateConnection">Indicates whether we should update this connection's IP address after connecting.</param>
        /// <param name="manualCertificate">A manually provided X509 Certificate for trust validation against this device.</param>
        /// <remarks>Connect sends ConnectionStatus events to indicate the current progress in the connection process.
        /// Some applications may opt to not register for the ConnectionStatus event and await on Connect.</remarks>
        /// <returns>Task for tracking the connect.</returns>
        public async Task ConnectAsync(
            string ssid           = null,
            string ssidKey        = null,
            bool updateConnection = false,
            X509Certificate2 manualCertificate = null)
        {
            this.ConnectionHttpStatusCode = HttpStatusCode.OK;
            string connectionPhaseDescription = string.Empty;

            if (manualCertificate != null)
            {
                this.SetManualCertificate(manualCertificate);
            }

            try
            {
                // Get the device family and operating system information.
                connectionPhaseDescription = "Requesting operating system information";
                this.SendConnectionStatus(
                    DeviceConnectionStatus.Connecting,
                    DeviceConnectionPhase.RequestingOperatingSystemInformation,
                    connectionPhaseDescription);
                this.deviceConnection.Family = await this.GetDeviceFamilyAsync().ConfigureAwait(false);

                this.deviceConnection.OsInfo = await this.GetOperatingSystemInformationAsync().ConfigureAwait(false);

                // Default to using whatever was specified in the connection.
                bool requiresHttps = this.IsUsingHttps();

                // HoloLens is the only device that supports the GetIsHttpsRequired method.
                if (this.deviceConnection.OsInfo.Platform == DevicePortalPlatforms.HoloLens)
                {
                    // Check to see if HTTPS is required to communicate with this device.
                    connectionPhaseDescription = "Checking secure connection requirements";
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.DeterminingConnectionRequirements,
                        connectionPhaseDescription);
                    requiresHttps = await this.GetIsHttpsRequiredAsync().ConfigureAwait(false);
                }

                // Connect the device to the specified network.
                if (!string.IsNullOrWhiteSpace(ssid))
                {
                    connectionPhaseDescription = string.Format("Connecting to {0} network", ssid);
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.ConnectingToTargetNetwork,
                        connectionPhaseDescription);
                    WifiInterfaces wifiInterfaces = await this.GetWifiInterfacesAsync().ConfigureAwait(false);

                    // TODO - consider what to do if there is more than one wifi interface on a device
                    await this.ConnectToWifiNetworkAsync(wifiInterfaces.Interfaces[0].Guid, ssid, ssidKey).ConfigureAwait(false);
                }

                // Get the device's IP configuration and update the connection as appropriate.
                if (updateConnection)
                {
                    connectionPhaseDescription = "Updating device connection";
                    this.SendConnectionStatus(
                        DeviceConnectionStatus.Connecting,
                        DeviceConnectionPhase.UpdatingDeviceAddress,
                        connectionPhaseDescription);

                    bool preservePort = true;

                    // HoloLens and Mobile are the only devices that support USB.
                    // They require the port to be changed when the connection is updated
                    // to WiFi.
                    if ((this.Platform == DevicePortalPlatforms.HoloLens) ||
                        (this.Platform == DevicePortalPlatforms.Mobile))
                    {
                        preservePort = false;
                    }

                    this.deviceConnection.UpdateConnection(
                        await this.GetIpConfigAsync().ConfigureAwait(false),
                        requiresHttps,
                        preservePort);
                }

                this.SendConnectionStatus(
                    DeviceConnectionStatus.Connected,
                    DeviceConnectionPhase.Idle,
                    "Device connection established");
            }
            catch (Exception e)
            {
                DevicePortalException dpe = e as DevicePortalException;

                if (dpe != null)
                {
                    this.ConnectionHttpStatusCode    = dpe.StatusCode;
                    this.ConnectionFailedDescription = dpe.Message;
                }
                else
                {
                    this.ConnectionHttpStatusCode = HttpStatusCode.Conflict;

                    // Get to the innermost exception for our return message.
                    Exception innermostException = e;
                    while (innermostException.InnerException != null)
                    {
                        innermostException = innermostException.InnerException;
                        await Task.Yield();
                    }

                    this.ConnectionFailedDescription = innermostException.Message;
                }

                this.SendConnectionStatus(
                    DeviceConnectionStatus.Failed,
                    DeviceConnectionPhase.Idle,
                    string.Format("Device connection failed: {0}, {1}", connectionPhaseDescription, this.ConnectionFailedDescription));
            }
        }