diff --git a/ServerLib/CServer.cs b/ServerLib/CServer.cs index b085e2c1..f9bf489d 100644 --- a/ServerLib/CServer.cs +++ b/ServerLib/CServer.cs @@ -59,6 +59,8 @@ namespace ServerLib public static GetAllSongsDelegate GetAllSongs { internal get; set; } public static GetCurrentSongIdDelegate GetCurrentSongId { internal get; set; } + + public static GetMp3PathDelegate GetMp3Path { internal get; set; } #endregion #region playlist diff --git a/ServerLib/CWebservice.cs b/ServerLib/CWebservice.cs index fc385e89..3a085350 100644 --- a/ServerLib/CWebservice.cs +++ b/ServerLib/CWebservice.cs @@ -37,7 +37,9 @@ namespace ServerLib { sessionKey = Guid.Parse(sessionHeader); } - catch (Exception) {} + catch (Exception) + { } + CSessionControl.ResetSessionTimeout(sessionKey); return sessionKey; } @@ -144,7 +146,7 @@ namespace ServerLib public SProfileData[] GetProfileList() { if (CServer.GetProfileList == null) - return new SProfileData[] {}; + return new SProfileData[] { }; return CServer.GetProfileList(); } #endregion @@ -172,6 +174,12 @@ namespace ServerLib return sessionId; } + public void Logout() + { + Guid sessionKey = _GetSession(); + CSessionControl.InvalidateSessions(sessionKey); + } + public Stream Index() { if (WebOperationContext.Current != null) @@ -289,6 +297,7 @@ namespace ServerLib public bool IsServerOnline() { + _GetSession(); return true; } #endregion @@ -308,6 +317,55 @@ namespace ServerLib { return CServer.GetAllSongs(); } + + public Stream GetMp3File(int songId) + { + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.UtcNow; + WebOperationContext.Current.OutgoingResponse.Headers.Add( + HttpResponseHeader.Expires, + DateTime.UtcNow.AddYears(1).ToString("r")); + } + + + String path = CServer.GetMp3Path(songId); + path = path.Replace("..", ""); + + + if (!File.Exists(path) + || !(path.EndsWith(".mp3", StringComparison.InvariantCulture) + || path.EndsWith(".ogg", StringComparison.InvariantCulture) + || path.EndsWith(".wav", StringComparison.InvariantCulture) + || path.EndsWith(".webm", StringComparison.InvariantCulture))) + { + if (WebOperationContext.Current != null) + WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.NotFound; + return null; + } + + if (WebOperationContext.Current != null) + { + if (path.EndsWith(".mp3", StringComparison.InvariantCulture)) + { + WebOperationContext.Current.OutgoingResponse.ContentType = "audio/mpeg"; + } + else if (path.EndsWith(".ogg", StringComparison.InvariantCulture)) + { + WebOperationContext.Current.OutgoingResponse.ContentType = "audio/ogg"; + } + else if (path.EndsWith(".wav", StringComparison.InvariantCulture)) + { + WebOperationContext.Current.OutgoingResponse.ContentType = "audio/wav"; + } + else if (path.EndsWith(".webm", StringComparison.InvariantCulture)) + { + WebOperationContext.Current.OutgoingResponse.ContentType = "audio/webm"; + } + } + + return File.OpenRead(path); + } #endregion #region playlist diff --git a/ServerLib/DataStructs.cs b/ServerLib/DataStructs.cs index 11942ac9..591b5f98 100644 --- a/ServerLib/DataStructs.cs +++ b/ServerLib/DataStructs.cs @@ -111,6 +111,8 @@ namespace ServerLib public delegate int GetCurrentSongIdDelegate(); + public delegate string GetMp3PathDelegate(int songId); + [DataContract] public struct SSongInfo { diff --git a/ServerLib/ICWebservice.cs b/ServerLib/ICWebservice.cs index 1324c2d9..27d68081 100644 --- a/ServerLib/ICWebservice.cs +++ b/ServerLib/ICWebservice.cs @@ -71,6 +71,11 @@ namespace ServerLib UriTemplate = "/login?username={username}&password={password}")] Guid Login(string username, string password); + [OperationContract, WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/logout")] + void Logout(); + [OperationContract, WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "")] @@ -127,6 +132,11 @@ namespace ServerLib ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getAllSongs")] SSongInfo[] GetAllSongs(); + + [OperationContract, WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/getMp3?songId={songId}")] + Stream GetMp3File(int songId); #endregion #region playlist diff --git a/ServerLib/Session.cs b/ServerLib/Session.cs index ad0f612f..416b34c9 100644 --- a/ServerLib/Session.cs +++ b/ServerLib/Session.cs @@ -38,12 +38,20 @@ namespace ServerLib { get { return _Roles; } } + + private DateTime _LastSeen; + public DateTime LastSeen + { + get { return _LastSeen; } + internal set { _LastSeen = value; } + } public CSession(Guid id, int profileId, EUserRoles roles) { _ID = id; _ProfileId = profileId; _Roles = roles; + _LastSeen = DateTime.Now; } } } \ No newline at end of file diff --git a/ServerLib/SessionControl.cs b/ServerLib/SessionControl.cs index 80bd2e66..0fc80117 100644 --- a/ServerLib/SessionControl.cs +++ b/ServerLib/SessionControl.cs @@ -18,12 +18,35 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Timers; namespace ServerLib { static class CSessionControl { - private static readonly Dictionary _ActiveSessions = new Dictionary(); + private static readonly Dictionary _ActiveSessions; + private const int _UserTimeoutCheckIntervall = 120000; + private const int _UserTimeout = 120000; + + static CSessionControl() + { + _ActiveSessions = new Dictionary(); + Timer timer = new Timer(_UserTimeoutCheckIntervall) {AutoReset = true, Enabled = true}; + timer.Elapsed += _CheckForUserTimeouts; + timer.Start(); + } + + private static void _CheckForUserTimeouts(object sender, ElapsedEventArgs e) + { + var sessionIdsToRemove = _ActiveSessions.Where(pair => (DateTime.Now-pair.Value.LastSeen).TotalMilliseconds > _UserTimeout) + .Select(pair => pair.Key) + .ToList(); + + foreach (var sessionToRemove in sessionIdsToRemove) + { + InvalidateSessions(sessionToRemove); + } + } public static Guid OpenSession(string userName, string password) { @@ -34,7 +57,7 @@ namespace ServerLib int id = _GetProfileIdFormUsername(userName); EUserRoles roles = _GetUserRoles(id); CSession session = new CSession(newId, id, roles); - InvalidateSessions(id); + //InvalidateSessions(id); _ActiveSessions.Add(newId, session); return newId; @@ -63,6 +86,14 @@ namespace ServerLib _ActiveSessions.Remove(s.Key); } + internal static void InvalidateSessions(Guid sessionId) + { + if (_ActiveSessions.ContainsKey(sessionId)) + { + _ActiveSessions.Remove(sessionId); + } + } + internal static bool RequestRight(Guid sessionId, EUserRights requestedRight) { return ((CUserRoleControl.GetUserRightsFromUserRole(_ActiveSessions[sessionId].Roles) @@ -75,5 +106,14 @@ namespace ServerLib return -1; return _ActiveSessions[sessionId].ProfileId; } + + internal static void ResetSessionTimeout(Guid sessionId) + { + CSession value; + if (_ActiveSessions.TryGetValue(sessionId, out value)) + { + value.LastSeen = DateTime.Now; + } + } } } \ No newline at end of file diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 878bbc37..252c0ef7 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -73,6 +73,7 @@ namespace Vocaluxe.Base.Server CServer.GetSong = _GetSong; CServer.GetAllSongs = _GetAllSongs; CServer.GetCurrentSongId = _GetCurrentSongId; + CServer.GetMp3Path = _GetMp3Path; CServer.ValidatePassword = _ValidatePassword; CServer.GetUserRole = _GetUserRole; CServer.SetUserRole = _SetUserRole; @@ -463,6 +464,11 @@ namespace Vocaluxe.Base.Server return (from s in songs select _GetSongInfo(s, false)).ToArray(); } + private static string _GetMp3Path(int songId) + { + CSong song = CSongs.GetSong(songId); + return song.GetMP3(); + } private static int _GetCurrentSongId() { diff --git a/Vocaluxe/Website/index.html b/Vocaluxe/Website/index.html index 3ef1620b..c6731d36 100644 --- a/Vocaluxe/Website/index.html +++ b/Vocaluxe/Website/index.html @@ -231,6 +231,7 @@