diff options
Diffstat (limited to 'MediaBrowser.Controller')
| -rw-r--r-- | MediaBrowser.Controller/IServerApplicationHost.cs | 57 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs | 12 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Net/IHttpServer.cs | 27 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Net/IWebSocketConnection.cs | 41 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Session/ISessionController.cs | 3 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Session/SessionInfo.cs | 74 |
6 files changed, 83 insertions, 131 deletions
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 04ba0fabc..d1d6c74b8 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -39,10 +39,9 @@ namespace MediaBrowser.Controller int HttpsPort { get; } /// <summary> - /// Gets a value indicating whether [supports HTTPS]. + /// Gets a value indicating whether the server should listen on an HTTPS port. /// </summary> - /// <value><c>true</c> if [supports HTTPS]; otherwise, <c>false</c>.</value> - bool EnableHttps { get; } + bool ListenWithHttps { get; } /// <summary> /// Gets a value indicating whether this instance has update available. @@ -57,34 +56,50 @@ namespace MediaBrowser.Controller string FriendlyName { get; } /// <summary> - /// Gets the local ip address. + /// Gets all the local IP addresses of this API instance. Each address is validated by sending a 'ping' request + /// to the API that should exist at the address. /// </summary> - /// <value>The local ip address.</value> + /// <param name="cancellationToken">A cancellation token that can be used to cancel the task.</param> + /// <returns>A list containing all the local IP addresses of the server.</returns> Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken); /// <summary> - /// Gets the local API URL. + /// Gets a local (LAN) URL that can be used to access the API. The hostname used is the first valid configured + /// IP address that can be found via <see cref="GetLocalIpAddresses"/>. HTTPS will be preferred when available. /// </summary> - /// <param name="cancellationToken">Token to cancel the request if needed.</param> - /// <param name="forceHttp">Whether to force usage of plain HTTP protocol.</param> - /// <value>The local API URL.</value> - Task<string> GetLocalApiUrl(CancellationToken cancellationToken, bool forceHttp = false); + /// <param name="cancellationToken">A cancellation token that can be used to cancel the task.</param> + /// <returns>The server URL.</returns> + Task<string> GetLocalApiUrl(CancellationToken cancellationToken); /// <summary> - /// Gets the local API URL. + /// Gets a localhost URL that can be used to access the API using the loop-back IP address (127.0.0.1) + /// over HTTP (not HTTPS). /// </summary> - /// <param name="hostname">The hostname.</param> - /// <param name="forceHttp">Whether to force usage of plain HTTP protocol.</param> - /// <returns>The local API URL.</returns> - string GetLocalApiUrl(ReadOnlySpan<char> hostname, bool forceHttp = false); + /// <returns>The API URL.</returns> + string GetLoopbackHttpApiUrl(); /// <summary> - /// Gets the local API URL. + /// Gets a local (LAN) URL that can be used to access the API. HTTPS will be preferred when available. /// </summary> - /// <param name="address">The IP address.</param> - /// <param name="forceHttp">Whether to force usage of plain HTTP protocol.</param> - /// <returns>The local API URL.</returns> - string GetLocalApiUrl(IPAddress address, bool forceHttp = false); + /// <param name="address">The IP address to use as the hostname in the URL.</param> + /// <returns>The API URL.</returns> + string GetLocalApiUrl(IPAddress address); + + /// <summary> + /// Gets a local (LAN) URL that can be used to access the API. + /// Note: if passing non-null scheme or port it is up to the caller to ensure they form the correct pair. + /// </summary> + /// <param name="hostname">The hostname to use in the URL.</param> + /// <param name="scheme"> + /// The scheme to use for the URL. If null, the scheme will be selected automatically, + /// preferring HTTPS, if available. + /// </param> + /// <param name="port"> + /// The port to use for the URL. If null, the port will be selected automatically, + /// preferring the HTTPS port, if available. + /// </param> + /// <returns>The API URL.</returns> + string GetLocalApiUrl(ReadOnlySpan<char> hostname, string scheme = null, int? port = null); /// <summary> /// Open a URL in an external browser window. @@ -101,7 +116,5 @@ namespace MediaBrowser.Controller string ReverseVirtualPath(string path); Task ExecuteHttpHandlerAsync(HttpContext context, Func<Task> next); - - Task ExecuteWebsocketHandlerAsync(HttpContext context, Func<Task> next); } } diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index b710318ee..1162bff13 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -77,8 +77,6 @@ namespace MediaBrowser.Controller.Net return Task.CompletedTask; } - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - /// <summary> /// Starts sending messages over a web socket /// </summary> @@ -87,12 +85,12 @@ namespace MediaBrowser.Controller.Net { var vals = message.Data.Split(','); - var dueTimeMs = long.Parse(vals[0], UsCulture); - var periodMs = long.Parse(vals[1], UsCulture); + var dueTimeMs = long.Parse(vals[0], CultureInfo.InvariantCulture); + var periodMs = long.Parse(vals[1], CultureInfo.InvariantCulture); var cancellationTokenSource = new CancellationTokenSource(); - Logger.LogDebug("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name); + Logger.LogDebug("WS {1} begin transmitting to {0}", message.Connection.RemoteEndPoint, GetType().Name); var state = new TStateType { @@ -154,7 +152,6 @@ namespace MediaBrowser.Controller.Net { MessageType = Name, Data = data - }, cancellationToken).ConfigureAwait(false); state.DateLastSendUtc = DateTime.UtcNow; @@ -197,7 +194,7 @@ namespace MediaBrowser.Controller.Net /// <param name="connection">The connection.</param> private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, TStateType> connection) { - Logger.LogDebug("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name); + Logger.LogDebug("WS {1} stop transmitting to {0}", connection.Item1.RemoteEndPoint, GetType().Name); // TODO disposing the connection seems to break websockets in subtle ways, so what is the purpose of this function really... // connection.Item1.Dispose(); @@ -242,6 +239,7 @@ namespace MediaBrowser.Controller.Net public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } } diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs index 806478864..efb5f4ac3 100644 --- a/MediaBrowser.Controller/Net/IHttpServer.cs +++ b/MediaBrowser.Controller/Net/IHttpServer.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Events; using MediaBrowser.Model.Services; @@ -9,9 +8,9 @@ using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net { /// <summary> - /// Interface IHttpServer + /// Interface IHttpServer. /// </summary> - public interface IHttpServer : IDisposable + public interface IHttpServer { /// <summary> /// Gets the URL prefix. @@ -20,11 +19,6 @@ namespace MediaBrowser.Controller.Net string[] UrlPrefixes { get; } /// <summary> - /// Stops this instance. - /// </summary> - void Stop(); - - /// <summary> /// Occurs when [web socket connected]. /// </summary> event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected; @@ -40,22 +34,17 @@ namespace MediaBrowser.Controller.Net string GlobalResponse { get; set; } /// <summary> - /// Sends the http context to the socket listener + /// The HTTP request handler /// </summary> - /// <param name="ctx"></param> + /// <param name="context"></param> /// <returns></returns> - Task ProcessWebSocketRequest(HttpContext ctx); + Task RequestHandler(HttpContext context); /// <summary> - /// The HTTP request handler + /// Get the default CORS headers /// </summary> - /// <param name="httpReq"></param> - /// <param name="urlString"></param> - /// <param name="host"></param> - /// <param name="localPath"></param> - /// <param name="cancellationToken"></param> + /// <param name="req"></param> /// <returns></returns> - Task RequestHandler(IHttpRequest httpReq, string urlString, string host, string localPath, - CancellationToken cancellationToken); + IDictionary<string, string> GetDefaultCorsHeaders(IRequest req); } } diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs index 31eb7ccb7..09e43c683 100644 --- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs +++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs @@ -1,4 +1,7 @@ +#nullable enable + using System; +using System.Net; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; @@ -7,18 +10,12 @@ using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net { - public interface IWebSocketConnection : IDisposable + public interface IWebSocketConnection { /// <summary> /// Occurs when [closed]. /// </summary> - event EventHandler<EventArgs> Closed; - - /// <summary> - /// Gets the id. - /// </summary> - /// <value>The id.</value> - Guid Id { get; } + event EventHandler<EventArgs>? Closed; /// <summary> /// Gets the last activity date. @@ -27,21 +24,16 @@ namespace MediaBrowser.Controller.Net DateTime LastActivityDate { get; } /// <summary> - /// Gets or sets the URL. - /// </summary> - /// <value>The URL.</value> - string Url { get; set; } - /// <summary> /// Gets or sets the query string. /// </summary> /// <value>The query string.</value> - IQueryCollection QueryString { get; set; } + IQueryCollection QueryString { get; } /// <summary> /// Gets or sets the receive action. /// </summary> /// <value>The receive action.</value> - Func<WebSocketMessageInfo, Task> OnReceive { get; set; } + Func<WebSocketMessageInfo, Task>? OnReceive { get; set; } /// <summary> /// Gets the state. @@ -53,7 +45,7 @@ namespace MediaBrowser.Controller.Net /// Gets the remote end point. /// </summary> /// <value>The remote end point.</value> - string RemoteEndPoint { get; } + IPAddress? RemoteEndPoint { get; } /// <summary> /// Sends a message asynchronously. @@ -65,21 +57,6 @@ namespace MediaBrowser.Controller.Net /// <exception cref="ArgumentNullException">message</exception> Task SendAsync<T>(WebSocketMessage<T> message, CancellationToken cancellationToken); - /// <summary> - /// Sends a message asynchronously. - /// </summary> - /// <param name="buffer">The buffer.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task SendAsync(byte[] buffer, CancellationToken cancellationToken); - - /// <summary> - /// Sends a message asynchronously. - /// </summary> - /// <param name="text">The text.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="ArgumentNullException">buffer</exception> - Task SendAsync(string text, CancellationToken cancellationToken); + Task ProcessAsync(CancellationToken cancellationToken = default); } } diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs index a59c96ac7..04450085b 100644 --- a/MediaBrowser.Controller/Session/ISessionController.cs +++ b/MediaBrowser.Controller/Session/ISessionController.cs @@ -1,3 +1,4 @@ +using System; using System.Threading; using System.Threading.Tasks; @@ -20,6 +21,6 @@ namespace MediaBrowser.Controller.Session /// <summary> /// Sends the message. /// </summary> - Task SendMessage<T>(string name, string messageId, T data, ISessionController[] allControllers, CancellationToken cancellationToken); + Task SendMessage<T>(string name, Guid messageId, T data, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index f1f10a3a3..2ba7c9fec 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -10,13 +10,23 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Session { /// <summary> - /// Class SessionInfo + /// Class SessionInfo. /// </summary> - public class SessionInfo : IDisposable + public sealed class SessionInfo : IDisposable { - private ISessionManager _sessionManager; + // 1 second + private const long ProgressIncrement = 10000000; + + private readonly ISessionManager _sessionManager; private readonly ILogger _logger; + + private readonly object _progressLock = new object(); + private Timer _progressTimer; + private PlaybackProgressInfo _lastProgressInfo; + + private bool _disposed = false; + public SessionInfo(ISessionManager sessionManager, ILogger logger) { _sessionManager = sessionManager; @@ -97,8 +107,6 @@ namespace MediaBrowser.Controller.Session /// <value>The name of the device.</value> public string DeviceName { get; set; } - public string DeviceType { get; set; } - /// <summary> /// Gets or sets the now playing item. /// </summary> @@ -128,22 +136,6 @@ namespace MediaBrowser.Controller.Session [JsonIgnore] public ISessionController[] SessionControllers { get; set; } - /// <summary> - /// Gets or sets the supported commands. - /// </summary> - /// <value>The supported commands.</value> - public string[] SupportedCommands - { - get - { - if (Capabilities == null) - { - return new string[] { }; - } - return Capabilities.SupportedCommands; - } - } - public TranscodingInfo TranscodingInfo { get; set; } /// <summary> @@ -215,6 +207,14 @@ namespace MediaBrowser.Controller.Session } } + public QueueItem[] NowPlayingQueue { get; set; } + + public bool HasCustomDeviceName { get; set; } + + public string PlaylistItemId { get; set; } + + public string UserPrimaryImageTag { get; set; } + public Tuple<ISessionController, bool> EnsureController<T>(Func<SessionInfo, ISessionController> factory) { var controllers = SessionControllers.ToList(); @@ -258,10 +258,6 @@ namespace MediaBrowser.Controller.Session return false; } - private readonly object _progressLock = new object(); - private Timer _progressTimer; - private PlaybackProgressInfo _lastProgressInfo; - public void StartAutomaticProgress(PlaybackProgressInfo progressInfo) { if (_disposed) @@ -284,9 +280,6 @@ namespace MediaBrowser.Controller.Session } } - // 1 second - private const long ProgressIncrement = 10000000; - private async void OnProgressTimerCallback(object state) { if (_disposed) @@ -345,8 +338,7 @@ namespace MediaBrowser.Controller.Session } } - private bool _disposed = false; - + /// <inheritdoc /> public void Dispose() { _disposed = true; @@ -358,30 +350,12 @@ namespace MediaBrowser.Controller.Session foreach (var controller in controllers) { - var disposable = controller as IDisposable; - - if (disposable != null) + if (controller is IDisposable disposable) { _logger.LogDebug("Disposing session controller {0}", disposable.GetType().Name); - - try - { - disposable.Dispose(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error disposing session controller"); - } + disposable.Dispose(); } } - - _sessionManager = null; } - - public QueueItem[] NowPlayingQueue { get; set; } - public bool HasCustomDeviceName { get; set; } - public string PlaylistItemId { get; set; } - public string ServerId { get; set; } - public string UserPrimaryImageTag { get; set; } } } |
