This commit is contained in:
Luke Pulverenti 2017-03-03 00:53:21 -05:00
parent b9c12ca4a7
commit 7cbc76af27
10 changed files with 96 additions and 82 deletions

View file

@ -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() public void Close()
{ {
#if NET46 #if NET46

View file

@ -31,7 +31,7 @@ namespace Emby.Common.Implementations.Net
_logger = logger; _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 try
{ {

View file

@ -172,8 +172,8 @@
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunManager.cs" /> <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunManager.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunDiscovery.cs" /> <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunDiscovery.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunHost.cs" /> <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunHost.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunLiveStream.cs" /> <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunHttpStream.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\LegacyHdHomerunLiveStream.cs" /> <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunUdpStream.cs" />
<Compile Include="LiveTv\TunerHosts\M3uParser.cs" /> <Compile Include="LiveTv\TunerHosts\M3uParser.cs" />
<Compile Include="LiveTv\TunerHosts\M3UTunerHost.cs" /> <Compile Include="LiveTv\TunerHosts\M3UTunerHost.cs" />
<Compile Include="LiveTv\TunerHosts\MulticastStream.cs" /> <Compile Include="LiveTv\TunerHosts\MulticastStream.cs" />

View file

@ -29,14 +29,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly ISocketFactory _socketFactory; 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) : base(config, logger, jsonSerializer, mediaEncoder)
{ {
_httpClient = httpClient; _httpClient = httpClient;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_appHost = appHost; _appHost = appHost;
_socketFactory = socketFactory; _socketFactory = socketFactory;
_networkManager = networkManager;
} }
public string Name public string Name
@ -89,6 +91,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private class HdHomerunChannelInfo : ChannelInfo private class HdHomerunChannelInfo : ChannelInfo
{ {
public bool IsLegacyTuner { get; set; } public bool IsLegacyTuner { get; set; }
public string Url { get; set; }
} }
protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) protected override async Task<List<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken)
@ -106,7 +109,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
AudioCodec = i.AudioCodec, AudioCodec = i.AudioCodec,
VideoCodec = i.VideoCodec, VideoCodec = i.VideoCodec,
ChannelType = ChannelType.TV, 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<ChannelInfo>().ToList(); }).Cast<ChannelInfo>().ToList();
} }
@ -500,7 +504,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var hdhrId = GetHdHrIdFromChannelId(channelId); var hdhrId = GetHdHrIdFromChannelId(channelId);
var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false); 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; var hdHomerunChannelInfo = channelInfo as HdHomerunChannelInfo;
@ -570,24 +574,23 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var hdhrId = GetHdHrIdFromChannelId(channelId); var hdhrId = GetHdHrIdFromChannelId(channelId);
var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false); 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; var hdhomerunChannel = channelInfo as HdHomerunChannelInfo;
if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner) if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner)
{ {
var modelInfo = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
var mediaSource = GetLegacyMediaSource(info, hdhrId, channelInfo); var mediaSource = GetLegacyMediaSource(info, hdhrId, channelInfo);
var liveStream = new HdHomerunLiveStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost); var liveStream = new HdHomerunUdpStream(mediaSource, streamId, hdhomerunChannel.Url, modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager);
liveStream.EnableStreamSharing = true;
return liveStream; return liveStream;
} }
else else
{ {
var mediaSource = GetMediaSource(info, hdhrId, channelInfo, profile); var mediaSource = GetMediaSource(info, hdhrId, channelInfo, profile);
var liveStream = new HdHomerunLiveStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost); var liveStream = new HdHomerunHttpStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost);
liveStream.EnableStreamSharing = true;
return liveStream; return liveStream;
} }
} }

View file

