private async Task writeResponseAsync(string request, IOutputStream os, StreamSocketInformation socketInfo) { try { request = request.TrimEnd('\0'); //remove possible null from POST request string[] requestParts = request.Split('/'); // Request for the root page, so redirect to home page if (request.Equals("/")) { await redirectToPage(NavConstants.HOME_PAGE, os); } // Request for the home page else if (request.Contains(NavConstants.HOME_PAGE)) { // Generate the default config page string html = await GeneratePageHtml(NavConstants.HOME_PAGE); string onState = (this.playbackManager.PlaybackState == PlaybackState.Playing) ? "On" : "Off"; html = html.Replace("#onState#", onState); html = html.Replace("#radioVolume#", (this.playbackManager.Volume * 100).ToString()); html = html.Replace("#currentTrack#", this.playlistManager.CurrentTrack.Name); await WebHelper.WriteToStream(html, os); } // Request for the settings page else if (request.Contains(NavConstants.SETTINGS_PAGE)) { if (!string.IsNullOrEmpty(request)) { string settingParam = ""; IDictionary<string, string> parameters = WebHelper.ParseGetParametersFromUrl(new Uri(string.Format("http://0.0.0.0/{0}", request))); bool waitForPlaying = (this.playbackManager.PlaybackState == PlaybackState.Playing); bool waitForTrackChange = false; string trackName = this.playlistManager.CurrentTrack.Name; settingParam = "onStateVal"; if (parameters.ContainsKey(settingParam) && !string.IsNullOrWhiteSpace(parameters[settingParam])) { switch (parameters[settingParam]) { case "On": if (!waitForPlaying) this.playbackManager.Play(new Uri(this.playlistManager.CurrentTrack.Address)); waitForPlaying = true; break; case "Off": this.playbackManager.Pause(); waitForPlaying = false; break; } } settingParam = "volumeSlide"; if (parameters.ContainsKey(settingParam) && !string.IsNullOrWhiteSpace(parameters[settingParam])) { double newVolume = this.playbackManager.Volume; if (double.TryParse(parameters[settingParam], out newVolume)) { newVolume = Math.Round(newVolume / 100, 2); if (newVolume >= 0 && newVolume <= 1 && newVolume != this.playbackManager.Volume) { this.playbackManager.Volume = newVolume; } } } settingParam = "trackAction"; if (parameters.ContainsKey(settingParam) && !string.IsNullOrWhiteSpace(parameters[settingParam])) { waitForTrackChange = true; switch (parameters[settingParam]) { case "prev": this.playbackManager.Pause(); this.playlistManager.PreviousTrack(); break; case "next": this.playbackManager.Pause(); this.playlistManager.NextTrack(); break; case "track": if (parameters.ContainsKey("trackName") && !string.IsNullOrWhiteSpace(parameters["trackName"])) { if (trackName != parameters["trackName"]) { this.playbackManager.Pause(); this.playlistManager.PlayTrack(parameters["trackName"]); } else waitForTrackChange = false; } break; } if (waitForTrackChange) { waitForPlaying = true; } } DateTime timeOut = DateTime.Now.AddSeconds(30); Debug.WriteLine("Waiting on State: playback={0}; trackname={1}", (waitForPlaying)?"Playing":"NotPlaying", trackName); while (DateTime.Now.CompareTo(timeOut) < 0 && ( (this.playbackManager.PlaybackState == PlaybackState.Playing) != waitForPlaying || (this.playlistManager.CurrentTrack.Name != trackName) != waitForTrackChange )); if (DateTime.Now.CompareTo(timeOut) >= 0) { Debug.WriteLine("track did not start playing in time limit"); } } //handle UI interaction await redirectToPage(NavConstants.HOME_PAGE, os); } else if (request.Contains(NavConstants.ADDSTATION_PAGE)) { string html = await GeneratePageHtml(NavConstants.ADDSTATION_PAGE); string trackName = ""; string trackUrl = ""; if (!string.IsNullOrEmpty(request)) { string settingParam = "trackName"; IDictionary<string, string> parameters = WebHelper.ParseGetParametersFromUrl(new Uri(string.Format("http://0.0.0.0/{0}", request))); if (parameters.ContainsKey(settingParam) && !string.IsNullOrWhiteSpace(parameters[settingParam])) { Track trackToUpdate = playlistManager.CurrentPlaylist.Tracks.First(t => t.Name == parameters[settingParam]); if (null != trackToUpdate) { trackName = trackToUpdate.Name; trackUrl = trackToUpdate.Address; } } } html = html.Replace("var stationName = '';", string.Format("var stationName = '{0}';", trackName)); html = html.Replace("var stationUrl = '';", string.Format("var stationUrl = '{0}';", trackUrl)); await WebHelper.WriteToStream(html, os); } else if (request.Contains(NavConstants.ADDSTATIONSET_PAGE)) { if (!string.IsNullOrEmpty(request)) { Track origTrack = null; Track newTrack = null; string trackAction = ""; IDictionary<string, string> parameters = WebHelper.ParseGetParametersFromUrl(new Uri(string.Format("http://0.0.0.0/{0}", request))); if (parameters.ContainsKey("name") && !string.IsNullOrWhiteSpace(parameters["name"])) { if (parameters.ContainsKey("url") && !string.IsNullOrWhiteSpace(parameters["url"])) { newTrack = new Track() { Name = parameters["name"], Address = parameters["url"] }; } } if (parameters.ContainsKey("nameOrig") && !string.IsNullOrWhiteSpace(parameters["nameOrig"])) { origTrack = this.playlistManager.CurrentPlaylist.Tracks.First(t => t.Name == parameters["nameOrig"]); } if (parameters.ContainsKey("trackAction") && !string.IsNullOrWhiteSpace(parameters["trackAction"])) { trackAction = parameters["trackAction"]; } if (null != newTrack) { switch (trackAction) { case "Update": if (null != origTrack) { this.playlistManager.CurrentPlaylist.Tracks[this.playlistManager.CurrentPlaylist.Tracks.IndexOf(origTrack)] = newTrack; } else { this.playlistManager.CurrentPlaylist.Tracks.Add(newTrack); } break; case "Remove": if (null != origTrack) this.playlistManager.CurrentPlaylist.Tracks.Remove(origTrack); break; case "": case "Add": this.playlistManager.CurrentPlaylist.Tracks.Add(newTrack); break; } } } await redirectToPage(NavConstants.HOME_PAGE, os); } // Request for a file that is in the Assets\Web folder (e.g. logo, css file) else { using (Stream resp = os.AsStreamForWrite()) { bool exists = true; try { var folder = Windows.ApplicationModel.Package.Current.InstalledLocation; // Map the requested path to Assets\Web folder string filePath = NavConstants.ASSETSWEB + request.Replace('/', '\\'); // Open the file and write it to the stream using (Stream fs = await folder.OpenStreamForReadAsync(filePath)) { string contentType = ""; if (request.Contains("css")) { contentType = "Content-Type: text/css\r\n"; } if (request.Contains("htm")) { contentType = "Content-Type: text/html\r\n"; } string header = String.Format("HTTP/1.1 200 OK\r\n" + "Content-Length: {0}\r\n{1}" + "Connection: close\r\n\r\n", fs.Length, contentType); byte[] headerArray = Encoding.UTF8.GetBytes(header); await resp.WriteAsync(headerArray, 0, headerArray.Length); await fs.CopyToAsync(resp); } } catch (FileNotFoundException ex) { exists = false; // Log telemetry event about this exception var events = new Dictionary<string, string> { { "WebServer", ex.Message } }; TelemetryManager.WriteTelemetryEvent("FailedToOpenStream", events); } // Send 404 not found if can't find file if (!exists) { byte[] headerArray = Encoding.UTF8.GetBytes( "HTTP/1.1 404 Not Found\r\n" + "Content-Length:0\r\n" + "Connection: close\r\n\r\n"); await resp.WriteAsync(headerArray, 0, headerArray.Length); } await resp.FlushAsync(); } } } catch (Exception ex) { Debug.WriteLine("Exception in writeResponseAsync(): " + ex.Message); Debug.WriteLine(ex.StackTrace); // Log telemetry event about this exception var events = new Dictionary<string, string> { { "WebServer", ex.Message } }; TelemetryManager.WriteTelemetryEvent("FailedToWriteResponse", events); try { // Try to send an error page back if there was a problem servicing the request string html = helper.GenerateErrorPage("There's been an error: " + ex.Message + "<br><br>" + ex.StackTrace); await WebHelper.WriteToStream(html, os); } catch (Exception e) { TelemetryManager.WriteTelemetryException(e); } } }
private async Task writeResponseAsync(string request, IOutputStream os, StreamSocketInformation socketInfo) { try { string[] requestParts = request.Split('/'); // Request for the root page, so redirect to home page if (request.Equals("/")) { await redirectToPage(NavConstants.HOME_PAGE, os); } // Request for the home page else if(request.Contains(NavConstants.HOME_PAGE)) { // Generate the default config page string html = await helper.GenerateStatusPage(); await WebHelper.WriteToStream(html, os); } // Request for the settings page else if (request.Contains(NavConstants.SETTINGS_PAGE)) { // Process the GET parameters if (request.Contains("?")) { // Format the URI with the get parameters Uri uri = new Uri("http://1.2.3.4:8000" + request); // Take the parameters from the URL and put it into Settings helper.ParseUriIntoSettings(uri); await AppSettings.SaveAsync(App.Controller.XmlSettings, "Settings.xml"); // This is an event that lets us know what the controller is done restarting after the settings are applied AutoResetEvent ase = new AutoResetEvent(false); // Dispose and Initialize need to be called on UI thread because of DispatcherTimers await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => { try { // Restart the controller to apply new settings App.Controller.Dispose(); await App.Controller.Initialize(); // Create the settings page and add a confirmation message that the settings were applied successfully string html = helper.GeneratePage("Security System Config", "Security System Config", helper.CreateHtmlFormFromSettings(), "<span style='color:Green'>Configuration saved!</span><br><br>"); await WebHelper.WriteToStream(html, os); } catch (Exception ex) { Debug.WriteLine("Error restarting controller: " + ex.Message); } // Signal that the restart is done ase.Set(); }); // Wait for controller restart to finish ase.WaitOne(); } else { // Generate the default config page string html = helper.GeneratePage("Security System Config", "Security System Config", helper.CreateHtmlFormFromSettings()); await WebHelper.WriteToStream(html, os); } } // Request for the OneDrive page else if (request.Contains(NavConstants.ONEDRIVE_PAGE)) { // Take in the parameters and try to login to OneDrive if (request.Contains("?")) { // I just put some arbitrary IP and port just so I have a correctly formatted URI, it's not important to have an actual IP + port Uri uri = new Uri("http://1.2.3.4:8000" + request); await helper.ParseOneDriveUri(uri); var oneDrive = App.Controller.Storage as OneDrive; if (oneDrive != null) { if (oneDrive.IsLoggedIn()) { // Save tokens to settings file if we successfully logged in await AppSettings.SaveAsync(App.Controller.XmlSettings, "Settings.xml"); } } } // Generate page and write to stream string html = helper.GenerateOneDrivePage(); await WebHelper.WriteToStream(html, os); } // Request for gallery page else if(request.Contains(NavConstants.GALLERY_PAGE)) { string html = ""; var storageType = App.Controller.Storage.GetType(); // If the storage type is OneDrive, generate page with link to OneDrive if (storageType == typeof(OneDrive)) { html = helper.GeneratePage("Gallery", "Gallery", "<b>" + storageType.Name + "</b> is set as your storage provider. " + "Please view your pictures on <a href='http://www.onedrive.com' target='_blank'>OneDrive</a>.<br><br>" + "To view your pictures here, please select <b>" + StorageProvider.Local + "</b> as your storage provider."); } // Otherwise show the gallery for the files on the device else { StorageFolder folder = KnownFolders.PicturesLibrary; int page = 1; int pageSize = 30; // Parse GET parameters if (request.Contains("?")) { Uri uri = new Uri("http://1.2.3.4:8000" + request); var parameters = helper.ParseGetParametersFromUrl(uri); try { // Find the folder that's specified in the parameters folder = await StorageFolder.GetFolderFromPathAsync(parameters["folder"]); if(parameters.ContainsKey("page")) { try { page = Convert.ToInt32(parameters["page"]); } catch (Exception) { } } if (parameters.ContainsKey("pageSize")) { try { pageSize = Convert.ToInt32(parameters["pageSize"]); } catch (Exception) { } } } catch (Exception ex) { Debug.WriteLine("Exception finding folder: " + ex.Message); folder = await folder.GetFolderAsync(AppSettings.FolderName); // Log telemetry event about this exception var events = new Dictionary<string, string> { { "WebServer", ex.Message } }; TelemetryHelper.TrackEvent("FailedToGetFolderFromPath", events); } } else { folder = await folder.GetFolderAsync(AppSettings.FolderName); } // Generate gallery page and write to stream string galleryHtml = await helper.GenerateGallery(folder, page, pageSize); html = helper.GeneratePage("Gallery", "Gallery", galleryHtml); } await WebHelper.WriteToStream(html, os); } // Request for API else if(request.Contains("api")) { try { if (requestParts.Length > 2) { switch (requestParts[2].ToLower()) { // An image from the gallery was requested case "gallery": var temp = request.Split(new string[] { "gallery/" }, StringSplitOptions.None); // HTML decode the file path string decodedPath = WebUtility.UrlDecode(temp[1]); // Retrieve the file StorageFile file = await StorageFile.GetFileFromPathAsync(decodedPath); // Write the file to the stream await WebHelper.WriteFileToStream(file, os); break; } } }catch(Exception ex) { Debug.WriteLine("Exception in web API: " + ex.Message); // Log telemetry event about this exception var events = new Dictionary<string, string> { { "WebServer", ex.Message } }; TelemetryHelper.TrackEvent("FailedToProcessApiRequest", events); } } // Request for a file that is in the Assets\Web folder (e.g. logo, css file) else { using (Stream resp = os.AsStreamForWrite()) { bool exists = true; try { var folder = Windows.ApplicationModel.Package.Current.InstalledLocation; // Map the requested path to Assets\Web folder string filePath = @"Assets\Web" + request.Replace('/', '\\'); // Open the file and write it to the stream using (Stream fs = await folder.OpenStreamForReadAsync(filePath)) { string header = String.Format("HTTP/1.1 200 OK\r\n" + "Content-Length: {0}\r\n{1}" + "Connection: close\r\n\r\n", fs.Length, ((request.Contains("css")) ? "Content-Type: text/css\r\n" : "")); byte[] headerArray = Encoding.UTF8.GetBytes(header); await resp.WriteAsync(headerArray, 0, headerArray.Length); await fs.CopyToAsync(resp); } } catch (FileNotFoundException ex) { exists = false; // Log telemetry event about this exception var events = new Dictionary<string, string> { { "WebServer", ex.Message } }; TelemetryHelper.TrackEvent("FailedToOpenStream", events); } // Send 404 not found if can't find file if (!exists) { byte[] headerArray = Encoding.UTF8.GetBytes( "HTTP/1.1 404 Not Found\r\n" + "Content-Length:0\r\n" + "Connection: close\r\n\r\n"); await resp.WriteAsync(headerArray, 0, headerArray.Length); } await resp.FlushAsync(); } } }catch(Exception ex) { Debug.WriteLine("Exception in writeResponseAsync(): " + ex.Message); Debug.WriteLine(ex.StackTrace); // Log telemetry event about this exception var events = new Dictionary<string, string> { { "WebServer", ex.Message } }; TelemetryHelper.TrackEvent("FailedToWriteResponse", events); try { // Try to send an error page back if there was a problem servicing the request string html = helper.GeneratePage("Error", "Error", "There's been an error: " + ex.Message + "<br><br>" + ex.StackTrace); await WebHelper.WriteToStream(html, os); } catch (Exception e) { TelemetryHelper.TrackException(e); } } }
/// <summary> /// Creates a new ClientConnectedEventArgs object /// </summary> /// <param name="clientInformation">Client socket information</param> /// <param name="clientId">Client's GUID</param> public ClientConnectedEventArgs(StreamSocketInformation clientInformation, string clientId) : base() { this.clientInformation = clientInformation; this.ClientId = clientId; }