private void DispatchRequest(HttpListenerRequest request, HttpListenerResponse response, bool isCompressed) { DACPResponse dacpResponse = null; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // based on the URL, figure out what the client wanted and return it string url = request.RawUrl.ToLower(); try { // first handle either login or security check if (url.StartsWith("/login")) { dacpResponse = Login(request); ReleaseAllLatches(); } else if (url.StartsWith("/server-info")) { ReleaseAllLatches(); dacpResponse = new ServerInfoResponse(request); } else if (url.Equals("/ctrl-int")) { ReleaseAllLatches(); dacpResponse = new CtrlIntResponse(request); } else if (url.StartsWith("/databases?session-id=")) { dacpResponse = GetDatabaseInfo(request); } else if (url.StartsWith("/update")) { stopWatch = null; dacpResponse = GetUpdate(request); } else if (url.StartsWith("/logout")) { dacpResponse = new LogoutResponse(request); Logout(request); } else if (url.StartsWith("/fp-setup")) { dacpResponse = new FairPlayResponse(request); } else if (url.StartsWith("/refreshcache")) { RefreshCache(); } else if (url.StartsWith("/databases/")) { if (url.Contains("daap.baseplaylist")) { dacpResponse = GetPlaylists(request); } else if (url.Contains("artwork")) { dacpResponse = GetArtworkResponse(request); } else if (url.Contains("browse/artists")) { dacpResponse = GetArtists(request); } else if (url.Contains("browse/genres")) { dacpResponse = GetGenres(request); } else if (url.Contains("browse/composers")) { dacpResponse = GetComposers(request); } else if (url.Contains("groups?") && url.Contains("type=music&group-type=albums")) { dacpResponse = GetAlbums(request); } else if (url.Contains("groups?") && url.Contains("type=music&group-type=artists")) { dacpResponse = GetArtists(request); } else if (url.Contains("items?") && url.Contains("query=")) { dacpResponse = GetTracks(request); } else if (url.Contains("containers")) { if (url.Contains("action=add")) { dacpResponse = PlaylistAddTrack(request); } else if (url.Contains("action=remove")) { dacpResponse = PlaylistRemoveTrack(request); } else if (url.Contains("action=move")) { dacpResponse = PlaylistMoveTrack(request); } else if (url.Contains("action=rename")) { dacpResponse = PlaylistRename(request); SessionBoundResponse.IncrementDatabaseRevision(); } else if (url.Contains("action=refresh")) { dacpResponse = PlaylistRefresh(request); SessionBoundResponse.IncrementDatabaseRevision(); } else { dacpResponse = GetPlaylistTracks(request); } } else if (url.Contains("edit?action=add")) { dacpResponse = PlaylistAdd(request); SessionBoundResponse.IncrementDatabaseRevision(); } else if (url.Contains("edit?action=remove")) { dacpResponse = PlaylistRemove(request); SessionBoundResponse.IncrementDatabaseRevision(); } } else if (url.StartsWith("/ctrl-int/")) { if (url.Contains("playstatusupdate")) { stopWatch = null; dacpResponse = GetCurrentPlayerStatus(request); } else if (url.Contains(ArtworkResponse.PROPERTY_NOW_PLAYING)) { dacpResponse = GetArtworkResponse(request); } else if (url.Contains("cue?command=clear")) { if (PairingDatabase.RespectClearCueCommand) { ClearQueue = true; ControlClearQueue(request); } else { ClearQueue = false; Console.WriteLine("Clearing Playlist Cue disabled by RespectClearCueCommand in XML properties!"); } } else if (url.Contains("cue?command=play")) { // check for the clear flag if (PairingDatabase.RespectClearCueCommand) { if (url.Contains("clear-first")) { ClearQueue = true; } } QueueTracks(request, ClearQueue, true); } else if (url.Contains("cue?command=add")) { QueueTracks(request, false, false); } else if (url.Contains("playspec?")) { SetPlaylist(request); } else if (url.Contains("getproperty")) { dacpResponse = GetProperty(request); } else if (url.Contains("setproperty")) { dacpResponse = SetProperty(request); } else if (url.Contains("playpause")) { ControlPlayPause(request); } else if (url.Contains("pause")) { ControlPause(request); } else if (url.Contains("stop")) { ControlStop(request); } else if (url.Contains("nextitem")) { ControlNextItem(request); } else if (url.Contains("previtem")) { ControlPreviousItem(request); } else if (url.Contains("beginff")) { ControlFastForward(request); } else if (url.Contains("beginrew")) { ControlRewind(request); } else if (url.Contains("playresume")) { ControlPlayResume(request); } else if (url.Contains("items")) { dacpResponse = GetNowPlaying(request); } else if (url.Contains("getspeakers")) { dacpResponse = GetSpeakers(request); } else if (url.Contains("setspeakers")) { SetSpeakers(request); } else if (url.Contains("set-genius-seed")) { ControlGeniusSeed(request); } else { Console.WriteLine("Unknown URL type: {0}", request.RawUrl); } } else { Console.WriteLine("Unknown URL type: {0}", request.RawUrl); } // return a NO Content found if either null or is marker interface if ((dacpResponse == null) || (dacpResponse is INoContentResponse)) { response.StatusCode = DACPResponse.MSTT_NO_CONTENT; return; } // return a 500 Internal Server Error if (dacpResponse is IErrorResponse) { Console.WriteLine("500 Internal Server Error Response"); response.StatusCode = DACPResponse.MSTT_ERROR; return; } // now output the DACPResponse as a binary byte message byte[] responseBytes = dacpResponse.GetBytes(); if (isCompressed) { response.AppendHeader("Content-Encoding", "gzip"); using (MemoryStream memoryStream = new MemoryStream(8092)) { // Decide regular stream or gzip stream based on whether the response can be compressed or not using (Stream writer = new GZipStream(memoryStream, CompressionMode.Compress)) { writer.Write(responseBytes, 0, responseBytes.Length); } responseBytes = memoryStream.ToArray(); } } else { response.AppendHeader("Content-Encoding", "utf-8"); response.ContentEncoding = Encoding.Unicode; } response.StatusCode = (int)HttpStatusCode.OK; response.OutputStream.Write(responseBytes, 0, responseBytes.Length); } catch (Exception ex) { Console.WriteLine(this.GetApplicationName() + " Error: " + ex.Message, ex); response.StatusCode = (int)HttpStatusCode.ServiceUnavailable; } finally { if (stopWatch != null) { // Get the elapsed time as a TimeSpan value. TimeSpan ts = stopWatch.Elapsed; if (ts.TotalMilliseconds > 2500) { Console.WriteLine("DACP Response Time Exceeded Threshold: {0,21} '{1}'", ts.TotalMilliseconds, url); } else { Console.WriteLine("DACP Response Time: {0,21}", ts.TotalMilliseconds); } } } }