@ -13,7 +13,7 @@ using MediaBrowser.Model.MediaInfo;
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{ {
public class HdHomerunLiveStream : LiveStream, IDirectStreamProvider public class HdHomerunHttpStream : LiveStream, IDirectStreamProvider
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>(); private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
private readonly MulticastStream _multicastStream; private readonly MulticastStream _multicastStream;
public HdHomerunLiveStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost) public HdHomerunHttpStream(MediaSourceInfo mediaSource, string originalStreamId, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost)
: base(mediaSource) : base(mediaSource)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;

View file

@ -17,7 +17,7 @@ using MediaBrowser.Model.Net;
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{ {
public class LegacyHdHomerunLiveStream : LiveStream, IDirectStreamProvider public class HdHomerunUdpStream : LiveStream, IDirectStreamProvider
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly int _numTuners; private readonly int _numTuners;
private readonly INetworkManager _networkManager; 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) 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) : base(mediaSource)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var uri = new Uri(mediaSource.Path); var uri = new Uri(mediaSource.Path);
var localPort = _networkManager.GetRandomUnusedUdpPort(); var localPort = _networkManager.GetRandomUnusedUdpPort();
_logger.Info("Opening Legacy HDHR Live stream from {0}", uri.Host); _logger.Info("Opening HDHR UDP Live stream from {0}", uri.Host);
var taskCompletionSource = new TaskCompletionSource<bool>(); var taskCompletionSource = new TaskCompletionSource<bool>();
@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public override Task Close() public override Task Close()
{ {
_logger.Info("Closing Legacy HDHR live stream"); _logger.Info("Closing HDHR UDP live stream");
_liveStreamCancellationTokenSource.Cancel(); _liveStreamCancellationTokenSource.Cancel();
return _liveStreamTaskCompletionSource.Task; return _liveStreamTaskCompletionSource.Task;
@ -89,74 +89,78 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private async Task StartStreaming(string remoteIp, int localPort, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken) private async Task StartStreaming(string remoteIp, int localPort, TaskCompletionSource<bool> openTaskCompletionSource, CancellationToken cancellationToken)
{ {
//await Task.Run(async () => await Task.Run(async () =>
//{ {
// var isFirstAttempt = true; var isFirstAttempt = true;
// var udpClient = _socketFactory.CreateUdpSocket(localPort); using (var udpClient = _socketFactory.CreateUdpSocket(localPort))
// using (var legCommand = new HdHomerunManager(_socketFactory)) {
// { using (var hdHomerunManager = new HdHomerunManager(_socketFactory))
// var remoteAddress = new IpAddressInfo(remoteIp, IpAddressFamily.InterNetwork); {
// IpAddressInfo localAddress = null; var remoteAddress = new IpAddressInfo(remoteIp, IpAddressFamily.InterNetwork);
// var tcpSocket = _socketFactory.CreateSocket(IpAddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, false); IpAddressInfo localAddress = null;
// try using (var tcpSocket = _socketFactory.CreateSocket(IpAddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp, false))
// { {
// tcpSocket.Connect(new IpEndPointInfo(remoteAddress, LegacyHdHomerunCommand.HdHomeRunPort)); try
// localAddress = tcpSocket.LocalEndPoint.IpAddress; {
// tcpSocket.Close(); tcpSocket.Connect(new IpEndPointInfo(remoteAddress, HdHomerunManager.HdHomeRunPort));
// } localAddress = tcpSocket.LocalEndPoint.IpAddress;
// catch (Exception) tcpSocket.Close();
// { }
// _logger.Error("Unable to determine local ip address for Legacy HDHomerun stream."); catch (Exception)
// return; {
// } _logger.Error("Unable to determine local ip address for Legacy HDHomerun stream.");
return;
}
}
// while (!cancellationToken.IsCancellationRequested) while (!cancellationToken.IsCancellationRequested)
// { {
// try try
// { {
// // send url to start streaming // send url to start streaming
// await legCommand.StartStreaming(remoteAddress, localAddress, localPort, _channelUrl, _numTuners, cancellationToken).ConfigureAwait(false); await hdHomerunManager.StartStreaming(remoteAddress, localAddress, localPort, _channelUrl, _numTuners, cancellationToken).ConfigureAwait(false);
// var response = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false); var response = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false);
// _logger.Info("Opened Legacy HDHR stream from {0}", _channelUrl); _logger.Info("Opened HDHR UDP stream from {0}", _channelUrl);
// if (!cancellationToken.IsCancellationRequested) if (!cancellationToken.IsCancellationRequested)
// { {
// Action onStarted = null; Action onStarted = null;
// if (isFirstAttempt) if (isFirstAttempt)
// { {
// onStarted = () => openTaskCompletionSource.TrySetResult(true); onStarted = () => openTaskCompletionSource.TrySetResult(true);
// } }
// var stream = new UdpClientStream(udpClient); var stream = new UdpClientStream(udpClient);
// await _multicastStream.CopyUntilCancelled(stream, onStarted, cancellationToken).ConfigureAwait(false); await _multicastStream.CopyUntilCancelled(stream, onStarted, cancellationToken).ConfigureAwait(false);
// } }
// } }
// catch (OperationCanceledException) catch (OperationCanceledException)
// { {
// break; break;
// } }
// catch (Exception ex) catch (Exception ex)
// { {
// if (isFirstAttempt) if (isFirstAttempt)
// { {
// _logger.ErrorException("Error opening live stream:", ex); _logger.ErrorException("Error opening live stream:", ex);
// openTaskCompletionSource.TrySetException(ex); openTaskCompletionSource.TrySetException(ex);
// break; break;
// } }
// _logger.ErrorException("Error copying live stream, will reopen", ex); _logger.ErrorException("Error copying live stream, will reopen", ex);
// } }
// isFirstAttempt = false; isFirstAttempt = false;
// } }
// await legCommand.StopStreaming().ConfigureAwait(false); await hdHomerunManager.StopStreaming().ConfigureAwait(false);
// udpClient.Dispose(); udpClient.Dispose();
// _liveStreamTaskCompletionSource.TrySetResult(true); _liveStreamTaskCompletionSource.TrySetResult(true);
// } }
}
//}).ConfigureAwait(false); }).ConfigureAwait(false);
} }
public Task CopyToAsync(Stream stream, CancellationToken cancellationToken) public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)

View file

@ -11,7 +11,7 @@ namespace MediaBrowser.Model.Net
void Shutdown(bool both); void Shutdown(bool both);
void Listen(int backlog); void Listen(int backlog);
void Bind(IpEndPointInfo endpoint); void Bind(IpEndPointInfo endpoint);
void Connect(IpEndPointInfo endPoint);
void StartAccept(Action<IAcceptSocket> onAccept, Func<bool> isClosed); void StartAccept(Action<IAcceptSocket> onAccept, Func<bool> isClosed);
} }

View file

@ -30,7 +30,7 @@ namespace MediaBrowser.Model.Net
/// <returns>A <see cref="ISocket"/> implementation.</returns> /// <returns>A <see cref="ISocket"/> implementation.</returns>
ISocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort); 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 public enum SocketType

View file

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.5.3")] [assembly: AssemblyVersion("3.2.5.4")]

View file

@ -67,7 +67,7 @@ namespace SocketHttpListener.Net
{ {
try 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) catch (SocketCreateException ex)
{ {
@ -78,7 +78,7 @@ namespace SocketHttpListener.Net
{ {
endpoint = new IpEndPointInfo(IpAddressInfo.Any, endpoint.Port); endpoint = new IpEndPointInfo(IpAddressInfo.Any, endpoint.Port);
_enableDualMode = false; _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 else
{ {