From bfcd1b520fd79b893e721ba916ae5e1656407d2f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 16 Aug 2017 02:43:41 -0400 Subject: merge common implementations and server implementations --- .../Net/DisposableManagedObjectBase.cs | 71 +++++ Emby.Server.Implementations/Net/NetAcceptSocket.cs | 154 +++++++++++ Emby.Server.Implementations/Net/SocketAcceptor.cs | 127 +++++++++ Emby.Server.Implementations/Net/SocketFactory.cs | 294 +++++++++++++++++++++ Emby.Server.Implementations/Net/UdpSocket.cs | 255 ++++++++++++++++++ 5 files changed, 901 insertions(+) create mode 100644 Emby.Server.Implementations/Net/DisposableManagedObjectBase.cs create mode 100644 Emby.Server.Implementations/Net/NetAcceptSocket.cs create mode 100644 Emby.Server.Implementations/Net/SocketAcceptor.cs create mode 100644 Emby.Server.Implementations/Net/SocketFactory.cs create mode 100644 Emby.Server.Implementations/Net/UdpSocket.cs (limited to 'Emby.Server.Implementations/Net') diff --git a/Emby.Server.Implementations/Net/DisposableManagedObjectBase.cs b/Emby.Server.Implementations/Net/DisposableManagedObjectBase.cs new file mode 100644 index 0000000000..b18335da77 --- /dev/null +++ b/Emby.Server.Implementations/Net/DisposableManagedObjectBase.cs @@ -0,0 +1,71 @@ +using System; + +namespace Emby.Server.Implementations.Net +{ + /// + /// Correclty implements the interface and pattern for an object containing only managed resources, and adds a few common niceities not on the interface such as an property. + /// + public abstract class DisposableManagedObjectBase : IDisposable + { + + #region Public Methods + + /// + /// Override this method and dispose any objects you own the lifetime of if disposing is true; + /// + /// True if managed objects should be disposed, if false, only unmanaged resources should be released. + protected abstract void Dispose(bool disposing); + + /// + /// Throws and if the property is true. + /// + /// + /// Thrown if the property is true. + /// + protected virtual void ThrowIfDisposed() + { + if (this.IsDisposed) throw new ObjectDisposedException(this.GetType().FullName); + } + + #endregion + + #region Public Properties + + /// + /// Sets or returns a boolean indicating whether or not this instance has been disposed. + /// + /// + public bool IsDisposed + { + get; + private set; + } + + #endregion + + #region IDisposable Members + + /// + /// Disposes this object instance and all internally managed resources. + /// + /// + /// Sets the property to true. Does not explicitly throw an exception if called multiple times, but makes no promises about behaviour of derived classes. + /// + /// + public void Dispose() + { + try + { + IsDisposed = true; + + Dispose(true); + } + finally + { + GC.SuppressFinalize(this); + } + } + + #endregion + } +} diff --git a/Emby.Server.Implementations/Net/NetAcceptSocket.cs b/Emby.Server.Implementations/Net/NetAcceptSocket.cs new file mode 100644 index 0000000000..936a66c0b0 --- /dev/null +++ b/Emby.Server.Implementations/Net/NetAcceptSocket.cs @@ -0,0 +1,154 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Emby.Server.Implementations.Networking; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; + +namespace Emby.Server.Implementations.Net +{ + public class NetAcceptSocket : IAcceptSocket + { + public Socket Socket { get; private set; } + private readonly ILogger _logger; + + public bool DualMode { get; private set; } + + public NetAcceptSocket(Socket socket, ILogger logger, bool isDualMode) + { + if (socket == null) + { + throw new ArgumentNullException("socket"); + } + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + + Socket = socket; + _logger = logger; + DualMode = isDualMode; + } + + public IpEndPointInfo LocalEndPoint + { + get + { + return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.LocalEndPoint); + } + } + + public IpEndPointInfo RemoteEndPoint + { + get + { + return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.RemoteEndPoint); + } + } + + public void Connect(IpEndPointInfo endPoint) + { + var nativeEndpoint = NetworkManager.ToIPEndPoint(endPoint); + + Socket.Connect(nativeEndpoint); + } + + public void Close() + { +#if NET46 + Socket.Close(); +#else + Socket.Dispose(); +#endif + } + + public void Shutdown(bool both) + { + if (both) + { + Socket.Shutdown(SocketShutdown.Both); + } + else + { + // Change interface if ever needed + throw new NotImplementedException(); + } + } + + public void Listen(int backlog) + { + Socket.Listen(backlog); + } + + public void Bind(IpEndPointInfo endpoint) + { + var nativeEndpoint = NetworkManager.ToIPEndPoint(endpoint); + + Socket.Bind(nativeEndpoint); + } + + private SocketAcceptor _acceptor; + public void StartAccept(Action onAccept, Func isClosed) + { + _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed, DualMode); + + _acceptor.StartAccept(); + } + + public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken) + { + var options = TransmitFileOptions.UseDefaultWorkerThread; + + var completionSource = new TaskCompletionSource(); + + var result = Socket.BeginSendFile(path, preBuffer, postBuffer, options, new AsyncCallback(FileSendCallback), new Tuple>(Socket, path, completionSource)); + + return completionSource.Task; + } + + public IAsyncResult BeginSendFile(string path, byte[] preBuffer, byte[] postBuffer, AsyncCallback callback, object state) + { + var options = TransmitFileOptions.UseDefaultWorkerThread; + + return Socket.BeginSendFile(path, preBuffer, postBuffer, options, new AsyncCallback(FileSendCallback), state); + } + + public void EndSendFile(IAsyncResult result) + { + Socket.EndSendFile(result); + } + + private void FileSendCallback(IAsyncResult ar) + { + // Retrieve the socket from the state object. + Tuple> data = (Tuple>)ar.AsyncState; + + var client = data.Item1; + var path = data.Item2; + var taskCompletion = data.Item3; + + // Complete sending the data to the remote device. + try + { + client.EndSendFile(ar); + taskCompletion.TrySetResult(true); + } + catch (SocketException ex) + { + _logger.Info("Socket.SendFile failed for {0}. error code {1}", path, ex.SocketErrorCode); + taskCompletion.TrySetException(ex); + } + catch (Exception ex) + { + taskCompletion.TrySetException(ex); + } + } + + public void Dispose() + { + Socket.Dispose(); + } + } +} diff --git a/Emby.Server.Implementations/Net/SocketAcceptor.cs b/Emby.Server.Implementations/Net/SocketAcceptor.cs new file mode 100644 index 0000000000..288ba93adb --- /dev/null +++ b/Emby.Server.Implementations/Net/SocketAcceptor.cs @@ -0,0 +1,127 @@ +using System; +using System.Net.Sockets; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; + +namespace Emby.Server.Implementations.Net +{ + public class SocketAcceptor + { + private readonly ILogger _logger; + private readonly Socket _originalSocket; + private readonly Func _isClosed; + private readonly Action _onAccept; + private readonly bool _isDualMode; + + public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed, bool isDualMode) + { + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + if (originalSocket == null) + { + throw new ArgumentNullException("originalSocket"); + } + if (onAccept == null) + { + throw new ArgumentNullException("onAccept"); + } + if (isClosed == null) + { + throw new ArgumentNullException("isClosed"); + } + + _logger = logger; + _originalSocket = originalSocket; + _isClosed = isClosed; + _isDualMode = isDualMode; + _onAccept = onAccept; + } + + public void StartAccept() + { + Socket dummy = null; + StartAccept(null, ref dummy); + } + + public void StartAccept(SocketAsyncEventArgs acceptEventArg, ref Socket accepted) + { + if (acceptEventArg == null) + { + acceptEventArg = new SocketAsyncEventArgs(); + acceptEventArg.Completed += new EventHandler(AcceptEventArg_Completed); + } + else + { + // acceptSocket must be cleared since the context object is being reused + acceptEventArg.AcceptSocket = null; + } + + try + { + bool willRaiseEvent = _originalSocket.AcceptAsync(acceptEventArg); + + if (!willRaiseEvent) + { + ProcessAccept(acceptEventArg); + } + } + catch (Exception ex) + { + if (accepted != null) + { + try + { +#if NET46 + accepted.Close(); +#else + accepted.Dispose(); +#endif + } + catch + { + } + accepted = null; + } + } + } + + // This method is the callback method associated with Socket.AcceptAsync + // operations and is invoked when an accept operation is complete + // + void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) + { + ProcessAccept(e); + } + + private void ProcessAccept(SocketAsyncEventArgs e) + { + if (_isClosed()) + { + return; + } + + // http://msdn.microsoft.com/en-us/library/system.net.sockets.acceptSocket.acceptasync%28v=vs.110%29.aspx + // Under certain conditions ConnectionReset can occur + // Need to attept to re-accept + if (e.SocketError == SocketError.ConnectionReset) + { + _logger.Error("SocketError.ConnectionReset reported. Attempting to re-accept."); + Socket dummy = null; + StartAccept(e, ref dummy); + return; + } + + var acceptSocket = e.AcceptSocket; + if (acceptSocket != null) + { + //ProcessAccept(acceptSocket); + _onAccept(new NetAcceptSocket(acceptSocket, _logger, _isDualMode)); + } + + // Accept the next connection request + StartAccept(e, ref acceptSocket); + } + } +} diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs new file mode 100644 index 0000000000..ab3bd0b315 --- /dev/null +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -0,0 +1,294 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using Emby.Server.Implementations.Networking; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; + +namespace Emby.Server.Implementations.Net +{ + public class SocketFactory : ISocketFactory + { + // THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS + // Be careful to check any changes compile and work for all platform projects it is shared in. + + // Not entirely happy with this. Would have liked to have done something more generic/reusable, + // but that wasn't really the point so kept to YAGNI principal for now, even if the + // interfaces are a bit ugly, specific and make assumptions. + + private readonly ILogger _logger; + + public SocketFactory(ILogger logger) + { + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + + _logger = logger; + } + + public IAcceptSocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) + { + try + { + var addressFamily = family == IpAddressFamily.InterNetwork + ? AddressFamily.InterNetwork + : AddressFamily.InterNetworkV6; + + var socket = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); + + if (dualMode) + { + socket.DualMode = true; + } + + return new NetAcceptSocket(socket, _logger, dualMode); + } + catch (SocketException ex) + { + throw new SocketCreateException(ex.SocketErrorCode.ToString(), ex); + } + catch (ArgumentException ex) + { + if (dualMode) + { + // Mono for BSD incorrectly throws ArgumentException instead of SocketException + throw new SocketCreateException("AddressFamilyNotSupported", ex); + } + else + { + throw; + } + } + } + + public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort) + { + if (remotePort < 0) throw new ArgumentException("remotePort cannot be less than zero.", "remotePort"); + + var addressFamily = remoteAddress.AddressFamily == IpAddressFamily.InterNetwork + ? AddressFamily.InterNetwork + : AddressFamily.InterNetworkV6; + + var retVal = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); + + try + { + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + } + catch (SocketException) + { + // This is not supported on all operating systems (qnap) + } + + try + { + return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } + + /// + /// Creates a new UDP acceptSocket and binds it to the specified local port. + /// + /// An integer specifying the local port to bind the acceptSocket to. + public ISocket CreateUdpSocket(int localPort) + { + if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); + + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + try + { + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + return new UdpSocket(retVal, localPort, IPAddress.Any); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } + + public ISocket CreateUdpBroadcastSocket(int localPort) + { + if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); + + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + try + { + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); + + return new UdpSocket(retVal, localPort, IPAddress.Any); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } + + /// + /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port. + /// + /// An implementation of the interface used by RSSDP components to perform acceptSocket operations. + public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) + { + if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); + + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + try + { + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); + + var localIp = NetworkManager.ToIPAddress(localIpAddress); + + retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp)); + return new UdpSocket(retVal, localPort, localIp); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } + + /// + /// Creates a new UDP acceptSocket that is a member of the specified multicast IP address, and binds it to the specified local port. + /// + /// The multicast IP address to make the acceptSocket a member of. + /// The multicast time to live value for the acceptSocket. + /// The number of the local port to bind to. + /// + public ISocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort) + { + if (ipAddress == null) throw new ArgumentNullException("ipAddress"); + if (ipAddress.Length == 0) throw new ArgumentException("ipAddress cannot be an empty string.", "ipAddress"); + if (multicastTimeToLive <= 0) throw new ArgumentException("multicastTimeToLive cannot be zero or less.", "multicastTimeToLive"); + if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); + + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + + try + { + retVal.ExclusiveAddressUse = false; + //retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive); + + var localIp = IPAddress.Any; + + retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(ipAddress), localIp)); + retVal.MulticastLoopback = true; + + return new UdpSocket(retVal, localPort, localIp); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } + + public Stream CreateNetworkStream(ISocket socket, bool ownsSocket) + { + var netSocket = (UdpSocket)socket; + + return new SocketStream(netSocket.Socket, ownsSocket); + } + } + + public class SocketStream : Stream + { + private readonly Socket _socket; + + public SocketStream(Socket socket, bool ownsSocket) + { + _socket = socket; + } + + public override void Flush() + { + } + + public override bool CanRead + { + get { return true; } + } + public override bool CanSeek + { + get { return false; } + } + public override bool CanWrite + { + get { return true; } + } + public override long Length + { + get { throw new NotImplementedException(); } + } + public override long Position + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public override void Write(byte[] buffer, int offset, int count) + { + _socket.Send(buffer, offset, count, SocketFlags.None); + } + + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + return _socket.BeginSend(buffer, offset, count, SocketFlags.None, callback, state); + } + + public override void EndWrite(IAsyncResult asyncResult) + { + _socket.EndSend(asyncResult); + } + + public override void SetLength(long value) + { + throw new NotImplementedException(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotImplementedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return _socket.Receive(buffer, offset, count, SocketFlags.None); + } + + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + return _socket.BeginReceive(buffer, offset, count, SocketFlags.None, callback, state); + } + + public override int EndRead(IAsyncResult asyncResult) + { + return _socket.EndReceive(asyncResult); + } + } + +} diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs new file mode 100644 index 0000000000..58e4d6f89b --- /dev/null +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -0,0 +1,255 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Emby.Server.Implementations.Networking; +using MediaBrowser.Model.Net; + +namespace Emby.Server.Implementations.Net +{ + // THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS + // Be careful to check any changes compile and work for all platform projects it is shared in. + + public sealed class UdpSocket : DisposableManagedObjectBase, ISocket + { + private Socket _Socket; + private int _LocalPort; + + public Socket Socket + { + get { return _Socket; } + } + + private readonly SocketAsyncEventArgs _receiveSocketAsyncEventArgs = new SocketAsyncEventArgs() + { + SocketFlags = SocketFlags.None + }; + + private readonly SocketAsyncEventArgs _sendSocketAsyncEventArgs = new SocketAsyncEventArgs() + { + SocketFlags = SocketFlags.None + }; + + private TaskCompletionSource _currentReceiveTaskCompletionSource; + private TaskCompletionSource _currentSendTaskCompletionSource; + + public UdpSocket(Socket socket, int localPort, IPAddress ip) + { + if (socket == null) throw new ArgumentNullException("socket"); + + _Socket = socket; + _LocalPort = localPort; + LocalIPAddress = NetworkManager.ToIpAddressInfo(ip); + + _Socket.Bind(new IPEndPoint(ip, _LocalPort)); + + InitReceiveSocketAsyncEventArgs(); + } + + private void InitReceiveSocketAsyncEventArgs() + { + var receiveBuffer = new byte[8192]; + _receiveSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length); + _receiveSocketAsyncEventArgs.Completed += _receiveSocketAsyncEventArgs_Completed; + + var sendBuffer = new byte[8192]; + _sendSocketAsyncEventArgs.SetBuffer(sendBuffer, 0, sendBuffer.Length); + _sendSocketAsyncEventArgs.Completed += _sendSocketAsyncEventArgs_Completed; + } + + private void _receiveSocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e) + { + var tcs = _currentReceiveTaskCompletionSource; + if (tcs != null) + { + _currentReceiveTaskCompletionSource = null; + + if (e.SocketError == SocketError.Success) + { + tcs.TrySetResult(new SocketReceiveResult + { + Buffer = e.Buffer, + ReceivedBytes = e.BytesTransferred, + RemoteEndPoint = ToIpEndPointInfo(e.RemoteEndPoint as IPEndPoint), + LocalIPAddress = LocalIPAddress + }); + } + else + { + tcs.TrySetException(new Exception("SocketError: " + e.SocketError)); + } + } + } + + private void _sendSocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e) + { + var tcs = _currentSendTaskCompletionSource; + if (tcs != null) + { + _currentSendTaskCompletionSource = null; + + if (e.SocketError == SocketError.Success) + { + tcs.TrySetResult(e.BytesTransferred); + } + else + { + tcs.TrySetException(new Exception("SocketError: " + e.SocketError)); + } + } + } + + public UdpSocket(Socket socket, IpEndPointInfo endPoint) + { + if (socket == null) throw new ArgumentNullException("socket"); + + _Socket = socket; + _Socket.Connect(NetworkManager.ToIPEndPoint(endPoint)); + + InitReceiveSocketAsyncEventArgs(); + } + + public IpAddressInfo LocalIPAddress + { + get; + private set; + } + + public IAsyncResult BeginReceive(byte[] buffer, int offset, int count, AsyncCallback callback) + { + EndPoint receivedFromEndPoint = new IPEndPoint(IPAddress.Any, 0); + + return _Socket.BeginReceiveFrom(buffer, offset, count, SocketFlags.None, ref receivedFromEndPoint, callback, buffer); + } + + public int Receive(byte[] buffer, int offset, int count) + { + return _Socket.Receive(buffer, 0, buffer.Length, SocketFlags.None); + } + + public SocketReceiveResult EndReceive(IAsyncResult result) + { + IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); + EndPoint remoteEndPoint = (EndPoint)sender; + + var receivedBytes = _Socket.EndReceiveFrom(result, ref remoteEndPoint); + + var buffer = (byte[]) result.AsyncState; + + return new SocketReceiveResult + { + ReceivedBytes = receivedBytes, + RemoteEndPoint = ToIpEndPointInfo((IPEndPoint)remoteEndPoint), + Buffer = buffer, + LocalIPAddress = LocalIPAddress + }; + } + + public Task ReceiveAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + var taskCompletion = new TaskCompletionSource(); + + Action callback = callbackResult => + { + try + { + taskCompletion.TrySetResult(EndReceive(callbackResult)); + } + catch (Exception ex) + { + taskCompletion.TrySetException(ex); + } + }; + + var result = BeginReceive(buffer, offset, count, new AsyncCallback(callback)); + + if (result.CompletedSynchronously) + { + callback(result); + } + + cancellationToken.Register(() => taskCompletion.TrySetCanceled()); + + return taskCompletion.Task; + } + + public Task ReceiveAsync(CancellationToken cancellationToken) + { + var buffer = new byte[8192]; + + return ReceiveAsync(buffer, 0, buffer.Length, cancellationToken); + } + + public Task SendToAsync(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, CancellationToken cancellationToken) + { + var taskCompletion = new TaskCompletionSource(); + + Action callback = callbackResult => + { + try + { + taskCompletion.TrySetResult(EndSendTo(callbackResult)); + } + catch (Exception ex) + { + taskCompletion.TrySetException(ex); + } + }; + + var result = BeginSendTo(buffer, offset, size, endPoint, new AsyncCallback(callback), null); + + if (result.CompletedSynchronously) + { + callback(result); + } + + cancellationToken.Register(() => taskCompletion.TrySetCanceled()); + + return taskCompletion.Task; + } + + public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, AsyncCallback callback, object state) + { + var ipEndPoint = NetworkManager.ToIPEndPoint(endPoint); + + return _Socket.BeginSendTo(buffer, offset, size, SocketFlags.None, ipEndPoint, callback, state); + } + + public int EndSendTo(IAsyncResult result) + { + return _Socket.EndSendTo(result); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + var socket = _Socket; + if (socket != null) + socket.Dispose(); + + var tcs = _currentReceiveTaskCompletionSource; + if (tcs != null) + { + tcs.TrySetCanceled(); + } + var sendTcs = _currentSendTaskCompletionSource; + if (sendTcs != null) + { + sendTcs.TrySetCanceled(); + } + } + } + + private static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint) + { + if (endpoint == null) + { + return null; + } + + return NetworkManager.ToIpEndPointInfo(endpoint); + } + } +} -- cgit v1.2.3 From a7dcf7191a71bfefd4a8c69d24d2eec53973bb83 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 17 Aug 2017 16:19:02 -0400 Subject: add fixes for .net core --- .../AppBase/BaseApplicationPaths.cs | 9 ++-- Emby.Server.Implementations/ApplicationHost.cs | 56 +++++++++++----------- .../Cryptography/CertificateGenerator.cs | 42 +++++++++++++++- .../EnvironmentInfo/EnvironmentInfo.cs | 20 +++++--- .../HttpClientManager/HttpClientManager.cs | 10 ++-- Emby.Server.Implementations/Library/UserManager.cs | 6 +-- .../Logging/SimpleLogManager.cs | 4 +- Emby.Server.Implementations/Net/SocketFactory.cs | 23 ++++++--- .../ServerApplicationPaths.cs | 4 +- MediaBrowser.Model/Session/PlaybackProgressInfo.cs | 2 +- MediaBrowser.Server.Mono/MonoAppHost.cs | 2 +- MediaBrowser.Server.Mono/Program.cs | 49 +++++-------------- .../ImageEncoderHelper.cs | 1 - MediaBrowser.ServerApplication/MainStartup.cs | 16 ++----- .../MediaBrowser.ServerApplication.csproj | 4 -- MediaBrowser.ServerApplication/WindowsAppHost.cs | 4 +- 16 files changed, 132 insertions(+), 120 deletions(-) (limited to 'Emby.Server.Implementations/Net') diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs index 54d1d53023..1e63aa1a6d 100644 --- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs +++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs @@ -13,15 +13,12 @@ namespace Emby.Server.Implementations.AppBase /// /// Initializes a new instance of the class. /// - protected BaseApplicationPaths(string programDataPath, string appFolderPath, Action createDirectoryFn) + protected BaseApplicationPaths(string programDataPath, string appFolderPath) { ProgramDataPath = programDataPath; ProgramSystemPath = appFolderPath; - CreateDirectoryFn = createDirectoryFn; } - protected Action CreateDirectoryFn; - public string ProgramDataPath { get; private set; } /// @@ -45,7 +42,7 @@ namespace Emby.Server.Implementations.AppBase { _dataDirectory = Path.Combine(ProgramDataPath, "data"); - CreateDirectoryFn(_dataDirectory); + Directory.CreateDirectory(_dataDirectory); } return _dataDirectory; @@ -152,7 +149,7 @@ namespace Emby.Server.Implementations.AppBase { _cachePath = Path.Combine(ProgramDataPath, "cache"); - CreateDirectoryFn(_cachePath); + Directory.CreateDirectory(_cachePath); } return _cachePath; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3ad8fe7df9..bc88d652c4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -111,6 +111,7 @@ using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; +using Emby.Server.Core.Cryptography; using Emby.Server.Implementations.Archiving; using Emby.Server.Implementations.Cryptography; using Emby.Server.Implementations.Diagnostics; @@ -368,8 +369,6 @@ namespace Emby.Server.Implementations internal IPowerManagement PowerManagement { get; private set; } internal IImageEncoder ImageEncoder { get; private set; } - private readonly Action _certificateGenerator; - private readonly Func _defaultUserNameFactory; protected IProcessFactory ProcessFactory { get; private set; } protected ITimerFactory TimerFactory { get; private set; } protected ICryptoProvider CryptographyProvider = new CryptographyProvider(); @@ -394,10 +393,7 @@ namespace Emby.Server.Implementations IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, ISystemEvents systemEvents, - IMemoryStreamFactory memoryStreamFactory, - INetworkManager networkManager, - Action certificateGenerator, - Func defaultUsernameFactory) + INetworkManager networkManager) { // hack alert, until common can target .net core BaseExtensions.CryptographyProvider = CryptographyProvider; @@ -407,7 +403,7 @@ namespace Emby.Server.Implementations NetworkManager = networkManager; EnvironmentInfo = environmentInfo; SystemEvents = systemEvents; - MemoryStreamFactory = memoryStreamFactory; + MemoryStreamFactory = new MemoryStreamProvider(); FailedAssemblies = new List(); @@ -421,9 +417,7 @@ namespace Emby.Server.Implementations Logger = LogManager.GetLogger("App"); StartupOptions = options; - _certificateGenerator = certificateGenerator; _releaseAssetFilename = releaseAssetFilename; - _defaultUserNameFactory = defaultUsernameFactory; PowerManagement = powerManagement; ImageEncoder = imageEncoder; @@ -917,7 +911,7 @@ namespace Emby.Server.Implementations AuthenticationRepository = GetAuthenticationRepository(); RegisterSingleInstance(AuthenticationRepository); - UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer, FileSystemManager, CryptographyProvider, _defaultUserNameFactory()); + UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer, FileSystemManager, CryptographyProvider); RegisterSingleInstance(UserManager); LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager); @@ -1257,7 +1251,7 @@ namespace Emby.Server.Implementations case MediaBrowser.Model.System.Architecture.X64: return new[] { - "https://embydata.com/downloads/ffmpeg/osx/ffmpeg-x64-20170308.7z" + "https://embydata.com/downloads/ffmpeg/osx/ffmpeg-x64-20170308.7z" }; } @@ -1271,12 +1265,12 @@ namespace Emby.Server.Implementations case MediaBrowser.Model.System.Architecture.X64: return new[] { - "https://embydata.com/downloads/ffmpeg/windows/ffmpeg-20170308-win64.7z" + "https://embydata.com/downloads/ffmpeg/windows/ffmpeg-20170308-win64.7z" }; case MediaBrowser.Model.System.Architecture.X86: return new[] { - "https://embydata.com/downloads/ffmpeg/windows/ffmpeg-20170308-win32.7z" + "https://embydata.com/downloads/ffmpeg/windows/ffmpeg-20170308-win32.7z" }; } @@ -1290,12 +1284,12 @@ namespace Emby.Server.Implementations case MediaBrowser.Model.System.Architecture.X64: return new[] { - "https://embydata.com/downloads/ffmpeg/linux/ffmpeg-git-20170301-64bit-static.7z" + "https://embydata.com/downloads/ffmpeg/linux/ffmpeg-git-20170301-64bit-static.7z" }; case MediaBrowser.Model.System.Architecture.X86: return new[] { - "https://embydata.com/downloads/ffmpeg/linux/ffmpeg-git-20170301-32bit-static.7z" + "https://embydata.com/downloads/ffmpeg/linux/ffmpeg-git-20170301-32bit-static.7z" }; } @@ -1442,17 +1436,17 @@ namespace Emby.Server.Implementations StartServer(); LibraryManager.AddParts(GetExports(), - GetExports(), - GetExports(), - GetExports(), - GetExports(), - GetExports()); + GetExports(), + GetExports(), + GetExports(), + GetExports(), + GetExports()); ProviderManager.AddParts(GetExports(), - GetExports(), - GetExports(), - GetExports(), - GetExports()); + GetExports(), + GetExports(), + GetExports(), + GetExports()); ImageProcessor.AddParts(GetExports()); @@ -1652,7 +1646,7 @@ namespace Emby.Server.Implementations try { - _certificateGenerator(certPath, certHost, password); + CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, password, Logger); } catch (Exception ex) { @@ -2158,7 +2152,7 @@ namespace Emby.Server.Implementations list.Remove(plugin); Plugins = list.ToArray(); } - + /// /// Checks for update. /// @@ -2176,7 +2170,7 @@ namespace Emby.Server.Implementations } var result = await new GithubUpdater(HttpClient, JsonSerializer).CheckForUpdateResult("MediaBrowser", "Emby", ApplicationVersion, updateLevel, _releaseAssetFilename, - "MBServer", "Mbserver.zip", cacheLength, cancellationToken).ConfigureAwait(false); + "MBServer", "Mbserver.zip", cacheLength, cancellationToken).ConfigureAwait(false); HasUpdateAvailable = result.IsUpdateAvailable; @@ -2314,12 +2308,18 @@ namespace Emby.Server.Implementations NotifyPendingRestart(); } + private bool _disposed; /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { - Dispose(true); + if (!_disposed) + { + _disposed = true; + + Dispose(true); + } } /// diff --git a/Emby.Server.Implementations/Cryptography/CertificateGenerator.cs b/Emby.Server.Implementations/Cryptography/CertificateGenerator.cs index 2600d74702..b4c84a6003 100644 --- a/Emby.Server.Implementations/Cryptography/CertificateGenerator.cs +++ b/Emby.Server.Implementations/Cryptography/CertificateGenerator.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using System.Security.Cryptography; +using System.Xml; namespace Emby.Server.Core.Cryptography { @@ -27,7 +28,11 @@ namespace Emby.Server.Core.Cryptography DateTime notAfter = DateTime.Now.AddYears(10); RSA issuerKey = RSA.Create(); +#if NET46 issuerKey.FromXmlString(MonoTestRootAgency); +#else + RSACryptoServiceProviderExtensions.FromXmlString(issuerKey, MonoTestRootAgency); +#endif RSA subjectKey = RSA.Create(); // serial number MUST be positive @@ -44,7 +49,7 @@ namespace Emby.Server.Core.Cryptography cb.NotAfter = notAfter; cb.SubjectName = subject; cb.SubjectPublicKey = subjectKey; - + // signature cb.Hash = "SHA256"; byte[] rawcert = cb.Sign(issuerKey); @@ -66,4 +71,39 @@ namespace Emby.Server.Core.Cryptography p12.SaveToFile(fileName); } } + + public static class RSACryptoServiceProviderExtensions + { + public static void FromXmlString(RSA rsa, string xmlString) + { + RSAParameters parameters = new RSAParameters(); + + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(xmlString); + + if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")) + { + foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes) + { + switch (node.Name) + { + case "Modulus": parameters.Modulus = Convert.FromBase64String(node.InnerText); break; + case "Exponent": parameters.Exponent = Convert.FromBase64String(node.InnerText); break; + case "P": parameters.P = Convert.FromBase64String(node.InnerText); break; + case "Q": parameters.Q = Convert.FromBase64String(node.InnerText); break; + case "DP": parameters.DP = Convert.FromBase64String(node.InnerText); break; + case "DQ": parameters.DQ = Convert.FromBase64String(node.InnerText); break; + case "InverseQ": parameters.InverseQ = Convert.FromBase64String(node.InnerText); break; + case "D": parameters.D = Convert.FromBase64String(node.InnerText); break; + } + } + } + else + { + throw new Exception("Invalid XML RSA key."); + } + + rsa.ImportParameters(parameters); + } + } } diff --git a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs index 0999fa1418..f86279f372 100644 --- a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -6,16 +6,16 @@ namespace Emby.Server.Implementations.EnvironmentInfo { public class EnvironmentInfo : IEnvironmentInfo { - public Architecture? CustomArchitecture { get; set; } - public MediaBrowser.Model.System.OperatingSystem? CustomOperatingSystem { get; set; } + private Architecture? _customArchitecture; + private MediaBrowser.Model.System.OperatingSystem? _customOperatingSystem; public virtual MediaBrowser.Model.System.OperatingSystem OperatingSystem { get { - if (CustomOperatingSystem.HasValue) + if (_customOperatingSystem.HasValue) { - return CustomOperatingSystem.Value; + return _customOperatingSystem.Value; } switch (Environment.OSVersion.Platform) @@ -30,6 +30,10 @@ namespace Emby.Server.Implementations.EnvironmentInfo return MediaBrowser.Model.System.OperatingSystem.Windows; } + set + { + _customOperatingSystem = value; + } } public string OperatingSystemName @@ -60,13 +64,17 @@ namespace Emby.Server.Implementations.EnvironmentInfo { get { - if (CustomArchitecture.HasValue) + if (_customArchitecture.HasValue) { - return CustomArchitecture.Value; + return _customArchitecture.Value; } return Environment.Is64BitOperatingSystem ? MediaBrowser.Model.System.Architecture.X64 : MediaBrowser.Model.System.Architecture.X86; } + set + { + _customArchitecture = value; + } } public string GetEnvironmentVariable(string name) diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index 1017953ba7..f512b723d8 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -66,8 +66,10 @@ namespace Emby.Server.Implementations.HttpClientManager // http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c ServicePointManager.Expect100Continue = false; - // Trakt requests sometimes fail without this +#if NET46 +// Trakt requests sometimes fail without this ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls; +#endif } /// @@ -428,7 +430,7 @@ namespace Emby.Server.Implementations.HttpClientManager try { var bytes = options.RequestContentBytes ?? - Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty); + Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty); httpWebRequest.ContentType = options.RequestContentType ?? "application/x-www-form-urlencoded"; @@ -727,7 +729,7 @@ namespace Emby.Server.Implementations.HttpClientManager } var webException = ex as WebException - ?? ex.InnerException as WebException; + ?? ex.InnerException as WebException; if (webException != null) { @@ -762,7 +764,7 @@ namespace Emby.Server.Implementations.HttpClientManager } var operationCanceledException = ex as OperationCanceledException - ?? ex.InnerException as OperationCanceledException; + ?? ex.InnerException as OperationCanceledException; if (operationCanceledException != null) { diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 019b8162af..211c54ceea 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -71,9 +71,8 @@ namespace Emby.Server.Implementations.Library private readonly IServerApplicationHost _appHost; private readonly IFileSystem _fileSystem; private readonly ICryptoProvider _cryptographyProvider; - private readonly string _defaultUserName; - public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func imageProcessorFactory, Func dtoServiceFactory, Func connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptoProvider cryptographyProvider, string defaultUserName) + public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func imageProcessorFactory, Func dtoServiceFactory, Func connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ICryptoProvider cryptographyProvider) { _logger = logger; UserRepository = userRepository; @@ -86,7 +85,6 @@ namespace Emby.Server.Implementations.Library _jsonSerializer = jsonSerializer; _fileSystem = fileSystem; _cryptographyProvider = cryptographyProvider; - _defaultUserName = defaultUserName; ConfigurationManager = configurationManager; Users = new List(); @@ -381,7 +379,7 @@ namespace Emby.Server.Implementations.Library // There always has to be at least one user. if (users.Count == 0) { - var name = MakeValidUsername(_defaultUserName); + var name = MakeValidUsername(Environment.UserName); var user = InstantiateNewUser(name); diff --git a/Emby.Server.Implementations/Logging/SimpleLogManager.cs b/Emby.Server.Implementations/Logging/SimpleLogManager.cs index 1a50f162a1..5c83766fe8 100644 --- a/Emby.Server.Implementations/Logging/SimpleLogManager.cs +++ b/Emby.Server.Implementations/Logging/SimpleLogManager.cs @@ -138,10 +138,10 @@ namespace Emby.Server.Implementations.Logging foreach (var message in _queue.GetConsumingEnumerable()) { - any = true; - var bytes = Encoding.UTF8.GetBytes(message + Environment.NewLine); _fileStream.Write(bytes, 0, bytes.Length); + + any = true; } if (any) diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index ab3bd0b315..f78fbdfd72 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -69,8 +69,8 @@ namespace Emby.Server.Implementations.Net if (remotePort < 0) throw new ArgumentException("remotePort cannot be less than zero.", "remotePort"); var addressFamily = remoteAddress.AddressFamily == IpAddressFamily.InterNetwork - ? AddressFamily.InterNetwork - : AddressFamily.InterNetworkV6; + ? AddressFamily.InterNetwork + : AddressFamily.InterNetworkV6; var retVal = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); @@ -82,7 +82,7 @@ namespace Emby.Server.Implementations.Net { // This is not supported on all operating systems (qnap) } - + try { return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)); @@ -139,11 +139,11 @@ namespace Emby.Server.Implementations.Net throw; } } - + /// - /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port. - /// - /// An implementation of the interface used by RSSDP components to perform acceptSocket operations. + /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port. + /// + /// An implementation of the interface used by RSSDP components to perform acceptSocket operations. public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); @@ -186,7 +186,16 @@ namespace Emby.Server.Implementations.Net try { + // not supported on all platforms. throws on ubuntu with .net core 2.0 retVal.ExclusiveAddressUse = false; + } + catch (SocketException) + { + + } + + try + { //retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive); diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs index b4b2bb139e..675b0d78cd 100644 --- a/Emby.Server.Implementations/ServerApplicationPaths.cs +++ b/Emby.Server.Implementations/ServerApplicationPaths.cs @@ -13,8 +13,8 @@ namespace Emby.Server.Implementations /// /// Initializes a new instance of the class. /// - public ServerApplicationPaths(string programDataPath, string appFolderPath, string applicationResourcesPath, Action createDirectoryFn) - : base(programDataPath, appFolderPath, createDirectoryFn) + public ServerApplicationPaths(string programDataPath, string appFolderPath, string applicationResourcesPath) + : base(programDataPath, appFolderPath) { ApplicationResourcesPath = applicationResourcesPath; } diff --git a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs index 5f81f7269a..0319f67117 100644 --- a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Model.Session /// The position ticks. public long? PositionTicks { get; set; } - public long? playbackStartTimeTicks { get; set; } + public long? PlaybackStartTimeTicks { get; set; } /// /// Gets or sets the volume level. diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs index 1153d0f7db..e51324ec4d 100644 --- a/MediaBrowser.Server.Mono/MonoAppHost.cs +++ b/MediaBrowser.Server.Mono/MonoAppHost.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Server.Mono { public class MonoAppHost : ApplicationHost { - public MonoAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) + public MonoAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager) { } diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index c50f97fc12..73a568ca97 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -21,7 +21,6 @@ using Emby.Server.Implementations.Networking; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using Mono.Unix.Native; -using NLog; using ILogger = MediaBrowser.Model.Logging.ILogger; using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; @@ -48,7 +47,7 @@ namespace MediaBrowser.Server.Mono var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath); - var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); + var logManager = new SimpleLogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Info); logManager.AddConsoleOutput(); @@ -84,9 +83,7 @@ namespace MediaBrowser.Server.Mono var appFolderPath = Path.GetDirectoryName(applicationPath); - Action createDirectoryFn = s => Directory.CreateDirectory(s); - - return new ServerApplicationPaths(programDataPath, appFolderPath, Path.GetDirectoryName(applicationPath), createDirectoryFn); + return new ServerApplicationPaths(programDataPath, appFolderPath, Path.GetDirectoryName(applicationPath)); } private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); @@ -113,10 +110,7 @@ namespace MediaBrowser.Server.Mono environmentInfo, imageEncoder, new SystemEvents(logManager.GetLogger("SystemEvents")), - new MemoryStreamProvider(), - new NetworkManager(logManager.GetLogger("NetworkManager")), - GenerateCertificate, - () => Environment.UserName); + new NetworkManager(logManager.GetLogger("NetworkManager"))); if (options.ContainsOption("-v")) { @@ -141,11 +135,6 @@ namespace MediaBrowser.Server.Mono Task.WaitAll(task); } - private static void GenerateCertificate(string certPath, string certHost, string certPassword) - { - CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, certPassword, _logger); - } - private static MonoEnvironmentInfo GetEnvironmentInfo() { var info = new MonoEnvironmentInfo(); @@ -156,39 +145,38 @@ namespace MediaBrowser.Server.Mono if (string.Equals(sysName, "Darwin", StringComparison.OrdinalIgnoreCase)) { - //info.OperatingSystem = Startup.Common.OperatingSystem.Osx; + info.OperatingSystem = Model.System.OperatingSystem.OSX; } else if (string.Equals(sysName, "Linux", StringComparison.OrdinalIgnoreCase)) { - //info.OperatingSystem = Startup.Common.OperatingSystem.Linux; + info.OperatingSystem = Model.System.OperatingSystem.Linux; } else if (string.Equals(sysName, "BSD", StringComparison.OrdinalIgnoreCase)) { - //info.OperatingSystem = Startup.Common.OperatingSystem.Bsd; - info.IsBsd = true; + info.OperatingSystem = Model.System.OperatingSystem.BSD; } var archX86 = new Regex("(i|I)[3-6]86"); if (archX86.IsMatch(uname.machine)) { - info.CustomArchitecture = Architecture.X86; + info.SystemArchitecture = Architecture.X86; } else if (string.Equals(uname.machine, "x86_64", StringComparison.OrdinalIgnoreCase)) { - info.CustomArchitecture = Architecture.X64; + info.SystemArchitecture = Architecture.X64; } else if (uname.machine.StartsWith("arm", StringComparison.OrdinalIgnoreCase)) { - info.CustomArchitecture = Architecture.Arm; + info.SystemArchitecture = Architecture.Arm; } else if (System.Environment.Is64BitOperatingSystem) { - info.CustomArchitecture = Architecture.X64; + info.SystemArchitecture = Architecture.X64; } else { - info.CustomArchitecture = Architecture.X86; + info.SystemArchitecture = Architecture.X86; } return info; @@ -308,24 +296,9 @@ namespace MediaBrowser.Server.Mono public class MonoEnvironmentInfo : EnvironmentInfo { - public bool IsBsd { get; set; } - public override string GetUserId() { return Syscall.getuid().ToString(CultureInfo.InvariantCulture); } - - public override Model.System.OperatingSystem OperatingSystem - { - get - { - if (IsBsd) - { - return Model.System.OperatingSystem.BSD; - } - - return base.OperatingSystem; - } - } } } diff --git a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs index 77e6c65fec..0e99bbbad1 100644 --- a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs +++ b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs @@ -1,6 +1,5 @@ using System; using Emby.Drawing; -using Emby.Drawing.ImageMagick; using Emby.Drawing.Skia; using Emby.Server.Core; using Emby.Server.Implementations; diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index fba8f48118..6635cddb7b 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -236,18 +236,16 @@ namespace MediaBrowser.ServerApplication var resourcesPath = Path.GetDirectoryName(applicationPath); - Action createDirectoryFn = s => Directory.CreateDirectory(s); - if (runAsService) { var systemPath = Path.GetDirectoryName(applicationPath); var programDataPath = Path.GetDirectoryName(systemPath); - return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath, createDirectoryFn); + return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath); } - return new ServerApplicationPaths(ApplicationPathHelper.GetProgramDataPath(applicationPath), appFolderPath, resourcesPath, createDirectoryFn); + return new ServerApplicationPaths(ApplicationPathHelper.GetProgramDataPath(applicationPath), appFolderPath, resourcesPath); } /// @@ -316,10 +314,7 @@ namespace MediaBrowser.ServerApplication environmentInfo, new NullImageEncoder(), new SystemEvents(logManager.GetLogger("SystemEvents")), - new MemoryStreamProvider(), - new Networking.NetworkManager(logManager.GetLogger("NetworkManager")), - GenerateCertificate, - () => Environment.UserDomainName); + new Networking.NetworkManager(logManager.GetLogger("NetworkManager"))); var initProgress = new Progress(); @@ -366,11 +361,6 @@ namespace MediaBrowser.ServerApplication } } - private static void GenerateCertificate(string certPath, string certHost, string certPassword) - { - CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, certPassword, _logger); - } - private static ServerNotifyIcon _serverNotifyIcon; private static TaskScheduler _mainTaskScheduler; private static void ShowTrayIcon() diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index eed5bab8d3..2ee2acfc2e 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -201,10 +201,6 @@ {805844ab-e92f-45e6-9d99-4f6d48d129a5} Emby.Dlna - - {6cfee013-6e7c-432b-ac37-cabf0880c69a} - Emby.Drawing.ImageMagick - {2312da6d-ff86-4597-9777-bceec32d96dd} Emby.Drawing.Skia diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs index c872d96e2d..d72bd532e1 100644 --- a/MediaBrowser.ServerApplication/WindowsAppHost.cs +++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs @@ -25,8 +25,8 @@ namespace MediaBrowser.ServerApplication { public class WindowsAppHost : ApplicationHost { - public WindowsAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) - : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) + public WindowsAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) + : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager) { } -- cgit v1.2.3