HttpSessionController.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. using MediaBrowser.Common.Net;
  2. using MediaBrowser.Controller.Session;
  3. using MediaBrowser.Model.Entities;
  4. using MediaBrowser.Model.Serialization;
  5. using MediaBrowser.Model.Session;
  6. using MediaBrowser.Model.System;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Globalization;
  10. using System.Linq;
  11. using System.Net;
  12. using System.Threading;
  13. using System.Threading.Tasks;
  14. namespace MediaBrowser.Server.Implementations.Session
  15. {
  16. public class HttpSessionController : ISessionController, IDisposable
  17. {
  18. private readonly IHttpClient _httpClient;
  19. private readonly IJsonSerializer _json;
  20. private readonly ISessionManager _sessionManager;
  21. public SessionInfo Session { get; private set; }
  22. private readonly string _postUrl;
  23. private Timer _pingTimer;
  24. public HttpSessionController(IHttpClient httpClient,
  25. IJsonSerializer json,
  26. SessionInfo session,
  27. string postUrl, ISessionManager sessionManager)
  28. {
  29. _httpClient = httpClient;
  30. _json = json;
  31. Session = session;
  32. _postUrl = postUrl;
  33. _sessionManager = sessionManager;
  34. _pingTimer = new Timer(PingTimerCallback, null, Timeout.Infinite, Timeout.Infinite);
  35. ResetPingTimer();
  36. }
  37. public bool IsSessionActive
  38. {
  39. get
  40. {
  41. return (DateTime.UtcNow - Session.LastActivityDate).TotalMinutes <= 10;
  42. }
  43. }
  44. public bool SupportsMediaControl
  45. {
  46. get { return true; }
  47. }
  48. private async void PingTimerCallback(object state)
  49. {
  50. try
  51. {
  52. await SendMessage("Ping", CancellationToken.None).ConfigureAwait(false);
  53. }
  54. catch
  55. {
  56. ReportSessionEnded();
  57. }
  58. }
  59. private void ReportSessionEnded()
  60. {
  61. try
  62. {
  63. _sessionManager.ReportSessionEnded(Session.Id);
  64. }
  65. catch (Exception ex)
  66. {
  67. }
  68. }
  69. private void ResetPingTimer()
  70. {
  71. if (_pingTimer != null)
  72. {
  73. var period = TimeSpan.FromSeconds(60);
  74. _pingTimer.Change(period, period);
  75. }
  76. }
  77. private Task SendMessage(string name, CancellationToken cancellationToken)
  78. {
  79. return SendMessage(name, new Dictionary<string, string>(), cancellationToken);
  80. }
  81. private async Task SendMessage(string name,
  82. Dictionary<string, string> args,
  83. CancellationToken cancellationToken)
  84. {
  85. var url = _postUrl + "/" + name + ToQueryString(args);
  86. await _httpClient.Post(new HttpRequestOptions
  87. {
  88. Url = url,
  89. CancellationToken = cancellationToken
  90. }).ConfigureAwait(false);
  91. ResetPingTimer();
  92. }
  93. public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
  94. {
  95. return Task.FromResult(true);
  96. }
  97. public Task SendPlaybackStartNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
  98. {
  99. return Task.FromResult(true);
  100. }
  101. public Task SendPlaybackStoppedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
  102. {
  103. return Task.FromResult(true);
  104. }
  105. public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
  106. {
  107. var dict = new Dictionary<string, string>();
  108. dict["ItemIds"] = string.Join(",", command.ItemIds);
  109. if (command.StartPositionTicks.HasValue)
  110. {
  111. dict["StartPositionTicks"] = command.StartPositionTicks.Value.ToString(CultureInfo.InvariantCulture);
  112. }
  113. return SendMessage(command.PlayCommand.ToString(), dict, cancellationToken);
  114. }
  115. public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
  116. {
  117. var args = new Dictionary<string, string>();
  118. if (command.Command == PlaystateCommand.Seek)
  119. {
  120. if (!command.SeekPositionTicks.HasValue)
  121. {
  122. throw new ArgumentException("SeekPositionTicks cannot be null");
  123. }
  124. args["StartPositionTicks"] = command.SeekPositionTicks.Value.ToString(CultureInfo.InvariantCulture);
  125. }
  126. return SendMessage(command.Command.ToString(), cancellationToken);
  127. }
  128. public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
  129. {
  130. return Task.FromResult(true);
  131. }
  132. public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
  133. {
  134. return SendMessage("RestartRequired", cancellationToken);
  135. }
  136. public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken)
  137. {
  138. return Task.FromResult(true);
  139. }
  140. public Task SendServerShutdownNotification(CancellationToken cancellationToken)
  141. {
  142. return SendMessage("ServerShuttingDown", cancellationToken);
  143. }
  144. public Task SendServerRestartNotification(CancellationToken cancellationToken)
  145. {
  146. return SendMessage("ServerRestarting", cancellationToken);
  147. }
  148. public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
  149. {
  150. return SendMessage(command.Name, command.Arguments, cancellationToken);
  151. }
  152. private string ToQueryString(Dictionary<string, string> nvc)
  153. {
  154. var array = (from item in nvc
  155. select string.Format("{0}={1}", WebUtility.UrlEncode(item.Key), WebUtility.UrlEncode(item.Value)))
  156. .ToArray();
  157. var args = string.Join("&", array);
  158. if (string.IsNullOrEmpty(args))
  159. {
  160. return args;
  161. }
  162. return "?" + args;
  163. }
  164. public void Dispose()
  165. {
  166. DisposePingTimer();
  167. }
  168. private void DisposePingTimer()
  169. {
  170. if (_pingTimer != null)
  171. {
  172. _pingTimer.Dispose();
  173. _pingTimer = null;
  174. }
  175. }
  176. }
  177. }