From a8b340cbb29dbcf7fd5d101e640d66470c6d32bf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 8 Nov 2016 13:44:23 -0500 Subject: update portable projects --- .../HttpServer/SocketSharp/SharpWebSocket.cs | 166 +++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs (limited to 'Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs') diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs new file mode 100644 index 000000000..0a312f7b9 --- /dev/null +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs @@ -0,0 +1,166 @@ +using MediaBrowser.Common.Events; +using MediaBrowser.Controller.Net; +using MediaBrowser.Model.Logging; +using System; +using System.Threading; +using System.Threading.Tasks; +using WebSocketState = MediaBrowser.Model.Net.WebSocketState; + +namespace Emby.Server.Implementations.HttpServer.SocketSharp +{ + public class SharpWebSocket : IWebSocket + { + /// + /// The logger + /// + private readonly ILogger _logger; + + public event EventHandler Closed; + + /// + /// Gets or sets the web socket. + /// + /// The web socket. + private SocketHttpListener.WebSocket WebSocket { get; set; } + + private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + + public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger) + { + if (socket == null) + { + throw new ArgumentNullException("socket"); + } + + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + + _logger = logger; + WebSocket = socket; + + socket.OnMessage += socket_OnMessage; + socket.OnClose += socket_OnClose; + socket.OnError += socket_OnError; + + WebSocket.ConnectAsServer(); + } + + void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e) + { + _logger.Error("Error in SharpWebSocket: {0}", e.Message ?? string.Empty); + //EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); + } + + void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e) + { + EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger); + } + + void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e) + { + //if (!string.IsNullOrWhiteSpace(e.Data)) + //{ + // if (OnReceive != null) + // { + // OnReceive(e.Data); + // } + // return; + //} + if (OnReceiveBytes != null) + { + OnReceiveBytes(e.RawData); + } + } + + /// + /// Gets or sets the state. + /// + /// The state. + public WebSocketState State + { + get + { + WebSocketState commonState; + + if (!Enum.TryParse(WebSocket.ReadyState.ToString(), true, out commonState)) + { + _logger.Warn("Unrecognized WebSocketState: {0}", WebSocket.ReadyState.ToString()); + } + + return commonState; + } + } + + /// + /// Sends the async. + /// + /// The bytes. + /// if set to true [end of message]. + /// The cancellation token. + /// Task. + public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken) + { + var completionSource = new TaskCompletionSource(); + + WebSocket.SendAsync(bytes, res => completionSource.TrySetResult(true)); + + return completionSource.Task; + } + + /// + /// Sends the asynchronous. + /// + /// The text. + /// if set to true [end of message]. + /// The cancellation token. + /// Task. + public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken) + { + var completionSource = new TaskCompletionSource(); + + WebSocket.SendAsync(text, res => completionSource.TrySetResult(true)); + + return completionSource.Task; + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + WebSocket.OnMessage -= socket_OnMessage; + WebSocket.OnClose -= socket_OnClose; + WebSocket.OnError -= socket_OnError; + + _cancellationTokenSource.Cancel(); + + WebSocket.Close(); + } + } + + /// + /// Gets or sets the receive action. + /// + /// The receive action. + public Action OnReceiveBytes { get; set; } + + /// + /// Gets or sets the on receive. + /// + /// The on receive. + public Action OnReceive { get; set; } + } +} -- cgit v1.2.3 From 524e7facc87e746745af9095a3f100dcec1799b6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 13 Dec 2016 18:38:26 -0500 Subject: fix socket errors on linux under .net core --- Emby.Common.Implementations/Net/SocketFactory.cs | 12 ++--- .../Networking/NetworkManager.cs | 2 +- .../HttpServer/SocketSharp/SharpWebSocket.cs | 12 +---- MediaBrowser.Api/BaseApiService.cs | 3 +- SocketHttpListener.Portable/WebSocket.cs | 55 +++++++++------------- src/Emby.Server/Program.cs | 9 ++-- 6 files changed, 39 insertions(+), 54 deletions(-) (limited to 'Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs') diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index 1f41ffff5..70c7ba845 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -125,15 +125,15 @@ namespace Emby.Common.Implementations.Net try { -#if NETSTANDARD1_3 - // The ExclusiveAddressUse socket option is a Windows-specific option that, when set to "true," tells Windows not to allow another socket to use the same local address as this socket - // See https://github.com/dotnet/corefx/pull/11509 for more details - if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) +#if NET46 + retVal.ExclusiveAddressUse = false; +#else + // The ExclusiveAddressUse socket option is a Windows-specific option that, when set to "true," tells Windows not to allow another socket to use the same local address as this socket + // See https://github.com/dotnet/corefx/pull/11509 for more details + if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { retVal.ExclusiveAddressUse = false; } -#else - retVal.ExclusiveAddressUse = false; #endif //retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); diff --git a/Emby.Common.Implementations/Networking/NetworkManager.cs b/Emby.Common.Implementations/Networking/NetworkManager.cs index a4e6d47d4..4485e8b14 100644 --- a/Emby.Common.Implementations/Networking/NetworkManager.cs +++ b/Emby.Common.Implementations/Networking/NetworkManager.cs @@ -245,7 +245,7 @@ namespace Emby.Common.Implementations.Networking //} return ipProperties.UnicastAddresses - .Where(i => i.IsDnsEligible) + //.Where(i => i.IsDnsEligible) .Select(i => i.Address) .Where(i => i.AddressFamily == AddressFamily.InterNetwork) .ToList(); diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs index 0a312f7b9..9823a2ff5 100644 --- a/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs +++ b/Emby.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs @@ -102,11 +102,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp /// Task. public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken) { - var completionSource = new TaskCompletionSource(); - - WebSocket.SendAsync(bytes, res => completionSource.TrySetResult(true)); - - return completionSource.Task; + return WebSocket.SendAsync(bytes); } /// @@ -118,11 +114,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp /// Task. public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken) { - var completionSource = new TaskCompletionSource(); - - WebSocket.SendAsync(text, res => completionSource.TrySetResult(true)); - - return completionSource.Task; + return WebSocket.SendAsync(text); } /// diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 7a8951396..07ec6d955 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -151,9 +151,10 @@ namespace MediaBrowser.Api } if (client.IndexOf("web", StringComparison.OrdinalIgnoreCase) == -1 && + + // covers both emby mobile and emby for android mobile client.IndexOf("mobile", StringComparison.OrdinalIgnoreCase) == -1 && client.IndexOf("ios", StringComparison.OrdinalIgnoreCase) == -1 && - client.IndexOf("android", StringComparison.OrdinalIgnoreCase) == -1 && client.IndexOf("theater", StringComparison.OrdinalIgnoreCase) == -1) { options.Fields.Add(Model.Querying.ItemFields.ChildCount); diff --git a/SocketHttpListener.Portable/WebSocket.cs b/SocketHttpListener.Portable/WebSocket.cs index 889880387..9966d3fcf 100644 --- a/SocketHttpListener.Portable/WebSocket.cs +++ b/SocketHttpListener.Portable/WebSocket.cs @@ -5,6 +5,7 @@ using System.IO; using System.Net; using System.Text; using System.Threading; +using System.Threading.Tasks; using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.IO; using SocketHttpListener.Net.WebSockets; @@ -621,26 +622,22 @@ namespace SocketHttpListener } } - private void sendAsync(Opcode opcode, Stream stream, Action completed) + private Task sendAsync(Opcode opcode, Stream stream) { - Func sender = send; - sender.BeginInvoke( - opcode, - stream, - ar => - { - try - { - var sent = sender.EndInvoke(ar); - if (completed != null) - completed(sent); - } - catch (Exception ex) - { - error("An exception has occurred while callback.", ex); - } - }, - null); + var completionSource = new TaskCompletionSource(); + Task.Run(() => + { + try + { + send(opcode, stream); + completionSource.TrySetResult(true); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + }); + return completionSource.Task; } // As server @@ -833,22 +830,18 @@ namespace SocketHttpListener /// /// An array of that represents the binary data to send. /// - /// /// An Action<bool> delegate that references the method(s) called when the send is /// complete. A passed to this delegate is true if the send is /// complete successfully; otherwise, false. - /// - public void SendAsync(byte[] data, Action completed) + public Task SendAsync(byte[] data) { var msg = _readyState.CheckIfOpen() ?? data.CheckIfValidSendData(); if (msg != null) { - error(msg); - - return; + throw new Exception(msg); } - sendAsync(Opcode.Binary, _memoryStreamFactory.CreateNew(data), completed); + return sendAsync(Opcode.Binary, _memoryStreamFactory.CreateNew(data)); } /// @@ -860,22 +853,18 @@ namespace SocketHttpListener /// /// A that represents the text data to send. /// - /// /// An Action<bool> delegate that references the method(s) called when the send is /// complete. A passed to this delegate is true if the send is /// complete successfully; otherwise, false. - /// - public void SendAsync(string data, Action completed) + public Task SendAsync(string data) { var msg = _readyState.CheckIfOpen() ?? data.CheckIfValidSendData(); if (msg != null) { - error(msg); - - return; + throw new Exception(msg); } - sendAsync(Opcode.Text, _memoryStreamFactory.CreateNew(Encoding.UTF8.GetBytes(data)), completed); + return sendAsync(Opcode.Text, _memoryStreamFactory.CreateNew(Encoding.UTF8.GetBytes(data))); } #endregion diff --git a/src/Emby.Server/Program.cs b/src/Emby.Server/Program.cs index 24e391c73..26141a0ce 100644 --- a/src/Emby.Server/Program.cs +++ b/src/Emby.Server/Program.cs @@ -215,9 +215,12 @@ namespace Emby.Server var initProgress = new Progress(); - // Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes - SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT | - ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX); + if (environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows) + { + // Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes + SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT | + ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX); + } var task = _appHost.Init(initProgress); Task.WaitAll(task); -- cgit v1.2.3