From 9776ca09db59a1e382045a072813a29cf07cadb3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Mar 2017 15:50:09 -0500 Subject: update socket interfaces --- Emby.Common.Implementations/Net/NetAcceptSocket.cs | 97 ++++++++++++++++++++++ Emby.Common.Implementations/Net/NetSocket.cs | 97 ---------------------- Emby.Common.Implementations/Net/SocketAcceptor.cs | 10 +-- Emby.Common.Implementations/Net/SocketFactory.cs | 47 +++++++---- Emby.Common.Implementations/Net/UdpSocket.cs | 16 ++-- 5 files changed, 143 insertions(+), 124 deletions(-) create mode 100644 Emby.Common.Implementations/Net/NetAcceptSocket.cs delete mode 100644 Emby.Common.Implementations/Net/NetSocket.cs (limited to 'Emby.Common.Implementations/Net') diff --git a/Emby.Common.Implementations/Net/NetAcceptSocket.cs b/Emby.Common.Implementations/Net/NetAcceptSocket.cs new file mode 100644 index 000000000..0672a9e98 --- /dev/null +++ b/Emby.Common.Implementations/Net/NetAcceptSocket.cs @@ -0,0 +1,97 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using Emby.Common.Implementations.Networking; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Logging; + +namespace Emby.Common.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 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 void Dispose() + { + Socket.Dispose(); + } + } +} diff --git a/Emby.Common.Implementations/Net/NetSocket.cs b/Emby.Common.Implementations/Net/NetSocket.cs deleted file mode 100644 index bc012dfe2..000000000 --- a/Emby.Common.Implementations/Net/NetSocket.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using Emby.Common.Implementations.Networking; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Logging; - -namespace Emby.Common.Implementations.Net -{ - public class NetSocket : ISocket - { - public Socket Socket { get; private set; } - private readonly ILogger _logger; - - public bool DualMode { get; private set; } - - public NetSocket(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 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 void Dispose() - { - Socket.Dispose(); - } - } -} diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs index d4c6d33e5..11a8e5381 100644 --- a/Emby.Common.Implementations/Net/SocketAcceptor.cs +++ b/Emby.Common.Implementations/Net/SocketAcceptor.cs @@ -10,10 +10,10 @@ namespace Emby.Common.Implementations.Net private readonly ILogger _logger; private readonly Socket _originalSocket; private readonly Func _isClosed; - private readonly Action _onAccept; + private readonly Action _onAccept; private readonly bool _isDualMode; - public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed, bool isDualMode) + public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed, bool isDualMode) { if (logger == null) { @@ -54,7 +54,7 @@ namespace Emby.Common.Implementations.Net } else { - // socket must be cleared since the context object is being reused + // acceptSocket must be cleared since the context object is being reused acceptEventArg.AcceptSocket = null; } @@ -102,7 +102,7 @@ namespace Emby.Common.Implementations.Net return; } - // http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.acceptasync%28v=vs.110%29.aspx + // 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) @@ -117,7 +117,7 @@ namespace Emby.Common.Implementations.Net if (acceptSocket != null) { //ProcessAccept(acceptSocket); - _onAccept(new NetSocket(acceptSocket, _logger, _isDualMode)); + _onAccept(new NetAcceptSocket(acceptSocket, _logger, _isDualMode)); } // Accept the next connection request diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index 70c7ba845..bb964fe00 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -31,7 +31,7 @@ namespace Emby.Common.Implementations.Net _logger = logger; } - public ISocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) + public IAcceptSocket CreateAcceptSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) { try { @@ -46,7 +46,7 @@ namespace Emby.Common.Implementations.Net socket.DualMode = true; } - return new NetSocket(socket, _logger, dualMode); + return new NetAcceptSocket(socket, _logger, dualMode); } catch (SocketException ex) { @@ -54,13 +54,30 @@ namespace Emby.Common.Implementations.Net } } - #region ISocketFactory Members + public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort) + { + if (remotePort < 0) throw new ArgumentException("remotePort cannot be less than zero.", "remotePort"); + + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); + try + { + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } /// - /// Creates a new UDP socket and binds it to the specified local port. + /// Creates a new UDP acceptSocket and binds it to the specified local port. /// - /// An integer specifying the local port to bind the socket to. - public IUdpSocket CreateUdpSocket(int localPort) + /// 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"); @@ -80,10 +97,10 @@ namespace Emby.Common.Implementations.Net } /// - /// Creates a new UDP socket that is a member of the SSDP multicast local admin group and binds it to the specified local port. + /// 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 socket operations. - public IUdpSocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) + /// 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"); @@ -108,13 +125,13 @@ namespace Emby.Common.Implementations.Net } /// - /// Creates a new UDP socket that is a member of the specified multicast IP address, and binds it to the specified local port. + /// 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 socket a member of. - /// The multicast time to live value for the socket. + /// 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 IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort) + 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"); @@ -128,7 +145,7 @@ namespace Emby.Common.Implementations.Net #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 + // The ExclusiveAddressUse acceptSocket option is a Windows-specific option that, when set to "true," tells Windows not to allow another acceptSocket to use the same local address as this acceptSocket // See https://github.com/dotnet/corefx/pull/11509 for more details if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { @@ -154,7 +171,5 @@ namespace Emby.Common.Implementations.Net throw; } } - - #endregion } } diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs index e4b0c7d6d..8e2a1da6f 100644 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ b/Emby.Common.Implementations/Net/UdpSocket.cs @@ -14,7 +14,7 @@ namespace Emby.Common.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. - internal sealed class UdpSocket : DisposableManagedObjectBase, IUdpSocket + internal sealed class UdpSocket : DisposableManagedObjectBase, ISocket { #region Fields @@ -23,8 +23,6 @@ namespace Emby.Common.Implementations.Net private int _LocalPort; #endregion - #region Constructors - public UdpSocket(Socket socket, int localPort, IPAddress ip) { if (socket == null) throw new ArgumentNullException("socket"); @@ -36,7 +34,13 @@ namespace Emby.Common.Implementations.Net _Socket.Bind(new IPEndPoint(ip, _LocalPort)); } - #endregion + public UdpSocket(Socket socket, IpEndPointInfo endPoint) + { + if (socket == null) throw new ArgumentNullException("socket"); + + _Socket = socket; + _Socket.Connect(NetworkManager.ToIPEndPoint(endPoint)); + } public IpAddressInfo LocalIPAddress { @@ -44,9 +48,9 @@ namespace Emby.Common.Implementations.Net private set; } - #region IUdpSocket Members + #region ISocket Members - public Task ReceiveAsync() + public Task ReceiveAsync(CancellationToken cancellationToken) { ThrowIfDisposed(); -- cgit v1.2.3 From 7cbc76af27637fca10bca21d0b343f96b1a02b6a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 3 Mar 2017 00:53:21 -0500 Subject: 3.2.5.4 --- Emby.Common.Implementations/Net/NetAcceptSocket.cs | 7 + Emby.Common.Implementations/Net/SocketFactory.cs | 2 +- .../Emby.Server.Implementations.csproj | 4 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 19 +- .../TunerHosts/HdHomerun/HdHomerunHttpStream.cs | 143 ++++++++++ .../TunerHosts/HdHomerun/HdHomerunLiveStream.cs | 143 ---------- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 294 +++++++++++++++++++++ .../HdHomerun/LegacyHdHomerunLiveStream.cs | 290 -------------------- MediaBrowser.Model/Net/IAcceptSocket.cs | 2 +- MediaBrowser.Model/Net/ISocketFactory.cs | 2 +- SharedVersion.cs | 2 +- .../Net/EndPointListener.cs | 4 +- 12 files changed, 463 insertions(+), 449 deletions(-) create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs delete mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs delete mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunLiveStream.cs (limited to 'Emby.Common.Implementations/Net') diff --git a/Emby.Common.Implementations/Net/NetAcceptSocket.cs b/Emby.Common.Implementations/Net/NetAcceptSocket.cs index 0672a9e98..731ad1b74 100644 --- a/Emby.Common.Implementations/Net/NetAcceptSocket.cs +++ b/Emby.Common.Implementations/Net/NetAcceptSocket.cs @@ -47,6 +47,13 @@ namespace Emby.Common.Implementations.Net } } + public void Connect(IpEndPointInfo endPoint) + { + var nativeEndpoint = NetworkManager.ToIPEndPoint(endPoint); + + Socket.Connect(nativeEndpoint); + } + public void Close() { #if NET46 diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index bb964fe00..523f4da85 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -31,7 +31,7 @@ namespace Emby.Common.Implementations.Net _logger = logger; } - public IAcceptSocket CreateAcceptSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) + public IAcceptSocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) { try { diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 32954da35..c704d0e4e 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -172,8 +172,8 @@ - - + + diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2eb02d63c..c07b6be82 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -29,14 +29,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly IFileSystem _fileSystem; private readonly IServerApplicationHost _appHost; private readonly ISocketFactory _socketFactory; + private readonly INetworkManager _networkManager; - public HdHomerunHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IHttpClient httpClient, IFileSystem fileSystem, IServerApplicationHost appHost, ISocketFactory socketFactory) + public HdHomerunHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IHttpClient httpClient, IFileSystem fileSystem, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager) : base(config, logger, jsonSerializer, mediaEncoder) { _httpClient = httpClient; _fileSystem = fileSystem; _appHost = appHost; _socketFactory = socketFactory; + _networkManager = networkManager; } public string Name @@ -89,6 +91,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private class HdHomerunChannelInfo : ChannelInfo { public bool IsLegacyTuner { get; set; } + public string Url { get; set; } } protected override async Task> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) @@ -106,7 +109,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun AudioCodec = i.AudioCodec, VideoCodec = i.VideoCodec, ChannelType = ChannelType.TV, - IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase) + IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase), + Url = i.URL }).Cast().ToList(); } @@ -500,7 +504,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var hdhrId = GetHdHrIdFromChannelId(channelId); var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false); - var channelInfo = channels.FirstOrDefault(i => string.Equals(i.Number, channelId, StringComparison.OrdinalIgnoreCase)); + var channelInfo = channels.FirstOrDefault(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase)); var hdHomerunChannelInfo = channelInfo as HdHomerunChannelInfo; @@ -570,24 +574,23 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var hdhrId = GetHdHrIdFromChannelId(channelId); var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false); - var channelInfo = channels.FirstOrDefault(i => string.Equals(i.Number, channelId, StringComparison.OrdinalIgnoreCase)); + var channelInfo = channels.FirstOrDefault(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase)); var hdhomerunChannel = channelInfo as HdHomerunChannelInfo; if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner) { + var modelInfo = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); var mediaSource = GetLegacyMediaSource(info, hdhrId, channelInfo); - var liveStream = new HdHomerunLiveStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost); - liveStream.EnableStreamSharing = true; + var liveStream = new HdHomerunUdpStream(mediaSource, streamId, hdhomerunChannel.Url, modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager); return liveStream; } else { var mediaSource = GetMediaSource(info, hdhrId, channelInfo, profile); - var liveStream = new HdHomerunLiveStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost); - liveStream.EnableStreamSharing = true; + var liveStream = new HdHomerunHttpStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost); return liveStream; } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs new file mode 100644 index 000000000..2798805fa --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs @@ -0,0 +1,143 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.MediaInfo; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class HdHomerunHttpStream : LiveStream, IDirectStreamProvider + { + private readonly ILogger _logger; + private readonly IHttpClient _httpClient; + private readonly IFileSystem _fileSystem; + private readonly IServerApplicationPaths _appPaths; + private readonly IServerApplicationHost _appHost; + + private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); + private readonly TaskCompletionSource _liveStreamTaskCompletionSource = new TaskCompletionSource(); + private readonly MulticastStream _multicastStream; + + public HdHomerunHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost) + : base(mediaSource) + { + _fileSystem = fileSystem; + _httpClient = httpClient; + _logger = logger; + _appPaths = appPaths; + _appHost = appHost; + OriginalStreamId = originalStreamId; + _multicastStream = new MulticastStream(_logger); + } + + protected override async Task OpenInternal(CancellationToken openCancellationToken) + { + _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); + + var mediaSource = OriginalMediaSource; + + var url = mediaSource.Path; + + _logger.Info("Opening HDHR Live stream from {0}", url); + + var taskCompletionSource = new TaskCompletionSource(); + + StartStreaming(url, taskCompletionSource, _liveStreamCancellationTokenSource.Token); + + //OpenedMediaSource.Protocol = MediaProtocol.File; + //OpenedMediaSource.Path = tempFile; + //OpenedMediaSource.ReadAtNativeFramerate = true; + + OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + OpenedMediaSource.Protocol = MediaProtocol.Http; + OpenedMediaSource.SupportsDirectPlay = false; + OpenedMediaSource.SupportsDirectStream = true; + OpenedMediaSource.SupportsTranscoding = true; + + await taskCompletionSource.Task.ConfigureAwait(false); + + //await Task.Delay(5000).ConfigureAwait(false); + } + + public override Task Close() + { + _logger.Info("Closing HDHR live stream"); + _liveStreamCancellationTokenSource.Cancel(); + + return _liveStreamTaskCompletionSource.Task; + } + + private async Task StartStreaming(string url, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) + { + await Task.Run(async () => + { + var isFirstAttempt = true; + + while (!cancellationToken.IsCancellationRequested) + { + try + { + using (var response = await _httpClient.SendAsync(new HttpRequestOptions + { + Url = url, + CancellationToken = cancellationToken, + BufferContent = false, + + // Increase a little bit + TimeoutMs = 30000 + + }, "GET").ConfigureAwait(false)) + { + _logger.Info("Opened HDHR stream from {0}", url); + + if (!cancellationToken.IsCancellationRequested) + { + _logger.Info("Beginning multicastStream.CopyUntilCancelled"); + + Action onStarted = null; + if (isFirstAttempt) + { + onStarted = () => openTaskCompletionSource.TrySetResult(true); + } + + await _multicastStream.CopyUntilCancelled(response.Content, onStarted, cancellationToken).ConfigureAwait(false); + } + } + } + catch (OperationCanceledException) + { + break; + } + catch (Exception ex) + { + if (isFirstAttempt) + { + _logger.ErrorException("Error opening live stream:", ex); + openTaskCompletionSource.TrySetException(ex); + break; + } + + _logger.ErrorException("Error copying live stream, will reopen", ex); + } + + isFirstAttempt = false; + } + + _liveStreamTaskCompletionSource.TrySetResult(true); + + }).ConfigureAwait(false); + } + + public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) + { + return _multicastStream.CopyToAsync(stream); + } + } +} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs deleted file mode 100644 index 625e4457d..000000000 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; - -namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun -{ - public class HdHomerunLiveStream : LiveStream, IDirectStreamProvider - { - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IServerApplicationPaths _appPaths; - private readonly IServerApplicationHost _appHost; - - private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); - private readonly TaskCompletionSource _liveStreamTaskCompletionSource = new TaskCompletionSource(); - private readonly MulticastStream _multicastStream; - - public HdHomerunLiveStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost) - : base(mediaSource) - { - _fileSystem = fileSystem; - _httpClient = httpClient; - _logger = logger; - _appPaths = appPaths; - _appHost = appHost; - OriginalStreamId = originalStreamId; - _multicastStream = new MulticastStream(_logger); - } - - protected override async Task OpenInternal(CancellationToken openCancellationToken) - { - _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); - - var mediaSource = OriginalMediaSource; - - var url = mediaSource.Path; - - _logger.Info("Opening HDHR Live stream from {0}", url); - - var taskCompletionSource = new TaskCompletionSource(); - - StartStreaming(url, taskCompletionSource, _liveStreamCancellationTokenSource.Token); - - //OpenedMediaSource.Protocol = MediaProtocol.File; - //OpenedMediaSource.Path = tempFile; - //OpenedMediaSource.ReadAtNativeFramerate = true; - - OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; - OpenedMediaSource.Protocol = MediaProtocol.Http; - OpenedMediaSource.SupportsDirectPlay = false; - OpenedMediaSource.SupportsDirectStream = true; - OpenedMediaSource.SupportsTranscoding = true; - - await taskCompletionSource.Task.ConfigureAwait(false); - - //await Task.Delay(5000).ConfigureAwait(false); - } - - public override Task Close() - { - _logger.Info("Closing HDHR live stream"); - _liveStreamCancellationTokenSource.Cancel(); - - return _liveStreamTaskCompletionSource.Task; - } - - private async Task StartStreaming(string url, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) - { - await Task.Run(async () => - { - var isFirstAttempt = true; - - while (!cancellationToken.IsCancellationRequested) - { - try - { - using (var response = await _httpClient.SendAsync(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken, - BufferContent = false, - - // Increase a little bit - TimeoutMs = 30000 - - }, "GET").ConfigureAwait(false)) - { - _logger.Info("Opened HDHR stream from {0}", url); - - if (!cancellationToken.IsCancellationRequested) - { - _logger.Info("Beginning multicastStream.CopyUntilCancelled"); - - Action onStarted = null; - if (isFirstAttempt) - { - onStarted = () => openTaskCompletionSource.TrySetResult(true); - } - - await _multicastStream.CopyUntilCancelled(response.Content, onStarted, cancellationToken).ConfigureAwait(false); - } - } - } - catch (OperationCanceledException) - { - break; - } - catch (Exception ex) - { - if (isFirstAttempt) - { - _logger.ErrorException("Error opening live stream:", ex); - openTaskCompletionSource.TrySetException(ex); - break; - } - - _logger.ErrorException("Error copying live stream, will reopen", ex); - } - - isFirstAttempt = false; - } - - _liveStreamTaskCompletionSource.TrySetResult(true); - - }).ConfigureAwait(false); - } - - public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) - { - return _multicastStream.CopyToAsync(stream); - } - } -} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs new file mode 100644 index 000000000..95ceb0660 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -0,0 +1,294 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Net; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class HdHomerunUdpStream : LiveStream, IDirectStreamProvider + { + private readonly ILogger _logger; + private readonly IHttpClient _httpClient; + private readonly IFileSystem _fileSystem; + private readonly IServerApplicationPaths _appPaths; + private readonly IServerApplicationHost _appHost; + private readonly ISocketFactory _socketFactory; + + private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); + private readonly TaskCompletionSource _liveStreamTaskCompletionSource = new TaskCompletionSource(); + private readonly MulticastStream _multicastStream; + private readonly string _channelUrl; + private readonly int _numTuners; + private readonly INetworkManager _networkManager; + + public HdHomerunUdpStream(MediaSourceInfo mediaSource, string originalStreamId, string channelUrl, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager) + : base(mediaSource) + { + _fileSystem = fileSystem; + _httpClient = httpClient; + _logger = logger; + _appPaths = appPaths; + _appHost = appHost; + _socketFactory = socketFactory; + _networkManager = networkManager; + OriginalStreamId = originalStreamId; + _multicastStream = new MulticastStream(_logger); + _channelUrl = channelUrl; + _numTuners = numTuners; + } + + protected override async Task OpenInternal(CancellationToken openCancellationToken) + { + _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); + + var mediaSource = OriginalMediaSource; + + var uri = new Uri(mediaSource.Path); + var localPort = _networkManager.GetRandomUnusedUdpPort(); + + _logger.Info("Opening HDHR UDP Live stream from {0}", uri.Host); + + var taskCompletionSource = new TaskCompletionSource(); + + StartStreaming(uri.Host, localPort, taskCompletionSource, _liveStreamCancellationTokenSource.Token); + + //OpenedMediaSource.Protocol = MediaProtocol.File; + //OpenedMediaSource.Path = tempFile; + //OpenedMediaSource.ReadAtNativeFramerate = true; + + OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + OpenedMediaSource.Protocol = MediaProtocol.Http; + OpenedMediaSource.SupportsDirectPlay = false; + OpenedMediaSource.SupportsDirectStream = true; + OpenedMediaSource.SupportsTranscoding = true; + + await taskCompletionSource.Task.ConfigureAwait(false); + + //await Task.Delay(5000).ConfigureAwait(false); + } + + public override Task Close() + { + _logger.Info("Closing HDHR UDP live stream"); + _liveStreamCancellationTokenSource.Cancel(); + + return _liveStreamTaskCompletionSource.Task; + } + + private async Task StartStreaming(string remoteIp, int localPort, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) + { + await Task.Run(async () => + { + var isFirstAttempt = true; + using (var udpClient = _socketFactory.CreateUdpSocket(localPort)) + { + using (var hdHomerunManager = new HdHomerunManager(_socketFactory)) + { + var remoteAddress = new IpAddressInfo(remoteIp, IpAddressFamily.InterNetwork); + IpAddressInfo localAddress = null; + using (var tcpSocket = _socketFactory.CreateSocket(IpAddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, false)) + { + try + { + tcpSocket.Connect(new IpEndPointInfo(remoteAddress, HdHomerunManager.HdHomeRunPort)); + localAddress = tcpSocket.LocalEndPoint.IpAddress; + tcpSocket.Close(); + } + catch (Exception) + { + _logger.Error("Unable to determine local ip address for Legacy HDHomerun stream."); + return; + } + } + + while (!cancellationToken.IsCancellationRequested) + { + try + { + // send url to start streaming + await hdHomerunManager.StartStreaming(remoteAddress, localAddress, localPort, _channelUrl, _numTuners, cancellationToken).ConfigureAwait(false); + + var response = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false); + _logger.Info("Opened HDHR UDP stream from {0}", _channelUrl); + + if (!cancellationToken.IsCancellationRequested) + { + Action onStarted = null; + if (isFirstAttempt) + { + onStarted = () => openTaskCompletionSource.TrySetResult(true); + } + + var stream = new UdpClientStream(udpClient); + await _multicastStream.CopyUntilCancelled(stream, onStarted, cancellationToken).ConfigureAwait(false); + } + } + catch (OperationCanceledException) + { + break; + } + catch (Exception ex) + { + if (isFirstAttempt) + { + _logger.ErrorException("Error opening live stream:", ex); + openTaskCompletionSource.TrySetException(ex); + break; + } + + _logger.ErrorException("Error copying live stream, will reopen", ex); + } + + isFirstAttempt = false; + } + + await hdHomerunManager.StopStreaming().ConfigureAwait(false); + udpClient.Dispose(); + _liveStreamTaskCompletionSource.TrySetResult(true); + } + } + + }).ConfigureAwait(false); + } + + public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) + { + return _multicastStream.CopyToAsync(stream); + } + } + + // This handles the ReadAsync function only of a Stream object + // This is used to wrap a UDP socket into a stream for MulticastStream which only uses ReadAsync + public class UdpClientStream : Stream + { + private static int RtpHeaderBytes = 12; + private static int PacketSize = 1316; + private readonly ISocket _udpClient; + bool disposed; + + public UdpClientStream(ISocket udpClient) : base() + { + _udpClient = udpClient; + } + + public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (buffer == null) + throw new ArgumentNullException("buffer"); + + if (offset + count < 0) + throw new ArgumentOutOfRangeException("offset + count must not be negative", "offset+count"); + + if (offset + count > buffer.Length) + throw new ArgumentException("offset + count must not be greater than the length of buffer", "offset+count"); + + if (disposed) + throw new ObjectDisposedException(typeof(UdpClientStream).ToString()); + + // This will always receive a 1328 packet size (PacketSize + RtpHeaderSize) + // The RTP header will be stripped so see how many reads we need to make to fill the buffer. + int numReads = count / PacketSize; + int totalBytesRead = 0; + + for (int i = 0; i < numReads; ++i) + { + var data = await _udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false); + + var bytesRead = data.ReceivedBytes - RtpHeaderBytes; + + // remove rtp header + Buffer.BlockCopy(data.Buffer, RtpHeaderBytes, buffer, offset, bytesRead); + offset += bytesRead; + totalBytesRead += bytesRead; + } + return totalBytesRead; + } + + protected override void Dispose(bool disposing) + { + disposed = true; + } + + public override bool CanRead + { + get + { + throw new NotImplementedException(); + } + } + + public override bool CanSeek + { + get + { + throw new NotImplementedException(); + } + } + + public override bool CanWrite + { + get + { + throw new NotImplementedException(); + } + } + + public override long Length + { + get + { + throw new NotImplementedException(); + } + } + + public override long Position + { + get + { + throw new NotImplementedException(); + } + + set + { + throw new NotImplementedException(); + } + } + + public override void Flush() + { + throw new NotImplementedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotImplementedException(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotImplementedException(); + } + + public override void SetLength(long value) + { + throw new NotImplementedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotImplementedException(); + } + } +} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunLiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunLiveStream.cs deleted file mode 100644 index 7bb524c49..000000000 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunLiveStream.cs +++ /dev/null @@ -1,290 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Net; - -namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun -{ - public class LegacyHdHomerunLiveStream : LiveStream, IDirectStreamProvider - { - private readonly ILogger _logger; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IServerApplicationPaths _appPaths; - private readonly IServerApplicationHost _appHost; - private readonly ISocketFactory _socketFactory; - - private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource(); - private readonly TaskCompletionSource _liveStreamTaskCompletionSource = new TaskCompletionSource(); - private readonly MulticastStream _multicastStream; - private readonly string _channelUrl; - private readonly int _numTuners; - private readonly INetworkManager _networkManager; - - public LegacyHdHomerunLiveStream(MediaSourceInfo mediaSource, string originalStreamId, string channelUrl, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager) - : base(mediaSource) - { - _fileSystem = fileSystem; - _httpClient = httpClient; - _logger = logger; - _appPaths = appPaths; - _appHost = appHost; - _socketFactory = socketFactory; - _networkManager = networkManager; - OriginalStreamId = originalStreamId; - _multicastStream = new MulticastStream(_logger); - _channelUrl = channelUrl; - _numTuners = numTuners; - } - - protected override async Task OpenInternal(CancellationToken openCancellationToken) - { - _liveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); - - var mediaSource = OriginalMediaSource; - - var uri = new Uri(mediaSource.Path); - var localPort = _networkManager.GetRandomUnusedUdpPort(); - - _logger.Info("Opening Legacy HDHR Live stream from {0}", uri.Host); - - var taskCompletionSource = new TaskCompletionSource(); - - StartStreaming(uri.Host, localPort, taskCompletionSource, _liveStreamCancellationTokenSource.Token); - - //OpenedMediaSource.Protocol = MediaProtocol.File; - //OpenedMediaSource.Path = tempFile; - //OpenedMediaSource.ReadAtNativeFramerate = true; - - OpenedMediaSource.Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; - OpenedMediaSource.Protocol = MediaProtocol.Http; - OpenedMediaSource.SupportsDirectPlay = false; - OpenedMediaSource.SupportsDirectStream = true; - OpenedMediaSource.SupportsTranscoding = true; - - await taskCompletionSource.Task.ConfigureAwait(false); - - //await Task.Delay(5000).ConfigureAwait(false); - } - - public override Task Close() - { - _logger.Info("Closing Legacy HDHR live stream"); - _liveStreamCancellationTokenSource.Cancel(); - - return _liveStreamTaskCompletionSource.Task; - } - - private async Task StartStreaming(string remoteIp, int localPort, TaskCompletionSource openTaskCompletionSource, CancellationToken cancellationToken) - { - //await Task.Run(async () => - //{ - // var isFirstAttempt = true; - // var udpClient = _socketFactory.CreateUdpSocket(localPort); - // using (var legCommand = new HdHomerunManager(_socketFactory)) - // { - // var remoteAddress = new IpAddressInfo(remoteIp, IpAddressFamily.InterNetwork); - // IpAddressInfo localAddress = null; - // var tcpSocket = _socketFactory.CreateSocket(IpAddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, false); - // try - // { - // tcpSocket.Connect(new IpEndPointInfo(remoteAddress, LegacyHdHomerunCommand.HdHomeRunPort)); - // localAddress = tcpSocket.LocalEndPoint.IpAddress; - // tcpSocket.Close(); - // } - // catch (Exception) - // { - // _logger.Error("Unable to determine local ip address for Legacy HDHomerun stream."); - // return; - // } - - // while (!cancellationToken.IsCancellationRequested) - // { - // try - // { - // // send url to start streaming - // await legCommand.StartStreaming(remoteAddress, localAddress, localPort, _channelUrl, _numTuners, cancellationToken).ConfigureAwait(false); - - // var response = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false); - // _logger.Info("Opened Legacy HDHR stream from {0}", _channelUrl); - - // if (!cancellationToken.IsCancellationRequested) - // { - // Action onStarted = null; - // if (isFirstAttempt) - // { - // onStarted = () => openTaskCompletionSource.TrySetResult(true); - // } - - // var stream = new UdpClientStream(udpClient); - // await _multicastStream.CopyUntilCancelled(stream, onStarted, cancellationToken).ConfigureAwait(false); - // } - // } - // catch (OperationCanceledException) - // { - // break; - // } - // catch (Exception ex) - // { - // if (isFirstAttempt) - // { - // _logger.ErrorException("Error opening live stream:", ex); - // openTaskCompletionSource.TrySetException(ex); - // break; - // } - - // _logger.ErrorException("Error copying live stream, will reopen", ex); - // } - - // isFirstAttempt = false; - // } - - // await legCommand.StopStreaming().ConfigureAwait(false); - // udpClient.Dispose(); - // _liveStreamTaskCompletionSource.TrySetResult(true); - // } - - //}).ConfigureAwait(false); - } - - public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) - { - return _multicastStream.CopyToAsync(stream); - } - } - - // This handles the ReadAsync function only of a Stream object - // This is used to wrap a UDP socket into a stream for MulticastStream which only uses ReadAsync - public class UdpClientStream : Stream - { - private static int RtpHeaderBytes = 12; - private static int PacketSize = 1316; - private readonly ISocket _udpClient; - bool disposed; - - public UdpClientStream(ISocket udpClient) : base() - { - _udpClient = udpClient; - } - - public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (buffer == null) - throw new ArgumentNullException("buffer"); - - if (offset + count < 0) - throw new ArgumentOutOfRangeException("offset + count must not be negative", "offset+count"); - - if (offset + count > buffer.Length) - throw new ArgumentException("offset + count must not be greater than the length of buffer", "offset+count"); - - if (disposed) - throw new ObjectDisposedException(typeof(UdpClientStream).ToString()); - - // This will always receive a 1328 packet size (PacketSize + RtpHeaderSize) - // The RTP header will be stripped so see how many reads we need to make to fill the buffer. - int numReads = count / PacketSize; - int totalBytesRead = 0; - - for (int i = 0; i < numReads; ++i) - { - var data = await _udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false); - - var bytesRead = data.ReceivedBytes - RtpHeaderBytes; - - // remove rtp header - Buffer.BlockCopy(data.Buffer, RtpHeaderBytes, buffer, offset, bytesRead); - offset += bytesRead; - totalBytesRead += bytesRead; - } - return totalBytesRead; - } - - protected override void Dispose(bool disposing) - { - disposed = true; - } - - public override bool CanRead - { - get - { - throw new NotImplementedException(); - } - } - - public override bool CanSeek - { - get - { - throw new NotImplementedException(); - } - } - - public override bool CanWrite - { - get - { - throw new NotImplementedException(); - } - } - - public override long Length - { - get - { - throw new NotImplementedException(); - } - } - - public override long Position - { - get - { - throw new NotImplementedException(); - } - - set - { - throw new NotImplementedException(); - } - } - - public override void Flush() - { - throw new NotImplementedException(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotImplementedException(); - } - - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - } -} diff --git a/MediaBrowser.Model/Net/IAcceptSocket.cs b/MediaBrowser.Model/Net/IAcceptSocket.cs index 0467129c0..cac23b337 100644 --- a/MediaBrowser.Model/Net/IAcceptSocket.cs +++ b/MediaBrowser.Model/Net/IAcceptSocket.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Model.Net void Shutdown(bool both); void Listen(int backlog); void Bind(IpEndPointInfo endpoint); - + void Connect(IpEndPointInfo endPoint); void StartAccept(Action onAccept, Func isClosed); } diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs index e4ef9f6d4..4b70f3362 100644 --- a/MediaBrowser.Model/Net/ISocketFactory.cs +++ b/MediaBrowser.Model/Net/ISocketFactory.cs @@ -30,7 +30,7 @@ namespace MediaBrowser.Model.Net /// A implementation. ISocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort); - IAcceptSocket CreateAcceptSocket(IpAddressFamily family, SocketType socketType, ProtocolType protocolType, bool dualMode); + IAcceptSocket CreateSocket(IpAddressFamily family, SocketType socketType, ProtocolType protocolType, bool dualMode); } public enum SocketType diff --git a/SharedVersion.cs b/SharedVersion.cs index e66950cb5..a3b0bf79a 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.5.3")] +[assembly: AssemblyVersion("3.2.5.4")] diff --git a/SocketHttpListener.Portable/Net/EndPointListener.cs b/SocketHttpListener.Portable/Net/EndPointListener.cs index 77ed65aff..c7642d5d1 100644 --- a/SocketHttpListener.Portable/Net/EndPointListener.cs +++ b/SocketHttpListener.Portable/Net/EndPointListener.cs @@ -67,7 +67,7 @@ namespace SocketHttpListener.Net { try { - sock = _socketFactory.CreateAcceptSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); + sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); } catch (SocketCreateException ex) { @@ -78,7 +78,7 @@ namespace SocketHttpListener.Net { endpoint = new IpEndPointInfo(IpAddressInfo.Any, endpoint.Port); _enableDualMode = false; - sock = _socketFactory.CreateAcceptSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); + sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); } else { -- cgit v1.2.3