diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations')
4 files changed, 440 insertions, 296 deletions
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 99485f726..dc863ca4d 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -7,7 +7,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Connectivity; using MediaBrowser.Model.Logging; using System; using System.Collections.Concurrent; @@ -17,6 +16,7 @@ using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Session; namespace MediaBrowser.Server.Implementations.Library { @@ -28,8 +28,8 @@ namespace MediaBrowser.Server.Implementations.Library /// <summary> /// The _active connections /// </summary> - private readonly ConcurrentDictionary<string, ClientConnectionInfo> _activeConnections = - new ConcurrentDictionary<string, ClientConnectionInfo>(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections = + new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase); /// <summary> /// The _users @@ -70,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.Library /// Gets all connections. /// </summary> /// <value>All connections.</value> - public IEnumerable<ClientConnectionInfo> AllConnections + public IEnumerable<SessionInfo> AllConnections { get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate); } } @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Library /// Gets the active connections. /// </summary> /// <value>The active connections.</value> - public IEnumerable<ClientConnectionInfo> RecentConnections + public IEnumerable<SessionInfo> RecentConnections { get { return AllConnections.Where(c => (DateTime.UtcNow - c.LastActivityDate).TotalMinutes <= 5); } } @@ -89,8 +89,6 @@ namespace MediaBrowser.Server.Implementations.Library /// </summary> private readonly ILogger _logger; - private readonly IUserDataRepository _userDataRepository; - /// <summary> /// Gets or sets the configuration manager. /// </summary> @@ -109,11 +107,10 @@ namespace MediaBrowser.Server.Implementations.Library /// <param name="logger">The logger.</param> /// <param name="configurationManager">The configuration manager.</param> /// <param name="userDataRepository">The user data repository.</param> - public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserDataRepository userDataRepository) + public UserManager(ILogger logger, IServerConfigurationManager configurationManager) { _logger = logger; ConfigurationManager = configurationManager; - _userDataRepository = userDataRepository; } #region Events @@ -223,116 +220,6 @@ namespace MediaBrowser.Server.Implementations.Library } /// <summary> - /// Logs the user activity. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - public Task LogUserActivity(User user, string clientType, string deviceId, string deviceName) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - var activityDate = DateTime.UtcNow; - - var lastActivityDate = user.LastActivityDate; - - user.LastActivityDate = activityDate; - - LogConnection(user.Id, clientType, deviceId, deviceName, activityDate); - - // Don't log in the db anymore frequently than 10 seconds - if (lastActivityDate.HasValue && (activityDate - lastActivityDate.Value).TotalSeconds < 10) - { - return Task.FromResult(true); - } - - // Save this directly. No need to fire off all the events for this. - return UserRepository.SaveUser(user, CancellationToken.None); - } - - /// <summary> - /// Updates the now playing item id. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <param name="item">The item.</param> - /// <param name="currentPositionTicks">The current position ticks.</param> - private void UpdateNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item, long? currentPositionTicks = null) - { - var conn = GetConnection(user.Id, clientType, deviceId, deviceName); - - conn.NowPlayingPositionTicks = currentPositionTicks; - conn.NowPlayingItem = DtoBuilder.GetBaseItemInfo(item); - conn.LastActivityDate = DateTime.UtcNow; - } - - /// <summary> - /// Removes the now playing item id. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <param name="item">The item.</param> - private void RemoveNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item) - { - var conn = GetConnection(user.Id, clientType, deviceId, deviceName); - - if (conn.NowPlayingItem != null && conn.NowPlayingItem.Id.Equals(item.Id.ToString())) - { - conn.NowPlayingItem = null; - conn.NowPlayingPositionTicks = null; - } - } - - /// <summary> - /// Logs the connection. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <param name="lastActivityDate">The last activity date.</param> - private void LogConnection(Guid userId, string clientType, string deviceId, string deviceName, DateTime lastActivityDate) - { - GetConnection(userId, clientType, deviceId, deviceName).LastActivityDate = lastActivityDate; - } - - /// <summary> - /// Gets the connection. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <returns>ClientConnectionInfo.</returns> - private ClientConnectionInfo GetConnection(Guid userId, string clientType, string deviceId, string deviceName) - { - var key = clientType + deviceId; - - var connection = _activeConnections.GetOrAdd(key, keyName => new ClientConnectionInfo - { - UserId = userId.ToString(), - Client = clientType, - DeviceName = deviceName, - DeviceId = deviceId - }); - - connection.DeviceName = deviceName; - connection.UserId = userId.ToString(); - - return connection; - } - - /// <summary> /// Loads the users from the repository /// </summary> /// <returns>IEnumerable{User}.</returns> @@ -560,182 +447,5 @@ namespace MediaBrowser.Server.Implementations.Library DateModified = DateTime.UtcNow }; } - - /// <summary> - /// Used to report that playback has started for an item - /// </summary> - /// <param name="user">The user.</param> - /// <param name="item">The item.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <exception cref="System.ArgumentNullException"></exception> - public void OnPlaybackStart(User user, BaseItem item, string clientType, string deviceId, string deviceName) - { - if (user == null) - { - throw new ArgumentNullException(); - } - if (item == null) - { - throw new ArgumentNullException(); - } - - UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item); - - // Nothing to save here - // Fire events to inform plugins - EventHelper.QueueEventIfNotNull(PlaybackStart, this, new PlaybackProgressEventArgs - { - Item = item, - User = user - }, _logger); - } - - /// <summary> - /// Used to report playback progress for an item - /// </summary> - /// <param name="user">The user.</param> - /// <param name="item">The item.</param> - /// <param name="positionTicks">The position ticks.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public async Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName) - { - if (user == null) - { - throw new ArgumentNullException(); - } - if (item == null) - { - throw new ArgumentNullException(); - } - - UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, positionTicks); - - var key = item.GetUserDataKey(); - - if (positionTicks.HasValue) - { - var data = await _userDataRepository.GetUserData(user.Id, key).ConfigureAwait(false); - - UpdatePlayState(item, data, positionTicks.Value, false); - await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false); - } - - EventHelper.QueueEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs - { - Item = item, - User = user, - PlaybackPositionTicks = positionTicks - }, _logger); - } - - /// <summary> - /// Used to report that playback has ended for an item - /// </summary> - /// <param name="user">The user.</param> - /// <param name="item">The item.</param> - /// <param name="positionTicks">The position ticks.</param> - /// <param name="clientType">Type of the client.</param> - /// <param name="deviceId">The device id.</param> - /// <param name="deviceName">Name of the device.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public async Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName) - { - if (user == null) - { - throw new ArgumentNullException(); - } - if (item == null) - { - throw new ArgumentNullException(); - } - - RemoveNowPlayingItemId(user, clientType, deviceId, deviceName, item); - - var key = item.GetUserDataKey(); - - var data = await _userDataRepository.GetUserData(user.Id, key).ConfigureAwait(false); - - if (positionTicks.HasValue) - { - UpdatePlayState(item, data, positionTicks.Value, true); - } - else - { - // If the client isn't able to report this, then we'll just have to make an assumption - data.PlayCount++; - data.Played = true; - } - - await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false); - - EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackProgressEventArgs - { - Item = item, - User = user, - PlaybackPositionTicks = positionTicks - }, _logger); - } - - /// <summary> - /// Updates playstate position for an item but does not save - /// </summary> - /// <param name="item">The item</param> - /// <param name="data">User data for the item</param> - /// <param name="positionTicks">The current playback position</param> - /// <param name="incrementPlayCount">Whether or not to increment playcount</param> - private void UpdatePlayState(BaseItem item, UserItemData data, long positionTicks, bool incrementPlayCount) - { - // If a position has been reported, and if we know the duration - if (positionTicks > 0 && item.RunTimeTicks.HasValue && item.RunTimeTicks > 0) - { - var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100; - - // Don't track in very beginning - if (pctIn < ConfigurationManager.Configuration.MinResumePct) - { - positionTicks = 0; - incrementPlayCount = false; - } - - // If we're at the end, assume completed - else if (pctIn > ConfigurationManager.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value) - { - positionTicks = 0; - data.Played = true; - } - - else - { - // Enforce MinResumeDuration - var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds; - - if (durationSeconds < ConfigurationManager.Configuration.MinResumeDurationSeconds) - { - positionTicks = 0; - data.Played = true; - } - } - } - - if (item is Audio) - { - data.PlaybackPositionTicks = 0; - } - - data.PlaybackPositionTicks = positionTicks; - - if (incrementPlayCount) - { - data.PlayCount++; - data.LastPlayedDate = DateTime.UtcNow; - } - } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index f9e7f0385..45515b81f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -156,6 +156,10 @@ <Compile Include="ServerApplicationPaths.cs" /> <Compile Include="ServerManager\ServerManager.cs" /> <Compile Include="ServerManager\WebSocketConnection.cs" /> + <Compile Include="Session\SessionManager.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Session\SessionWebSocketListener.cs" /> <Compile Include="Sorting\AlbumArtistComparer.cs" /> <Compile Include="Sorting\AlbumComparer.cs" /> <Compile Include="Sorting\ArtistComparer.cs" /> diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs new file mode 100644 index 000000000..051c8fb68 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -0,0 +1,372 @@ +using MediaBrowser.Common.Events; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Session; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Session +{ + public class SessionManager : ISessionManager + { + private readonly IUserDataRepository _userDataRepository; + + private readonly IUserRepository _userRepository; + + /// <summary> + /// The _logger + /// </summary> + private readonly ILogger _logger; + + /// <summary> + /// Gets or sets the configuration manager. + /// </summary> + /// <value>The configuration manager.</value> + private readonly IServerConfigurationManager _configurationManager; + + /// <summary> + /// The _active connections + /// </summary> + private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections = + new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase); + + private readonly ConcurrentDictionary<Guid, IWebSocketConnection> _websocketConnections = + new ConcurrentDictionary<Guid, IWebSocketConnection>(); + + /// <summary> + /// Occurs when [playback start]. + /// </summary> + public event EventHandler<PlaybackProgressEventArgs> PlaybackStart; + /// <summary> + /// Occurs when [playback progress]. + /// </summary> + public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress; + /// <summary> + /// Occurs when [playback stopped]. + /// </summary> + public event EventHandler<PlaybackProgressEventArgs> PlaybackStopped; + + public SessionManager(IUserDataRepository userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository) + { + _userDataRepository = userDataRepository; + _configurationManager = configurationManager; + _logger = logger; + _userRepository = userRepository; + } + + /// <summary> + /// Gets all connections. + /// </summary> + /// <value>All connections.</value> + public IEnumerable<SessionInfo> AllConnections + { + get { return _activeConnections.Values.OrderByDescending(c => c.LastActivityDate); } + } + + /// <summary> + /// Gets the active connections. + /// </summary> + /// <value>The active connections.</value> + public IEnumerable<SessionInfo> RecentConnections + { + get { return AllConnections.Where(c => (DateTime.UtcNow - c.LastActivityDate).TotalMinutes <= 5); } + } + + private readonly Task _trueTaskResult = Task.FromResult(true); + + /// <summary> + /// Logs the user activity. + /// </summary> + /// <param name="clientType">Type of the client.</param> + /// <param name="deviceId">The device id.</param> + /// <param name="deviceName">Name of the device.</param> + /// <param name="user">The user.</param> + /// <returns>Task.</returns> + /// <exception cref="System.ArgumentNullException">user</exception> + public Task LogConnectionActivity(string clientType, string deviceId, string deviceName, User user) + { + var activityDate = DateTime.UtcNow; + + GetConnection(clientType, deviceId, deviceName, user).LastActivityDate = activityDate; + + if (user == null) + { + return _trueTaskResult; + } + + var lastActivityDate = user.LastActivityDate; + + user.LastActivityDate = activityDate; + + // Don't log in the db anymore frequently than 10 seconds + if (lastActivityDate.HasValue && (activityDate - lastActivityDate.Value).TotalSeconds < 10) + { + return _trueTaskResult; + } + + // Save this directly. No need to fire off all the events for this. + return _userRepository.SaveUser(user, CancellationToken.None); + } + + /// <summary> + /// Updates the now playing item id. + /// </summary> + /// <param name="user">The user.</param> + /// <param name="clientType">Type of the client.</param> + /// <param name="deviceId">The device id.</param> + /// <param name="deviceName">Name of the device.</param> + /// <param name="item">The item.</param> + /// <param name="currentPositionTicks">The current position ticks.</param> + private void UpdateNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item, long? currentPositionTicks = null) + { + var conn = GetConnection(clientType, deviceId, deviceName, user); + + conn.NowPlayingPositionTicks = currentPositionTicks; + conn.NowPlayingItem = DtoBuilder.GetBaseItemInfo(item); + conn.LastActivityDate = DateTime.UtcNow; + } + + /// <summary> + /// Removes the now playing item id. + /// </summary> + /// <param name="user">The user.</param> + /// <param name="clientType">Type of the client.</param> + /// <param name="deviceId">The device id.</param> + /// <param name="deviceName">Name of the device.</param> + /// <param name="item">The item.</param> + private void RemoveNowPlayingItemId(User user, string clientType, string deviceId, string deviceName, BaseItem item) + { + var conn = GetConnection(clientType, deviceId, deviceName, user); + + if (conn.NowPlayingItem != null && conn.NowPlayingItem.Id.Equals(item.Id.ToString())) + { + conn.NowPlayingItem = null; + conn.NowPlayingPositionTicks = null; + } + } + + /// <summary> + /// Gets the connection. + /// </summary> + /// <param name="clientType">Type of the client.</param> + /// <param name="deviceId">The device id.</param> + /// <param name="deviceName">Name of the device.</param> + /// <param name="user">The user.</param> + /// <returns>SessionInfo.</returns> + private SessionInfo GetConnection(string clientType, string deviceId, string deviceName, User user) + { + var key = clientType + deviceId; + + var connection = _activeConnections.GetOrAdd(key, keyName => new SessionInfo + { + Client = clientType, + DeviceId = deviceId, + Id = Guid.NewGuid() + }); + + connection.DeviceName = deviceName; + + connection.UserId = user == null ? null : user.Id.ToString(); + + return connection; + } + + /// <summary> + /// Used to report that playback has started for an item + /// </summary> + /// <param name="user">The user.</param> + /// <param name="item">The item.</param> + /// <param name="clientType">Type of the client.</param> + /// <param name="deviceId">The device id.</param> + /// <param name="deviceName">Name of the device.</param> + /// <exception cref="System.ArgumentNullException"></exception> + public void OnPlaybackStart(User user, BaseItem item, string clientType, string deviceId, string deviceName) + { + if (user == null) + { + throw new ArgumentNullException(); + } + if (item == null) + { + throw new ArgumentNullException(); + } + + UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item); + + // Nothing to save here + // Fire events to inform plugins + EventHelper.QueueEventIfNotNull(PlaybackStart, this, new PlaybackProgressEventArgs + { + Item = item, + User = user + }, _logger); + } + + /// <summary> + /// Used to report playback progress for an item + /// </summary> + /// <param name="user">The user.</param> + /// <param name="item">The item.</param> + /// <param name="positionTicks">The position ticks.</param> + /// <param name="clientType">Type of the client.</param> + /// <param name="deviceId">The device id.</param> + /// <param name="deviceName">Name of the device.</param> + /// <returns>Task.</returns> + /// <exception cref="System.ArgumentNullException"></exception> + public async Task OnPlaybackProgress(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName) + { + if (user == null) + { + throw new ArgumentNullException(); + } + if (item == null) + { + throw new ArgumentNullException(); + } + + UpdateNowPlayingItemId(user, clientType, deviceId, deviceName, item, positionTicks); + + var key = item.GetUserDataKey(); + + if (positionTicks.HasValue) + { + var data = await _userDataRepository.GetUserData(user.Id, key).ConfigureAwait(false); + + UpdatePlayState(item, data, positionTicks.Value, false); + await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false); + } + + EventHelper.QueueEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs + { + Item = item, + User = user, + PlaybackPositionTicks = positionTicks + }, _logger); + } + + /// <summary> + /// Used to report that playback has ended for an item + /// </summary> + /// <param name="user">The user.</param> + /// <param name="item">The item.</param> + /// <param name="positionTicks">The position ticks.</param> + /// <param name="clientType">Type of the client.</param> + /// <param name="deviceId">The device id.</param> + /// <param name="deviceName">Name of the device.</param> + /// <returns>Task.</returns> + /// <exception cref="System.ArgumentNullException"></exception> + public async Task OnPlaybackStopped(User user, BaseItem item, long? positionTicks, string clientType, string deviceId, string deviceName) + { + if (user == null) + { + throw new ArgumentNullException(); + } + if (item == null) + { + throw new ArgumentNullException(); + } + + RemoveNowPlayingItemId(user, clientType, deviceId, deviceName, item); + + var key = item.GetUserDataKey(); + + var data = await _userDataRepository.GetUserData(user.Id, key).ConfigureAwait(false); + + if (positionTicks.HasValue) + { + UpdatePlayState(item, data, positionTicks.Value, true); + } + else + { + // If the client isn't able to report this, then we'll just have to make an assumption + data.PlayCount++; + data.Played = true; + } + + await _userDataRepository.SaveUserData(user.Id, key, data, CancellationToken.None).ConfigureAwait(false); + + EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackProgressEventArgs + { + Item = item, + User = user, + PlaybackPositionTicks = positionTicks + }, _logger); + } + + /// <summary> + /// Updates playstate position for an item but does not save + /// </summary> + /// <param name="item">The item</param> + /// <param name="data">User data for the item</param> + /// <param name="positionTicks">The current playback position</param> + /// <param name="incrementPlayCount">Whether or not to increment playcount</param> + private void UpdatePlayState(BaseItem item, UserItemData data, long positionTicks, bool incrementPlayCount) + { + // If a position has been reported, and if we know the duration + if (positionTicks > 0 && item.RunTimeTicks.HasValue && item.RunTimeTicks > 0) + { + var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100; + + // Don't track in very beginning + if (pctIn < _configurationManager.Configuration.MinResumePct) + { + positionTicks = 0; + incrementPlayCount = false; + } + + // If we're at the end, assume completed + else if (pctIn > _configurationManager.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value) + { + positionTicks = 0; + data.Played = true; + } + + else + { + // Enforce MinResumeDuration + var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds; + + if (durationSeconds < _configurationManager.Configuration.MinResumeDurationSeconds) + { + positionTicks = 0; + data.Played = true; + } + } + } + + if (item is Audio) + { + data.PlaybackPositionTicks = 0; + } + + data.PlaybackPositionTicks = positionTicks; + + if (incrementPlayCount) + { + data.PlayCount++; + data.LastPlayedDate = DateTime.UtcNow; + } + } + + /// <summary> + /// Identifies the web socket. + /// </summary> + /// <param name="sessionId">The session id.</param> + /// <param name="webSocket">The web socket.</param> + public void IdentifyWebSocket(Guid sessionId, IWebSocketConnection webSocket) + { + _websocketConnections.AddOrUpdate(sessionId, webSocket, (key, existing) => webSocket); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs new file mode 100644 index 000000000..7ce074cd7 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs @@ -0,0 +1,58 @@ +using System.Linq; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Session; +using System; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Session +{ + /// <summary> + /// Class SessionWebSocketListener + /// </summary> + public class SessionWebSocketListener : IWebSocketListener + { + /// <summary> + /// The _true task result + /// </summary> + private readonly Task _trueTaskResult = Task.FromResult(true); + + /// <summary> + /// The _session manager + /// </summary> + private readonly ISessionManager _sessionManager; + + /// <summary> + /// Initializes a new instance of the <see cref="SessionWebSocketListener"/> class. + /// </summary> + /// <param name="sessionManager">The session manager.</param> + public SessionWebSocketListener(ISessionManager sessionManager) + { + _sessionManager = sessionManager; + } + + /// <summary> + /// Processes the message. + /// </summary> + /// <param name="message">The message.</param> + /// <returns>Task.</returns> + public Task ProcessMessage(WebSocketMessageInfo message) + { + if (string.Equals(message.MessageType, "Identify", StringComparison.OrdinalIgnoreCase)) + { + var vals = message.Data.Split('|'); + + var deviceId = vals[0]; + var client = vals[1]; + + var session = _sessionManager.AllConnections.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) && string.Equals(i.Client, client)); + + if (session != null) + { + ((SessionManager)_sessionManager).IdentifyWebSocket(session.Id, message.Connection); + } + } + + return _trueTaskResult; + } + } +} |
