Browse Source

added periodic ping to http session controller

Luke Pulverenti 11 years ago
parent
commit
cb7fb3ae5c

+ 1 - 1
MediaBrowser.Controller/Session/ISessionManager.cs

@@ -99,7 +99,7 @@ namespace MediaBrowser.Controller.Session
         /// </summary>
         /// <param name="sessionId">The session identifier.</param>
         /// <returns>Task.</returns>
-        Task ReportSessionEnded(string sessionId);
+        void ReportSessionEnded(string sessionId);
 
         /// <summary>
         /// Gets the session info dto.

+ 4 - 4
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
                     {

+ 61 - 19
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);
+            try
+            {
+                await SendMessage("Ping", CancellationToken.None).ConfigureAwait(false);
+            }
+            catch
+            {
+                ReportSessionEnded();
+            }
+        }
 
-            return _httpClient.Post(new HttpRequestOptions
+        private void ReportSessionEnded()
+        {
+            try
+            {
+                _sessionManager.ReportSessionEnded(Session.Id);
+            }
+            catch (Exception ex)
             {
-                Url = _postUrl,
-                CancellationToken = cancellationToken,
-                RequestContent = json,
-                RequestContentType = "application/json"
-            });
+            }
+        }
+
+        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<string, string>(), cancellationToken);
         }
 
-        private Task SendMessage(string name, Dictionary<string, string> args, CancellationToken cancellationToken)
+        private async Task SendMessage(string name, 
+            Dictionary<string, string> 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;
+            }
+        }
     }
 }

+ 9 - 11
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);
                 }
             }