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()
{
#if NET46

View file

@ -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
{

View file

@ -172,8 +172,8 @@
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunManager.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunDiscovery.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunHost.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunLiveStream.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\LegacyHdHomerunLiveStream.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunHttpStream.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunUdpStream.cs" />
<Compile Include="LiveTv\TunerHosts\M3uParser.cs" />
<Compile Include="LiveTv\TunerHosts\M3UTunerHost.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 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<List<ChannelInfo>> 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<ChannelInfo>().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;
}
}

View file

@ -13,7 +13,7 @@ using MediaBrowser.Model.MediaInfo;
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
public class HdHomerunLiveStream : LiveStream, IDirectStreamProvider
public class HdHomerunHttpStream : LiveStream, IDirectStreamProvider
{
private readonly ILogger _logger;
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 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)
{
_fileSystem = fileSystem;

View file

@ -17,7 +17,7 @@ using MediaBrowser.Model.Net;
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
public class LegacyHdHomerunLiveStream : LiveStream, IDirectStreamProvider
public class HdHomerunUdpStream : LiveStream, IDirectStreamProvider
{
private readonly ILogger _logger;
private readonly IHttpClient _httpClient;
@ -33,7 +33,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
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)
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;
@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var uri = new Uri(mediaSource.Path);
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>();
@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public override Task Close()
{
_logger.Info("Closing Legacy HDHR live stream");
_logger.Info("Closing HDHR UDP live stream");
_liveStreamCancellationTokenSource.Cancel();
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)
{
//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;
// }
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 legCommand.StartStreaming(remoteAddress, localAddress, localPort, _channelUrl, _numTuners, cancellationToken).ConfigureAwait(false);
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 Legacy HDHR stream from {0}", _channelUrl);
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);
// }
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;
// }
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);
// }
_logger.ErrorException("Error copying live stream, will reopen", ex);
}
// isFirstAttempt = false;
// }
isFirstAttempt = false;
}
// await legCommand.StopStreaming().ConfigureAwait(false);
// udpClient.Dispose();
// _liveStreamTaskCompletionSource.TrySetResult(true);
// }
await hdHomerunManager.StopStreaming().ConfigureAwait(false);
udpClient.Dispose();
_liveStreamTaskCompletionSource.TrySetResult(true);
}
}
//}).ConfigureAwait(false);
}).ConfigureAwait(false);
}
public Task CopyToAsync(Stream stream, CancellationToken cancellationToken)

View file

@ -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<IAcceptSocket> onAccept, Func<bool> isClosed);
}

View file

@ -30,7 +30,7 @@ namespace MediaBrowser.Model.Net
/// <returns>A <see cref="ISocket"/> implementation.</returns>
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

View file

@ -1,3 +1,3 @@
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
{
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
{