diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index f7d1ecd4ae..fb2221c68e 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -99,7 +99,7 @@ namespace MediaBrowser.Controller.Session /// /// The session identifier. /// Task. - Task ReportSessionEnded(string sessionId); + void ReportSessionEnded(string sessionId); /// /// Gets the session info dto. diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index bcbd2a9c7c..35ebb4cf99 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -89,7 +89,7 @@ namespace MediaBrowser.Dlna.PlayTo try { // Session is inactive, mark it for Disposal and don't start the elapsed timer. - await _sessionManager.ReportSessionEnded(_session.Id).ConfigureAwait(false); + _sessionManager.ReportSessionEnded(_session.Id); } catch (Exception ex) { @@ -113,8 +113,8 @@ namespace MediaBrowser.Dlna.PlayTo string nt; if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty; - - if (string.Equals(e.Method, "NOTIFY", StringComparison.OrdinalIgnoreCase) && + + if (string.Equals(e.Method, "NOTIFY", StringComparison.OrdinalIgnoreCase) && string.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase) && usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1 && !_disposed) @@ -124,7 +124,7 @@ namespace MediaBrowser.Dlna.PlayTo { try { - await _sessionManager.ReportSessionEnded(_session.Id).ConfigureAwait(false); + _sessionManager.ReportSessionEnded(_session.Id); } catch { diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs index 110f66476d..e64121c455 100644 --- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs +++ b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs @@ -1,38 +1,44 @@ -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Net; -using MediaBrowser.Common.Net; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Net; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Session; using MediaBrowser.Model.System; using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Session { - public class HttpSessionController : ISessionController + public class HttpSessionController : ISessionController, IDisposable { private readonly IHttpClient _httpClient; private readonly IJsonSerializer _json; + private readonly ISessionManager _sessionManager; public SessionInfo Session { get; private set; } private readonly string _postUrl; + private Timer _pingTimer; + public HttpSessionController(IHttpClient httpClient, IJsonSerializer json, SessionInfo session, - string postUrl) + string postUrl, ISessionManager sessionManager) { _httpClient = httpClient; _json = json; Session = session; _postUrl = postUrl; + _sessionManager = sessionManager; + + _pingTimer = new Timer(PingTimerCallback, null, Timeout.Infinite, Timeout.Infinite); + + ResetPingTimer(); } public bool IsSessionActive @@ -48,17 +54,34 @@ namespace MediaBrowser.Server.Implementations.Session get { return true; } } - private Task SendMessage(object obj, CancellationToken cancellationToken) + private async void PingTimerCallback(object state) { - var json = _json.SerializeToString(obj); - - return _httpClient.Post(new HttpRequestOptions + try { - Url = _postUrl, - CancellationToken = cancellationToken, - RequestContent = json, - RequestContentType = "application/json" - }); + await SendMessage("Ping", CancellationToken.None).ConfigureAwait(false); + } + catch + { + ReportSessionEnded(); + } + } + + private void ReportSessionEnded() + { + try + { + _sessionManager.ReportSessionEnded(Session.Id); + } + catch (Exception ex) + { + } + } + + private void ResetPingTimer() + { + var period = TimeSpan.FromSeconds(60); + + _pingTimer.Change(period, period); } private Task SendMessage(string name, CancellationToken cancellationToken) @@ -66,15 +89,20 @@ namespace MediaBrowser.Server.Implementations.Session return SendMessage(name, new Dictionary(), cancellationToken); } - private Task SendMessage(string name, Dictionary args, CancellationToken cancellationToken) + private async Task SendMessage(string name, + Dictionary args, + CancellationToken cancellationToken) { var url = _postUrl + "/" + name + ToQueryString(args); - return _httpClient.Post(new HttpRequestOptions + await _httpClient.Post(new HttpRequestOptions { Url = url, CancellationToken = cancellationToken - }); + + }).ConfigureAwait(false); + + ResetPingTimer(); } public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken) @@ -160,5 +188,19 @@ namespace MediaBrowser.Server.Implementations.Session return "?" + args; } + + public void Dispose() + { + DisposePingTimer(); + } + + private void DisposePingTimer() + { + if (_pingTimer != null) + { + _pingTimer.Dispose(); + _pingTimer = null; + } + } } } diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index d78fae87b2..0ee9e6213b 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -248,7 +248,7 @@ namespace MediaBrowser.Server.Implementations.Session return session; } - public async Task ReportSessionEnded(string sessionId) + public async void ReportSessionEnded(string sessionId) { await _sessionLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); @@ -256,18 +256,16 @@ namespace MediaBrowser.Server.Implementations.Session { var session = GetSession(sessionId); - if (session == null) + if (session != null) { - throw new ArgumentException("Session not found"); - } + var key = GetSessionKey(session.Client, session.ApplicationVersion, session.DeviceId); - var key = GetSessionKey(session.Client, session.ApplicationVersion, session.DeviceId); + SessionInfo removed; - SessionInfo removed; - - if (_activeConnections.TryRemove(key, out removed)) - { - OnSessionEnded(removed); + if (_activeConnections.TryRemove(key, out removed)) + { + OnSessionEnded(removed); + } } } finally @@ -1155,7 +1153,7 @@ namespace MediaBrowser.Server.Implementations.Session if (controller == null) { - session.SessionController = new HttpSessionController(_httpClient, _jsonSerializer, session, postUrl); + session.SessionController = new HttpSessionController(_httpClient, _jsonSerializer, session, postUrl, this); } }