mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-21 21:20:39 +02:00
Merge pull request #1524 from Bond-009/ipaddress
Remove IpAddressInfo and IpEndPointInfo classes
This commit is contained in:
commit
85b277b872
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Emby.Dlna.PlayTo;
|
using Emby.Dlna.PlayTo;
|
||||||
|
@ -247,7 +248,7 @@ namespace Emby.Dlna.Main
|
||||||
|
|
||||||
foreach (var address in addresses)
|
foreach (var address in addresses)
|
||||||
{
|
{
|
||||||
if (address.AddressFamily == IpAddressFamily.InterNetworkV6)
|
if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
// Not support IPv6 right now
|
// Not support IPv6 right now
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
|
@ -14,7 +15,6 @@ using MediaBrowser.Controller.Session;
|
||||||
using MediaBrowser.Model.Dlna;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
_sessionManager.UpdateDeviceName(sessionInfo.Id, deviceName);
|
_sessionManager.UpdateDeviceName(sessionInfo.Id, deviceName);
|
||||||
|
|
||||||
string serverAddress;
|
string serverAddress;
|
||||||
if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Any))
|
if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IPAddress.Any) || info.LocalIpAddress.Equals(IPAddress.IPv6Any))
|
||||||
{
|
{
|
||||||
serverAddress = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
|
serverAddress = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Net.Sockets;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
@ -1546,14 +1547,32 @@ namespace Emby.Server.Implementations
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLocalApiUrl(IpAddressInfo ipAddress)
|
/// <summary>
|
||||||
|
/// Removes the scope id from IPv6 addresses.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">The IPv6 address.</param>
|
||||||
|
/// <returns>The IPv6 address without the scope id.</returns>
|
||||||
|
private string RemoveScopeId(string address)
|
||||||
{
|
{
|
||||||
if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
|
var index = address.IndexOf('%');
|
||||||
|
if (index == -1)
|
||||||
{
|
{
|
||||||
return GetLocalApiUrl("[" + ipAddress.Address + "]");
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetLocalApiUrl(ipAddress.Address);
|
return address.Substring(0, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetLocalApiUrl(IPAddress ipAddress)
|
||||||
|
{
|
||||||
|
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
var str = RemoveScopeId(ipAddress.ToString());
|
||||||
|
|
||||||
|
return GetLocalApiUrl("[" + str + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetLocalApiUrl(ipAddress.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLocalApiUrl(string host)
|
public string GetLocalApiUrl(string host)
|
||||||
|
@ -1564,19 +1583,22 @@ namespace Emby.Server.Implementations
|
||||||
host,
|
host,
|
||||||
HttpsPort.ToString(CultureInfo.InvariantCulture));
|
HttpsPort.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Format("http://{0}:{1}",
|
return string.Format("http://{0}:{1}",
|
||||||
host,
|
host,
|
||||||
HttpPort.ToString(CultureInfo.InvariantCulture));
|
HttpPort.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetWanApiUrl(IpAddressInfo ipAddress)
|
public string GetWanApiUrl(IPAddress ipAddress)
|
||||||
{
|
{
|
||||||
if (ipAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
|
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
return GetWanApiUrl("[" + ipAddress.Address + "]");
|
var str = RemoveScopeId(ipAddress.ToString());
|
||||||
|
|
||||||
|
return GetWanApiUrl("[" + str + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetWanApiUrl(ipAddress.Address);
|
return GetWanApiUrl(ipAddress.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetWanApiUrl(string host)
|
public string GetWanApiUrl(string host)
|
||||||
|
@ -1587,17 +1609,18 @@ namespace Emby.Server.Implementations
|
||||||
host,
|
host,
|
||||||
ServerConfigurationManager.Configuration.PublicHttpsPort.ToString(CultureInfo.InvariantCulture));
|
ServerConfigurationManager.Configuration.PublicHttpsPort.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
return string.Format("http://{0}:{1}",
|
return string.Format("http://{0}:{1}",
|
||||||
host,
|
host,
|
||||||
ServerConfigurationManager.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture));
|
ServerConfigurationManager.Configuration.PublicPort.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken)
|
public Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return GetLocalIpAddressesInternal(true, 0, cancellationToken);
|
return GetLocalIpAddressesInternal(true, 0, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<IpAddressInfo>> GetLocalIpAddressesInternal(bool allowLoopback, int limit, CancellationToken cancellationToken)
|
private async Task<List<IPAddress>> GetLocalIpAddressesInternal(bool allowLoopback, int limit, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var addresses = ServerConfigurationManager
|
var addresses = ServerConfigurationManager
|
||||||
.Configuration
|
.Configuration
|
||||||
|
@ -1611,13 +1634,13 @@ namespace Emby.Server.Implementations
|
||||||
addresses.AddRange(NetworkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces));
|
addresses.AddRange(NetworkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces));
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultList = new List<IpAddressInfo>();
|
var resultList = new List<IPAddress>();
|
||||||
|
|
||||||
foreach (var address in addresses)
|
foreach (var address in addresses)
|
||||||
{
|
{
|
||||||
if (!allowLoopback)
|
if (!allowLoopback)
|
||||||
{
|
{
|
||||||
if (address.Equals(IpAddressInfo.Loopback) || address.Equals(IpAddressInfo.IPv6Loopback))
|
if (address.Equals(IPAddress.Loopback) || address.Equals(IPAddress.IPv6Loopback))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1638,7 +1661,7 @@ namespace Emby.Server.Implementations
|
||||||
return resultList;
|
return resultList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IpAddressInfo NormalizeConfiguredLocalAddress(string address)
|
private IPAddress NormalizeConfiguredLocalAddress(string address)
|
||||||
{
|
{
|
||||||
var index = address.Trim('/').IndexOf('/');
|
var index = address.Trim('/').IndexOf('/');
|
||||||
|
|
||||||
|
@ -1647,7 +1670,7 @@ namespace Emby.Server.Implementations
|
||||||
address = address.Substring(index + 1);
|
address = address.Substring(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetworkManager.TryParseIpAddress(address.Trim('/'), out IpAddressInfo result))
|
if (IPAddress.TryParse(address.Trim('/'), out IPAddress result))
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1657,10 +1680,10 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken)
|
private async Task<bool> IsIpAddressValidAsync(IPAddress address, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (address.Equals(IpAddressInfo.Loopback) ||
|
if (address.Equals(IPAddress.Loopback) ||
|
||||||
address.Equals(IpAddressInfo.IPv6Loopback))
|
address.Equals(IPAddress.IPv6Loopback))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
@ -11,7 +12,6 @@ using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.LiveTv;
|
using MediaBrowser.Controller.LiveTv;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Dto;
|
using MediaBrowser.Model.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
@ -20,7 +20,6 @@ using MediaBrowser.Model.LiveTv;
|
||||||
using MediaBrowser.Model.MediaInfo;
|
using MediaBrowser.Model.MediaInfo;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.System;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
|
@ -259,7 +258,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
using (var manager = new HdHomerunManager(_socketFactory, Logger))
|
using (var manager = new HdHomerunManager(_socketFactory, Logger))
|
||||||
{
|
{
|
||||||
// Legacy HdHomeruns are IPv4 only
|
// Legacy HdHomeruns are IPv4 only
|
||||||
var ipInfo = _networkManager.ParseIpAddress(uri.Host);
|
var ipInfo = IPAddress.Parse(uri.Host);
|
||||||
|
|
||||||
for (int i = 0; i < model.TunerCount; ++i)
|
for (int i = 0; i < model.TunerCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -675,13 +674,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
// Need a way to set the Receive timeout on the socket otherwise this might never timeout?
|
// Need a way to set the Receive timeout on the socket otherwise this might never timeout?
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IpEndPointInfo(new IpAddressInfo("255.255.255.255", IpAddressFamily.InterNetwork), 65001), cancellationToken);
|
await udpClient.SendToAsync(discBytes, 0, discBytes.Length, new IPEndPoint(IPAddress.Parse("255.255.255.255"), 65001), cancellationToken);
|
||||||
var receiveBuffer = new byte[8192];
|
var receiveBuffer = new byte[8192];
|
||||||
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
var response = await udpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false);
|
var response = await udpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false);
|
||||||
var deviceIp = response.RemoteEndPoint.IpAddress.Address;
|
var deviceIp = response.RemoteEndPoint.Address.ToString();
|
||||||
|
|
||||||
// check to make sure we have enough bytes received to be a valid message and make sure the 2nd byte is the discover reply byte
|
// check to make sure we have enough bytes received to be a valid message and make sure the 2nd byte is the discover reply byte
|
||||||
if (response.ReceivedBytes > 13 && response.Buffer[1] == 3)
|
if (response.ReceivedBytes > 13 && response.Buffer[1] == 3)
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
private uint? _lockkey = null;
|
private uint? _lockkey = null;
|
||||||
private int _activeTuner = -1;
|
private int _activeTuner = -1;
|
||||||
private readonly ISocketFactory _socketFactory;
|
private readonly ISocketFactory _socketFactory;
|
||||||
private IpAddressInfo _remoteIp;
|
private IPAddress _remoteIp;
|
||||||
|
|
||||||
private ILogger _logger;
|
private ILogger _logger;
|
||||||
private ISocket _currentTcpSocket;
|
private ISocket _currentTcpSocket;
|
||||||
|
@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> CheckTunerAvailability(IpAddressInfo remoteIp, int tuner, CancellationToken cancellationToken)
|
public async Task<bool> CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using (var socket = _socketFactory.CreateTcpSocket(remoteIp, HdHomeRunPort))
|
using (var socket = _socketFactory.CreateTcpSocket(remoteIp, HdHomeRunPort))
|
||||||
{
|
{
|
||||||
|
@ -122,9 +122,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<bool> CheckTunerAvailability(ISocket socket, IpAddressInfo remoteIp, int tuner, CancellationToken cancellationToken)
|
private static async Task<bool> CheckTunerAvailability(ISocket socket, IPAddress remoteIp, int tuner, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var ipEndPoint = new IpEndPointInfo(remoteIp, HdHomeRunPort);
|
var ipEndPoint = new IPEndPoint(remoteIp, HdHomeRunPort);
|
||||||
|
|
||||||
var lockkeyMsg = CreateGetMessage(tuner, "lockkey");
|
var lockkeyMsg = CreateGetMessage(tuner, "lockkey");
|
||||||
await socket.SendToAsync(lockkeyMsg, 0, lockkeyMsg.Length, ipEndPoint, cancellationToken);
|
await socket.SendToAsync(lockkeyMsg, 0, lockkeyMsg.Length, ipEndPoint, cancellationToken);
|
||||||
|
@ -137,7 +137,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase);
|
return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartStreaming(IpAddressInfo remoteIp, IPAddress localIp, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken)
|
public async Task StartStreaming(IPAddress remoteIp, IPAddress localIp, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_remoteIp = remoteIp;
|
_remoteIp = remoteIp;
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
|
|
||||||
var lockKeyValue = _lockkey.Value;
|
var lockKeyValue = _lockkey.Value;
|
||||||
|
|
||||||
var ipEndPoint = new IpEndPointInfo(_remoteIp, HdHomeRunPort);
|
var ipEndPoint = new IPEndPoint(_remoteIp, HdHomeRunPort);
|
||||||
|
|
||||||
for (int i = 0; i < numTuners; ++i)
|
for (int i = 0; i < numTuners; ++i)
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
foreach (Tuple<string, string> command in commandList)
|
foreach (Tuple<string, string> command in commandList)
|
||||||
{
|
{
|
||||||
var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey);
|
var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey);
|
||||||
await tcpClient.SendToAsync(channelMsg, 0, channelMsg.Length, new IpEndPointInfo(_remoteIp, HdHomeRunPort), cancellationToken).ConfigureAwait(false);
|
await tcpClient.SendToAsync(channelMsg, 0, channelMsg.Length, new IPEndPoint(_remoteIp, HdHomeRunPort), cancellationToken).ConfigureAwait(false);
|
||||||
var response = await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false);
|
var response = await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false);
|
||||||
// parse response to make sure it worked
|
// parse response to make sure it worked
|
||||||
if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out string returnVal))
|
if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out string returnVal))
|
||||||
|
@ -242,7 +242,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
{
|
{
|
||||||
_logger.LogInformation("HdHomerunManager.ReleaseLockkey {0}", lockKeyValue);
|
_logger.LogInformation("HdHomerunManager.ReleaseLockkey {0}", lockKeyValue);
|
||||||
|
|
||||||
var ipEndPoint = new IpEndPointInfo(_remoteIp, HdHomeRunPort);
|
var ipEndPoint = new IPEndPoint(_remoteIp, HdHomeRunPort);
|
||||||
|
|
||||||
var releaseTarget = CreateSetMessage(_activeTuner, "target", "none", lockKeyValue);
|
var releaseTarget = CreateSetMessage(_activeTuner, "target", "none", lockKeyValue);
|
||||||
await tcpClient.SendToAsync(releaseTarget, 0, releaseTarget.Length, ipEndPoint, CancellationToken.None).ConfigureAwait(false);
|
await tcpClient.SendToAsync(releaseTarget, 0, releaseTarget.Length, ipEndPoint, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
|
@ -25,7 +25,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
private readonly int _numTuners;
|
private readonly int _numTuners;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
|
|
||||||
public HdHomerunUdpStream(MediaSourceInfo mediaSource, TunerHostInfo tunerHostInfo, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, MediaBrowser.Model.Net.ISocketFactory socketFactory, INetworkManager networkManager)
|
public HdHomerunUdpStream(
|
||||||
|
MediaSourceInfo mediaSource,
|
||||||
|
TunerHostInfo tunerHostInfo,
|
||||||
|
string originalStreamId,
|
||||||
|
IHdHomerunChannelCommands channelCommands,
|
||||||
|
int numTuners,
|
||||||
|
IFileSystem fileSystem,
|
||||||
|
IHttpClient httpClient,
|
||||||
|
ILogger logger,
|
||||||
|
IServerApplicationPaths appPaths,
|
||||||
|
IServerApplicationHost appHost,
|
||||||
|
MediaBrowser.Model.Net.ISocketFactory socketFactory,
|
||||||
|
INetworkManager networkManager)
|
||||||
: base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths)
|
: base(mediaSource, tunerHostInfo, fileSystem, logger, appPaths)
|
||||||
{
|
{
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
|
@ -58,7 +70,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host);
|
Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host);
|
||||||
|
|
||||||
var remoteAddress = IPAddress.Parse(uri.Host);
|
var remoteAddress = IPAddress.Parse(uri.Host);
|
||||||
var embyRemoteAddress = _networkManager.ParseIpAddress(uri.Host);
|
|
||||||
IPAddress localAddress = null;
|
IPAddress localAddress = null;
|
||||||
using (var tcpSocket = CreateSocket(remoteAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
|
using (var tcpSocket = CreateSocket(remoteAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
|
||||||
{
|
{
|
||||||
|
@ -81,7 +92,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// send url to start streaming
|
// send url to start streaming
|
||||||
await hdHomerunManager.StartStreaming(embyRemoteAddress, localAddress, localPort, _channelCommands, _numTuners, openCancellationToken).ConfigureAwait(false);
|
await hdHomerunManager.StartStreaming(remoteAddress, localAddress, localPort, _channelCommands, _numTuners, openCancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,14 +16,14 @@ namespace Emby.Server.Implementations.Net
|
||||||
// but that wasn't really the point so kept to YAGNI principal for now, even if the
|
// 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.
|
// interfaces are a bit ugly, specific and make assumptions.
|
||||||
|
|
||||||
public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort)
|
public ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort)
|
||||||
{
|
{
|
||||||
if (remotePort < 0)
|
if (remotePort < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("remotePort cannot be less than zero.", nameof(remotePort));
|
throw new ArgumentException("remotePort cannot be less than zero.", nameof(remotePort));
|
||||||
}
|
}
|
||||||
|
|
||||||
var addressFamily = remoteAddress.AddressFamily == IpAddressFamily.InterNetwork
|
var addressFamily = remoteAddress.AddressFamily == AddressFamily.InterNetwork
|
||||||
? AddressFamily.InterNetwork
|
? AddressFamily.InterNetwork
|
||||||
: AddressFamily.InterNetworkV6;
|
: AddressFamily.InterNetworkV6;
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Net
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort));
|
return new UdpSocket(retVal, new IPEndPoint(remoteAddress, remotePort));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Net
|
||||||
/// Creates a new UDP acceptSocket 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.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An implementation of the <see cref="ISocket"/> interface used by RSSDP components to perform acceptSocket operations.</returns>
|
/// <returns>An implementation of the <see cref="ISocket"/> interface used by RSSDP components to perform acceptSocket operations.</returns>
|
||||||
public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort)
|
public ISocket CreateSsdpUdpSocket(IPAddress localIpAddress, int localPort)
|
||||||
{
|
{
|
||||||
if (localPort < 0)
|
if (localPort < 0)
|
||||||
{
|
{
|
||||||
|
@ -115,10 +115,8 @@ namespace Emby.Server.Implementations.Net
|
||||||
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
||||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
|
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"), localIpAddress));
|
||||||
|
return new UdpSocket(retVal, localPort, localIpAddress);
|
||||||
retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp));
|
|
||||||
return new UdpSocket(retVal, localPort, localIp);
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.Net
|
||||||
|
|
||||||
public Socket Socket => _socket;
|
public Socket Socket => _socket;
|
||||||
|
|
||||||
public IpAddressInfo LocalIPAddress { get; }
|
public IPAddress LocalIPAddress { get; }
|
||||||
|
|
||||||
private readonly SocketAsyncEventArgs _receiveSocketAsyncEventArgs = new SocketAsyncEventArgs()
|
private readonly SocketAsyncEventArgs _receiveSocketAsyncEventArgs = new SocketAsyncEventArgs()
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Net
|
||||||
|
|
||||||
_socket = socket;
|
_socket = socket;
|
||||||
_localPort = localPort;
|
_localPort = localPort;
|
||||||
LocalIPAddress = NetworkManager.ToIpAddressInfo(ip);
|
LocalIPAddress = ip;
|
||||||
|
|
||||||
_socket.Bind(new IPEndPoint(ip, _localPort));
|
_socket.Bind(new IPEndPoint(ip, _localPort));
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.Net
|
||||||
{
|
{
|
||||||
Buffer = e.Buffer,
|
Buffer = e.Buffer,
|
||||||
ReceivedBytes = e.BytesTransferred,
|
ReceivedBytes = e.BytesTransferred,
|
||||||
RemoteEndPoint = ToIpEndPointInfo(e.RemoteEndPoint as IPEndPoint),
|
RemoteEndPoint = e.RemoteEndPoint as IPEndPoint,
|
||||||
LocalIPAddress = LocalIPAddress
|
LocalIPAddress = LocalIPAddress
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -100,12 +100,12 @@ namespace Emby.Server.Implementations.Net
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UdpSocket(Socket socket, IpEndPointInfo endPoint)
|
public UdpSocket(Socket socket, IPEndPoint endPoint)
|
||||||
{
|
{
|
||||||
if (socket == null) throw new ArgumentNullException(nameof(socket));
|
if (socket == null) throw new ArgumentNullException(nameof(socket));
|
||||||
|
|
||||||
_socket = socket;
|
_socket = socket;
|
||||||
_socket.Connect(NetworkManager.ToIPEndPoint(endPoint));
|
_socket.Connect(endPoint);
|
||||||
|
|
||||||
InitReceiveSocketAsyncEventArgs();
|
InitReceiveSocketAsyncEventArgs();
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ namespace Emby.Server.Implementations.Net
|
||||||
return new SocketReceiveResult
|
return new SocketReceiveResult
|
||||||
{
|
{
|
||||||
ReceivedBytes = receivedBytes,
|
ReceivedBytes = receivedBytes,
|
||||||
RemoteEndPoint = ToIpEndPointInfo((IPEndPoint)remoteEndPoint),
|
RemoteEndPoint = (IPEndPoint)remoteEndPoint,
|
||||||
Buffer = buffer,
|
Buffer = buffer,
|
||||||
LocalIPAddress = LocalIPAddress
|
LocalIPAddress = LocalIPAddress
|
||||||
};
|
};
|
||||||
|
@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Net
|
||||||
return ReceiveAsync(buffer, 0, buffer.Length, cancellationToken);
|
return ReceiveAsync(buffer, 0, buffer.Length, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SendToAsync(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, CancellationToken cancellationToken)
|
public Task SendToAsync(byte[] buffer, int offset, int size, IPEndPoint endPoint, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
|
@ -227,13 +227,11 @@ namespace Emby.Server.Implementations.Net
|
||||||
return taskCompletion.Task;
|
return taskCompletion.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, AsyncCallback callback, object state)
|
public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IPEndPoint endPoint, AsyncCallback callback, object state)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
var ipEndPoint = NetworkManager.ToIPEndPoint(endPoint);
|
return _socket.BeginSendTo(buffer, offset, size, SocketFlags.None, endPoint, callback, state);
|
||||||
|
|
||||||
return _socket.BeginSendTo(buffer, offset, size, SocketFlags.None, ipEndPoint, callback, state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int EndSendTo(IAsyncResult result)
|
public int EndSendTo(IAsyncResult result)
|
||||||
|
@ -268,15 +266,5 @@ namespace Emby.Server.Implementations.Net
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint)
|
|
||||||
{
|
|
||||||
if (endpoint == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NetworkManager.ToIpEndPointInfo(endpoint);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,55 +9,38 @@ using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.System;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
|
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Networking
|
namespace Emby.Server.Implementations.Networking
|
||||||
{
|
{
|
||||||
public class NetworkManager : INetworkManager
|
public class NetworkManager : INetworkManager
|
||||||
{
|
{
|
||||||
protected ILogger Logger { get; private set; }
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
public event EventHandler NetworkChanged;
|
private IPAddress[] _localIpAddresses;
|
||||||
public Func<string[]> LocalSubnetsFn { get; set; }
|
private readonly object _localIpAddressSyncLock = new object();
|
||||||
|
|
||||||
public NetworkManager(ILoggerFactory loggerFactory)
|
public NetworkManager(ILogger<NetworkManager> logger)
|
||||||
{
|
{
|
||||||
Logger = loggerFactory.CreateLogger(nameof(NetworkManager));
|
_logger = logger;
|
||||||
|
|
||||||
// In FreeBSD these events cause a crash
|
NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged;
|
||||||
if (OperatingSystem.Id != OperatingSystemId.BSD)
|
NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError(ex, "Error binding to NetworkAddressChanged event");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError(ex, "Error binding to NetworkChange_NetworkAvailabilityChanged event");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
|
public Func<string[]> LocalSubnetsFn { get; set; }
|
||||||
|
|
||||||
|
public event EventHandler NetworkChanged;
|
||||||
|
|
||||||
|
private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("NetworkAvailabilityChanged");
|
_logger.LogDebug("NetworkAvailabilityChanged");
|
||||||
OnNetworkChanged();
|
OnNetworkChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
|
private void OnNetworkAddressChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("NetworkAddressChanged");
|
_logger.LogDebug("NetworkAddressChanged");
|
||||||
OnNetworkChanged();
|
OnNetworkChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,39 +51,35 @@ namespace Emby.Server.Implementations.Networking
|
||||||
_localIpAddresses = null;
|
_localIpAddresses = null;
|
||||||
_macAddresses = null;
|
_macAddresses = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NetworkChanged != null)
|
if (NetworkChanged != null)
|
||||||
{
|
{
|
||||||
NetworkChanged(this, EventArgs.Empty);
|
NetworkChanged(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IpAddressInfo[] _localIpAddresses;
|
public IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface = true)
|
||||||
private readonly object _localIpAddressSyncLock = new object();
|
|
||||||
|
|
||||||
public IpAddressInfo[] GetLocalIpAddresses(bool ignoreVirtualInterface = true)
|
|
||||||
{
|
{
|
||||||
lock (_localIpAddressSyncLock)
|
lock (_localIpAddressSyncLock)
|
||||||
{
|
{
|
||||||
if (_localIpAddresses == null)
|
if (_localIpAddresses == null)
|
||||||
{
|
{
|
||||||
var addresses = GetLocalIpAddressesInternal(ignoreVirtualInterface).Result.Select(ToIpAddressInfo).ToArray();
|
var addresses = GetLocalIpAddressesInternal(ignoreVirtualInterface).ToArray();
|
||||||
|
|
||||||
_localIpAddresses = addresses;
|
_localIpAddresses = addresses;
|
||||||
|
|
||||||
return addresses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _localIpAddresses;
|
return _localIpAddresses;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<IPAddress>> GetLocalIpAddressesInternal(bool ignoreVirtualInterface)
|
private List<IPAddress> GetLocalIpAddressesInternal(bool ignoreVirtualInterface)
|
||||||
{
|
{
|
||||||
var list = GetIPsDefault(ignoreVirtualInterface)
|
var list = GetIPsDefault(ignoreVirtualInterface).ToList();
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (list.Count == 0)
|
if (list.Count == 0)
|
||||||
{
|
{
|
||||||
list.AddRange(await GetLocalIpAddressesFallback().ConfigureAwait(false));
|
list = GetLocalIpAddressesFallback().GetAwaiter().GetResult().ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
var listClone = list.ToList();
|
var listClone = list.ToList();
|
||||||
|
@ -351,13 +330,13 @@ namespace Emby.Server.Implementations.Networking
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var host = uri.DnsSafeHost;
|
var host = uri.DnsSafeHost;
|
||||||
Logger.LogDebug("Resolving host {0}", host);
|
_logger.LogDebug("Resolving host {0}", host);
|
||||||
|
|
||||||
address = GetIpAddresses(host).Result.FirstOrDefault();
|
address = GetIpAddresses(host).Result.FirstOrDefault();
|
||||||
|
|
||||||
if (address != null)
|
if (address != null)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("{0} resolved to {1}", host, address);
|
_logger.LogDebug("{0} resolved to {1}", host, address);
|
||||||
|
|
||||||
return IsInLocalNetworkInternal(address.ToString(), false);
|
return IsInLocalNetworkInternal(address.ToString(), false);
|
||||||
}
|
}
|
||||||
|
@ -368,7 +347,7 @@ namespace Emby.Server.Implementations.Networking
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError(ex, "Error resolving hostname");
|
_logger.LogError(ex, "Error resolving hostname");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -381,56 +360,41 @@ namespace Emby.Server.Implementations.Networking
|
||||||
return Dns.GetHostAddressesAsync(hostName);
|
return Dns.GetHostAddressesAsync(hostName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<IPAddress> GetIPsDefault(bool ignoreVirtualInterface)
|
private IEnumerable<IPAddress> GetIPsDefault(bool ignoreVirtualInterface)
|
||||||
{
|
{
|
||||||
NetworkInterface[] interfaces;
|
IEnumerable<NetworkInterface> interfaces;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var validStatuses = new[] { OperationalStatus.Up, OperationalStatus.Unknown };
|
|
||||||
|
|
||||||
interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
interfaces = NetworkInterface.GetAllNetworkInterfaces()
|
||||||
.Where(i => validStatuses.Contains(i.OperationalStatus))
|
.Where(x => x.OperationalStatus == OperationalStatus.Up
|
||||||
.ToArray();
|
|| x.OperationalStatus == OperationalStatus.Unknown);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (NetworkInformationException ex)
|
||||||
{
|
{
|
||||||
Logger.LogError(ex, "Error in GetAllNetworkInterfaces");
|
_logger.LogError(ex, "Error in GetAllNetworkInterfaces");
|
||||||
return new List<IPAddress>();
|
return Enumerable.Empty<IPAddress>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return interfaces.SelectMany(network =>
|
return interfaces.SelectMany(network =>
|
||||||
{
|
{
|
||||||
|
var ipProperties = network.GetIPProperties();
|
||||||
|
|
||||||
try
|
// Try to exclude virtual adapters
|
||||||
|
// http://stackoverflow.com/questions/8089685/c-sharp-finding-my-machines-local-ip-address-and-not-the-vms
|
||||||
|
var addr = ipProperties.GatewayAddresses.FirstOrDefault();
|
||||||
|
if (addr == null
|
||||||
|
|| (ignoreVirtualInterface
|
||||||
|
&& (addr.Address.Equals(IPAddress.Any) || addr.Address.Equals(IPAddress.IPv6Any))))
|
||||||
{
|
{
|
||||||
// suppress logging because it might be causing nas device wake up
|
return Enumerable.Empty<IPAddress>();
|
||||||
//logger.LogDebug("Querying interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
|
|
||||||
|
|
||||||
var ipProperties = network.GetIPProperties();
|
|
||||||
|
|
||||||
// Try to exclude virtual adapters
|
|
||||||
// http://stackoverflow.com/questions/8089685/c-sharp-finding-my-machines-local-ip-address-and-not-the-vms
|
|
||||||
var addr = ipProperties.GatewayAddresses.FirstOrDefault();
|
|
||||||
if (addr == null || ignoreVirtualInterface && string.Equals(addr.Address.ToString(), "0.0.0.0", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return new List<IPAddress>();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ipProperties.UnicastAddresses
|
|
||||||
.Select(i => i.Address)
|
|
||||||
.Where(i => i.AddressFamily == AddressFamily.InterNetwork || i.AddressFamily == AddressFamily.InterNetworkV6)
|
|
||||||
.ToList();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError(ex, "Error querying network interface");
|
|
||||||
return new List<IPAddress>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ipProperties.UnicastAddresses
|
||||||
|
.Select(i => i.Address)
|
||||||
|
.Where(i => i.AddressFamily == AddressFamily.InterNetwork || i.AddressFamily == AddressFamily.InterNetworkV6);
|
||||||
}).GroupBy(i => i.ToString())
|
}).GroupBy(i => i.ToString())
|
||||||
.Select(x => x.First())
|
.Select(x => x.First());
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<IEnumerable<IPAddress>> GetLocalIpAddressesFallback()
|
private static async Task<IEnumerable<IPAddress>> GetLocalIpAddressesFallback()
|
||||||
|
@ -612,32 +576,10 @@ namespace Emby.Server.Implementations.Networking
|
||||||
return hosts[0];
|
return hosts[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public IpAddressInfo ParseIpAddress(string ipAddress)
|
public bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask)
|
||||||
{
|
{
|
||||||
if (TryParseIpAddress(ipAddress, out var info))
|
IPAddress network1 = GetNetworkAddress(address1, subnetMask);
|
||||||
{
|
IPAddress network2 = GetNetworkAddress(address2, subnetMask);
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException("Invalid ip address: " + ipAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo)
|
|
||||||
{
|
|
||||||
if (IPAddress.TryParse(ipAddress, out var address))
|
|
||||||
{
|
|
||||||
ipAddressInfo = ToIpAddressInfo(address);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ipAddressInfo = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsInSameSubnet(IpAddressInfo address1, IpAddressInfo address2, IpAddressInfo subnetMask)
|
|
||||||
{
|
|
||||||
IPAddress network1 = GetNetworkAddress(ToIPAddress(address1), ToIPAddress(subnetMask));
|
|
||||||
IPAddress network2 = GetNetworkAddress(ToIPAddress(address2), ToIPAddress(subnetMask));
|
|
||||||
return network1.Equals(network2);
|
return network1.Equals(network2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -656,13 +598,13 @@ namespace Emby.Server.Implementations.Networking
|
||||||
{
|
{
|
||||||
broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
|
broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new IPAddress(broadcastAddress);
|
return new IPAddress(broadcastAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IpAddressInfo GetLocalIpSubnetMask(IpAddressInfo address)
|
public IPAddress GetLocalIpSubnetMask(IPAddress address)
|
||||||
{
|
{
|
||||||
NetworkInterface[] interfaces;
|
NetworkInterface[] interfaces;
|
||||||
IPAddress ipaddress = ToIPAddress(address);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -674,7 +616,7 @@ namespace Emby.Server.Implementations.Networking
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError(ex, "Error in GetAllNetworkInterfaces");
|
_logger.LogError(ex, "Error in GetAllNetworkInterfaces");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,85 +626,17 @@ namespace Emby.Server.Implementations.Networking
|
||||||
{
|
{
|
||||||
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses)
|
||||||
{
|
{
|
||||||
if (ip.Address.Equals(ipaddress) && ip.IPv4Mask != null)
|
if (ip.Address.Equals(address) && ip.IPv4Mask != null)
|
||||||
{
|
{
|
||||||
return ToIpAddressInfo(ip.IPv4Mask);
|
return ip.IPv4Mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint)
|
|
||||||
{
|
|
||||||
if (endpoint == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IpEndPointInfo(ToIpAddressInfo(endpoint.Address), endpoint.Port);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IPEndPoint ToIPEndPoint(IpEndPointInfo endpoint)
|
|
||||||
{
|
|
||||||
if (endpoint == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IPEndPoint(ToIPAddress(endpoint.IpAddress), endpoint.Port);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IPAddress ToIPAddress(IpAddressInfo address)
|
|
||||||
{
|
|
||||||
if (address.Equals(IpAddressInfo.Any))
|
|
||||||
{
|
|
||||||
return IPAddress.Any;
|
|
||||||
}
|
|
||||||
if (address.Equals(IpAddressInfo.IPv6Any))
|
|
||||||
{
|
|
||||||
return IPAddress.IPv6Any;
|
|
||||||
}
|
|
||||||
if (address.Equals(IpAddressInfo.Loopback))
|
|
||||||
{
|
|
||||||
return IPAddress.Loopback;
|
|
||||||
}
|
|
||||||
if (address.Equals(IpAddressInfo.IPv6Loopback))
|
|
||||||
{
|
|
||||||
return IPAddress.IPv6Loopback;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IPAddress.Parse(address.Address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IpAddressInfo ToIpAddressInfo(IPAddress address)
|
|
||||||
{
|
|
||||||
if (address.Equals(IPAddress.Any))
|
|
||||||
{
|
|
||||||
return IpAddressInfo.Any;
|
|
||||||
}
|
|
||||||
if (address.Equals(IPAddress.IPv6Any))
|
|
||||||
{
|
|
||||||
return IpAddressInfo.IPv6Any;
|
|
||||||
}
|
|
||||||
if (address.Equals(IPAddress.Loopback))
|
|
||||||
{
|
|
||||||
return IpAddressInfo.Loopback;
|
|
||||||
}
|
|
||||||
if (address.Equals(IPAddress.IPv6Loopback))
|
|
||||||
{
|
|
||||||
return IpAddressInfo.IPv6Loopback;
|
|
||||||
}
|
|
||||||
return new IpAddressInfo(address.ToString(), address.AddressFamily == AddressFamily.InterNetworkV6 ? IpAddressFamily.InterNetworkV6 : IpAddressFamily.InterNetwork);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IpAddressInfo[]> GetHostAddressesAsync(string host)
|
|
||||||
{
|
|
||||||
var addresses = await Dns.GetHostAddressesAsync(host).ConfigureAwait(false);
|
|
||||||
return addresses.Select(ToIpAddressInfo).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the network shares.
|
/// Gets the network shares.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -25,7 +26,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
|
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
private readonly List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> _responders = new List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>();
|
private readonly List<Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>> _responders = new List<Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>>();
|
||||||
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly IJsonSerializer _json;
|
private readonly IJsonSerializer _json;
|
||||||
|
@ -43,9 +44,9 @@ namespace Emby.Server.Implementations.Udp
|
||||||
AddMessageResponder("who is JellyfinServer?", true, RespondToV2Message);
|
AddMessageResponder("who is JellyfinServer?", true, RespondToV2Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddMessageResponder(string message, bool isSubstring, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task> responder)
|
private void AddMessageResponder(string message, bool isSubstring, Func<string, IPEndPoint, Encoding, CancellationToken, Task> responder)
|
||||||
{
|
{
|
||||||
_responders.Add(new Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>(message, isSubstring, responder));
|
_responders.Add(new Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>(message, isSubstring, responder));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -83,7 +84,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding)
|
private Tuple<string, Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding)
|
||||||
{
|
{
|
||||||
var text = encoding.GetString(buffer, 0, bytesReceived);
|
var text = encoding.GetString(buffer, 0, bytesReceived);
|
||||||
var responder = _responders.FirstOrDefault(i =>
|
var responder = _responders.FirstOrDefault(i =>
|
||||||
|
@ -99,10 +100,10 @@ namespace Emby.Server.Implementations.Udp
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>(text, responder);
|
return new Tuple<string, Tuple<string, bool, Func<string, IPEndPoint, Encoding, CancellationToken, Task>>>(text, responder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding, CancellationToken cancellationToken)
|
private async Task RespondToV2Message(string messageText, IPEndPoint endpoint, Encoding encoding, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var parts = messageText.Split('|');
|
var parts = messageText.Split('|');
|
||||||
|
|
||||||
|
@ -254,7 +255,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint, CancellationToken cancellationToken)
|
public async Task SendAsync(byte[] bytes, IPEndPoint remoteEndPoint, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_isDisposed)
|
if (_isDisposed)
|
||||||
{
|
{
|
||||||
|
|
|
@ -143,7 +143,7 @@ namespace Jellyfin.Server
|
||||||
options,
|
options,
|
||||||
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
|
||||||
new NullImageEncoder(),
|
new NullImageEncoder(),
|
||||||
new NetworkManager(_loggerFactory),
|
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()),
|
||||||
appConfig))
|
appConfig))
|
||||||
{
|
{
|
||||||
await appHost.InitAsync(new ServiceCollection()).ConfigureAwait(false);
|
await appHost.InitAsync(new ServiceCollection()).ConfigureAwait(false);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
|
@ -53,17 +54,12 @@ namespace MediaBrowser.Common.Net
|
||||||
/// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns>
|
||||||
bool IsInLocalNetwork(string endpoint);
|
bool IsInLocalNetwork(string endpoint);
|
||||||
|
|
||||||
IpAddressInfo[] GetLocalIpAddresses(bool ignoreVirtualInterface);
|
IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface);
|
||||||
|
|
||||||
IpAddressInfo ParseIpAddress(string ipAddress);
|
|
||||||
|
|
||||||
bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo);
|
|
||||||
|
|
||||||
Task<IpAddressInfo[]> GetHostAddressesAsync(string host);
|
|
||||||
|
|
||||||
bool IsAddressInSubnets(string addressString, string[] subnets);
|
bool IsAddressInSubnets(string addressString, string[] subnets);
|
||||||
|
|
||||||
bool IsInSameSubnet(IpAddressInfo address1, IpAddressInfo address2, IpAddressInfo subnetMask);
|
bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask);
|
||||||
IpAddressInfo GetLocalIpSubnetMask(IpAddressInfo address);
|
|
||||||
|
IPAddress GetLocalIpSubnetMask(IPAddress address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller
|
namespace MediaBrowser.Controller
|
||||||
|
@ -59,7 +59,7 @@ namespace MediaBrowser.Controller
|
||||||
/// Gets the local ip address.
|
/// Gets the local ip address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The local ip address.</value>
|
/// <value>The local ip address.</value>
|
||||||
Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken);
|
Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local API URL.
|
/// Gets the local API URL.
|
||||||
|
@ -77,7 +77,7 @@ namespace MediaBrowser.Controller
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local API URL.
|
/// Gets the local API URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string GetLocalApiUrl(IpAddressInfo address);
|
string GetLocalApiUrl(IPAddress address);
|
||||||
|
|
||||||
void LaunchUrl(string url);
|
void LaunchUrl(string url);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Model.Net;
|
using System.Net;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Dlna
|
namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
{
|
{
|
||||||
public Uri Location { get; set; }
|
public Uri Location { get; set; }
|
||||||
public Dictionary<string, string> Headers { get; set; }
|
public Dictionary<string, string> Headers { get; set; }
|
||||||
public IpAddressInfo LocalIpAddress { get; set; }
|
public IPAddress LocalIpAddress { get; set; }
|
||||||
public int LocalPort { get; set; }
|
public int LocalPort { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ namespace MediaBrowser.Model.Net
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISocket : IDisposable
|
public interface ISocket : IDisposable
|
||||||
{
|
{
|
||||||
IpAddressInfo LocalIPAddress { get; }
|
IPAddress LocalIPAddress { get; }
|
||||||
|
|
||||||
Task<SocketReceiveResult> ReceiveAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken);
|
Task<SocketReceiveResult> ReceiveAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
@ -21,6 +22,6 @@ namespace MediaBrowser.Model.Net
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a UDP message to a particular end point (uni or multicast).
|
/// Sends a UDP message to a particular end point (uni or multicast).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task SendToAsync(byte[] buffer, int offset, int bytes, IpEndPointInfo endPoint, CancellationToken cancellationToken);
|
Task SendToAsync(byte[] buffer, int offset, int bytes, IPEndPoint endPoint, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Net
|
namespace MediaBrowser.Model.Net
|
||||||
{
|
{
|
||||||
|
@ -8,7 +9,7 @@ namespace MediaBrowser.Model.Net
|
||||||
public interface ISocketFactory
|
public interface ISocketFactory
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Createa a new unicast socket using the specified local port number.
|
/// Creates a new unicast socket using the specified local port number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="localPort">The local port to bind to.</param>
|
/// <param name="localPort">The local port to bind to.</param>
|
||||||
/// <returns>A <see cref="ISocket"/> implementation.</returns>
|
/// <returns>A <see cref="ISocket"/> implementation.</returns>
|
||||||
|
@ -16,15 +17,15 @@ namespace MediaBrowser.Model.Net
|
||||||
|
|
||||||
ISocket CreateUdpBroadcastSocket(int localPort);
|
ISocket CreateUdpBroadcastSocket(int localPort);
|
||||||
|
|
||||||
ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort);
|
ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Createa a new unicast socket using the specified local port number.
|
/// Creates a new unicast socket using the specified local port number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ISocket CreateSsdpUdpSocket(IpAddressInfo localIp, int localPort);
|
ISocket CreateSsdpUdpSocket(IPAddress localIp, int localPort);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Createa a new multicast socket using the specified multicast IP address, multicast time to live and local port.
|
/// Creates a new multicast socket using the specified multicast IP address, multicast time to live and local port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ipAddress">The multicast IP address to bind to.</param>
|
/// <param name="ipAddress">The multicast IP address to bind to.</param>
|
||||||
/// <param name="multicastTimeToLive">The multicast time to live value. Actually a maximum number of network hops for UDP packets.</param>
|
/// <param name="multicastTimeToLive">The multicast time to live value. Actually a maximum number of network hops for UDP packets.</param>
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Net
|
|
||||||
{
|
|
||||||
public class IpAddressInfo
|
|
||||||
{
|
|
||||||
public static IpAddressInfo Any = new IpAddressInfo("0.0.0.0", IpAddressFamily.InterNetwork);
|
|
||||||
public static IpAddressInfo IPv6Any = new IpAddressInfo("00000000000000000000", IpAddressFamily.InterNetworkV6);
|
|
||||||
public static IpAddressInfo Loopback = new IpAddressInfo("127.0.0.1", IpAddressFamily.InterNetwork);
|
|
||||||
public static IpAddressInfo IPv6Loopback = new IpAddressInfo("::1", IpAddressFamily.InterNetworkV6);
|
|
||||||
|
|
||||||
public string Address { get; set; }
|
|
||||||
public IpAddressInfo SubnetMask { get; set; }
|
|
||||||
public IpAddressFamily AddressFamily { get; set; }
|
|
||||||
|
|
||||||
public IpAddressInfo(string address, IpAddressFamily addressFamily)
|
|
||||||
{
|
|
||||||
Address = address;
|
|
||||||
AddressFamily = addressFamily;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(IpAddressInfo address)
|
|
||||||
{
|
|
||||||
return string.Equals(address.Address, Address, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Address;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum IpAddressFamily
|
|
||||||
{
|
|
||||||
InterNetwork,
|
|
||||||
InterNetworkV6
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Net
|
|
||||||
{
|
|
||||||
public class IpEndPointInfo
|
|
||||||
{
|
|
||||||
public IpAddressInfo IpAddress { get; set; }
|
|
||||||
|
|
||||||
public int Port { get; set; }
|
|
||||||
|
|
||||||
public IpEndPointInfo()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IpEndPointInfo(IpAddressInfo address, int port)
|
|
||||||
{
|
|
||||||
IpAddress = address;
|
|
||||||
Port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
var ipAddresString = IpAddress == null ? string.Empty : IpAddress.ToString();
|
|
||||||
|
|
||||||
return ipAddresString + ":" + Port.ToString(CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace MediaBrowser.Model.Net
|
namespace MediaBrowser.Model.Net
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -18,7 +20,7 @@ namespace MediaBrowser.Model.Net
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="IpEndPointInfo"/> the data was received from.
|
/// The <see cref="IpEndPointInfo"/> the data was received from.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IpEndPointInfo RemoteEndPoint { get; set; }
|
public IPEndPoint RemoteEndPoint { get; set; }
|
||||||
public IpAddressInfo LocalIPAddress { get; set; }
|
public IPAddress LocalIPAddress { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Net;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
|
|
||||||
namespace Rssdp
|
namespace Rssdp
|
||||||
{
|
{
|
||||||
|
@ -11,12 +8,12 @@ namespace Rssdp
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DeviceAvailableEventArgs : EventArgs
|
public sealed class DeviceAvailableEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public IpAddressInfo LocalIpAddress { get; set; }
|
public IPAddress LocalIpAddress { get; set; }
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
private readonly DiscoveredSsdpDevice _DiscoveredDevice;
|
private readonly DiscoveredSsdpDevice _DiscoveredDevice;
|
||||||
private readonly bool _IsNewlyDiscovered;
|
private readonly bool _IsNewlyDiscovered;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -29,34 +26,34 @@ namespace Rssdp
|
||||||
/// <param name="isNewlyDiscovered">A boolean value indicating whether or not this device came from the cache. See <see cref="IsNewlyDiscovered"/> for more detail.</param>
|
/// <param name="isNewlyDiscovered">A boolean value indicating whether or not this device came from the cache. See <see cref="IsNewlyDiscovered"/> for more detail.</param>
|
||||||
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="discoveredDevice"/> parameter is null.</exception>
|
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="discoveredDevice"/> parameter is null.</exception>
|
||||||
public DeviceAvailableEventArgs(DiscoveredSsdpDevice discoveredDevice, bool isNewlyDiscovered)
|
public DeviceAvailableEventArgs(DiscoveredSsdpDevice discoveredDevice, bool isNewlyDiscovered)
|
||||||
{
|
{
|
||||||
if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice));
|
if (discoveredDevice == null) throw new ArgumentNullException(nameof(discoveredDevice));
|
||||||
|
|
||||||
_DiscoveredDevice = discoveredDevice;
|
_DiscoveredDevice = discoveredDevice;
|
||||||
_IsNewlyDiscovered = isNewlyDiscovered;
|
_IsNewlyDiscovered = isNewlyDiscovered;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public Properties
|
#region Public Properties
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if the device was discovered due to an alive notification, or a search and was not already in the cache. Returns false if the item came from the cache but matched the current search request.
|
/// Returns true if the device was discovered due to an alive notification, or a search and was not already in the cache. Returns false if the item came from the cache but matched the current search request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsNewlyDiscovered
|
public bool IsNewlyDiscovered
|
||||||
{
|
{
|
||||||
get { return _IsNewlyDiscovered; }
|
get { return _IsNewlyDiscovered; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A reference to a <see cref="DiscoveredSsdpDevice"/> instance containing the discovered details and allowing access to the full device description.
|
/// A reference to a <see cref="DiscoveredSsdpDevice"/> instance containing the discovered details and allowing access to the full device description.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DiscoveredSsdpDevice DiscoveredDevice
|
public DiscoveredSsdpDevice DiscoveredDevice
|
||||||
{
|
{
|
||||||
get { return _DiscoveredDevice; }
|
get { return _DiscoveredDevice; }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
|
|
||||||
namespace Rssdp.Infrastructure
|
namespace Rssdp.Infrastructure
|
||||||
{
|
{
|
||||||
|
@ -40,13 +40,13 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to a particular address (uni or multicast) and port.
|
/// Sends a message to a particular address (uni or multicast) and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken);
|
Task SendMessage(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to the SSDP multicast address and port.
|
/// Sends a message to the SSDP multicast address and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task SendMulticastMessage(string message, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken);
|
Task SendMulticastMessage(string message, IPAddress fromLocalIpAddress, CancellationToken cancellationToken);
|
||||||
Task SendMulticastMessage(string message, int sendCount, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken);
|
Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
|
|
||||||
namespace Rssdp.Infrastructure
|
namespace Rssdp.Infrastructure
|
||||||
{
|
{
|
||||||
|
@ -16,18 +12,18 @@ namespace Rssdp.Infrastructure
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
private readonly HttpRequestMessage _Message;
|
private readonly HttpRequestMessage _Message;
|
||||||
private readonly IpEndPointInfo _ReceivedFrom;
|
private readonly IPEndPoint _ReceivedFrom;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public IpAddressInfo LocalIpAddress { get; private set; }
|
public IPAddress LocalIpAddress { get; private set; }
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Full constructor.
|
/// Full constructor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RequestReceivedEventArgs(HttpRequestMessage message, IpEndPointInfo receivedFrom, IpAddressInfo localIpAddress)
|
public RequestReceivedEventArgs(HttpRequestMessage message, IPEndPoint receivedFrom, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
_Message = message;
|
_Message = message;
|
||||||
_ReceivedFrom = receivedFrom;
|
_ReceivedFrom = receivedFrom;
|
||||||
|
@ -49,7 +45,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="UdpEndPoint"/> the request came from.
|
/// The <see cref="UdpEndPoint"/> the request came from.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IpEndPointInfo ReceivedFrom
|
public IPEndPoint ReceivedFrom
|
||||||
{
|
{
|
||||||
get { return _ReceivedFrom; }
|
get { return _ReceivedFrom; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
|
|
||||||
namespace Rssdp.Infrastructure
|
namespace Rssdp.Infrastructure
|
||||||
{
|
{
|
||||||
|
@ -14,12 +10,12 @@ namespace Rssdp.Infrastructure
|
||||||
public sealed class ResponseReceivedEventArgs : EventArgs
|
public sealed class ResponseReceivedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
|
|
||||||
public IpAddressInfo LocalIpAddress { get; set; }
|
public IPAddress LocalIpAddress { get; set; }
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
private readonly HttpResponseMessage _Message;
|
private readonly HttpResponseMessage _Message;
|
||||||
private readonly IpEndPointInfo _ReceivedFrom;
|
private readonly IPEndPoint _ReceivedFrom;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -28,7 +24,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Full constructor.
|
/// Full constructor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ResponseReceivedEventArgs(HttpResponseMessage message, IpEndPointInfo receivedFrom)
|
public ResponseReceivedEventArgs(HttpResponseMessage message, IPEndPoint receivedFrom)
|
||||||
{
|
{
|
||||||
_Message = message;
|
_Message = message;
|
||||||
_ReceivedFrom = receivedFrom;
|
_ReceivedFrom = receivedFrom;
|
||||||
|
@ -49,7 +45,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="UdpEndPoint"/> the response came from.
|
/// The <see cref="UdpEndPoint"/> the response came from.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IpEndPointInfo ReceivedFrom
|
public IPEndPoint ReceivedFrom
|
||||||
{
|
{
|
||||||
get { return _ReceivedFrom; }
|
get { return _ReceivedFrom; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -163,7 +164,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to a particular address (uni or multicast) and port.
|
/// Sends a message to a particular address (uni or multicast) and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task SendMessage(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken)
|
public async Task SendMessage(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (messageData == null) throw new ArgumentNullException(nameof(messageData));
|
if (messageData == null) throw new ArgumentNullException(nameof(messageData));
|
||||||
|
|
||||||
|
@ -186,7 +187,7 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SendFromSocket(ISocket socket, byte[] messageData, IpEndPointInfo destination, CancellationToken cancellationToken)
|
private async Task SendFromSocket(ISocket socket, byte[] messageData, IPEndPoint destination, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -206,7 +207,7 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ISocket> GetSendSockets(IpAddressInfo fromLocalIpAddress, IpEndPointInfo destination)
|
private List<ISocket> GetSendSockets(IPAddress fromLocalIpAddress, IPEndPoint destination)
|
||||||
{
|
{
|
||||||
EnsureSendSocketCreated();
|
EnsureSendSocketCreated();
|
||||||
|
|
||||||
|
@ -215,24 +216,24 @@ namespace Rssdp.Infrastructure
|
||||||
var sockets = _sendSockets.Where(i => i.LocalIPAddress.AddressFamily == fromLocalIpAddress.AddressFamily);
|
var sockets = _sendSockets.Where(i => i.LocalIPAddress.AddressFamily == fromLocalIpAddress.AddressFamily);
|
||||||
|
|
||||||
// Send from the Any socket and the socket with the matching address
|
// Send from the Any socket and the socket with the matching address
|
||||||
if (fromLocalIpAddress.AddressFamily == IpAddressFamily.InterNetwork)
|
if (fromLocalIpAddress.AddressFamily == AddressFamily.InterNetwork)
|
||||||
{
|
{
|
||||||
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.Any) || fromLocalIpAddress.Equals(i.LocalIPAddress));
|
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.Any) || fromLocalIpAddress.Equals(i.LocalIPAddress));
|
||||||
|
|
||||||
// If sending to the loopback address, filter the socket list as well
|
// If sending to the loopback address, filter the socket list as well
|
||||||
if (destination.IpAddress.Equals(IpAddressInfo.Loopback))
|
if (destination.Address.Equals(IPAddress.Loopback))
|
||||||
{
|
{
|
||||||
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.Any) || i.LocalIPAddress.Equals(IpAddressInfo.Loopback));
|
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.Any) || i.LocalIPAddress.Equals(IPAddress.Loopback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (fromLocalIpAddress.AddressFamily == IpAddressFamily.InterNetworkV6)
|
else if (fromLocalIpAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.IPv6Any) || fromLocalIpAddress.Equals(i.LocalIPAddress));
|
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.IPv6Any) || fromLocalIpAddress.Equals(i.LocalIPAddress));
|
||||||
|
|
||||||
// If sending to the loopback address, filter the socket list as well
|
// If sending to the loopback address, filter the socket list as well
|
||||||
if (destination.IpAddress.Equals(IpAddressInfo.IPv6Loopback))
|
if (destination.Address.Equals(IPAddress.IPv6Loopback))
|
||||||
{
|
{
|
||||||
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IpAddressInfo.IPv6Any) || i.LocalIPAddress.Equals(IpAddressInfo.IPv6Loopback));
|
sockets = sockets.Where(i => i.LocalIPAddress.Equals(IPAddress.IPv6Any) || i.LocalIPAddress.Equals(IPAddress.IPv6Loopback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +241,7 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task SendMulticastMessage(string message, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken)
|
public Task SendMulticastMessage(string message, IPAddress fromLocalIpAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return SendMulticastMessage(message, SsdpConstants.UdpResendCount, fromLocalIpAddress, cancellationToken);
|
return SendMulticastMessage(message, SsdpConstants.UdpResendCount, fromLocalIpAddress, cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -248,7 +249,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a message to the SSDP multicast address and port.
|
/// Sends a message to the SSDP multicast address and port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task SendMulticastMessage(string message, int sendCount, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken)
|
public async Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (message == null) throw new ArgumentNullException(nameof(message));
|
if (message == null) throw new ArgumentNullException(nameof(message));
|
||||||
|
|
||||||
|
@ -263,12 +264,13 @@ namespace Rssdp.Infrastructure
|
||||||
// SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
|
// SSDP spec recommends sending messages multiple times (not more than 3) to account for possible packet loss over UDP.
|
||||||
for (var i = 0; i < sendCount; i++)
|
for (var i = 0; i < sendCount; i++)
|
||||||
{
|
{
|
||||||
await SendMessageIfSocketNotDisposed(messageData, new IpEndPointInfo
|
await SendMessageIfSocketNotDisposed(
|
||||||
{
|
messageData,
|
||||||
IpAddress = new IpAddressInfo(SsdpConstants.MulticastLocalAdminAddress, IpAddressFamily.InterNetwork),
|
new IPEndPoint(
|
||||||
Port = SsdpConstants.MulticastPort
|
IPAddress.Parse(SsdpConstants.MulticastLocalAdminAddress),
|
||||||
|
SsdpConstants.MulticastPort),
|
||||||
}, fromLocalIpAddress, cancellationToken).ConfigureAwait(false);
|
fromLocalIpAddress,
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -336,7 +338,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
#region Private Methods
|
#region Private Methods
|
||||||
|
|
||||||
private Task SendMessageIfSocketNotDisposed(byte[] messageData, IpEndPointInfo destination, IpAddressInfo fromLocalIpAddress, CancellationToken cancellationToken)
|
private Task SendMessageIfSocketNotDisposed(byte[] messageData, IPEndPoint destination, IPAddress fromLocalIpAddress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var sockets = _sendSockets;
|
var sockets = _sendSockets;
|
||||||
if (sockets != null)
|
if (sockets != null)
|
||||||
|
@ -364,13 +366,13 @@ namespace Rssdp.Infrastructure
|
||||||
{
|
{
|
||||||
var sockets = new List<ISocket>();
|
var sockets = new List<ISocket>();
|
||||||
|
|
||||||
sockets.Add(_SocketFactory.CreateSsdpUdpSocket(IpAddressInfo.Any, _LocalPort));
|
sockets.Add(_SocketFactory.CreateSsdpUdpSocket(IPAddress.Any, _LocalPort));
|
||||||
|
|
||||||
if (_enableMultiSocketBinding)
|
if (_enableMultiSocketBinding)
|
||||||
{
|
{
|
||||||
foreach (var address in _networkManager.GetLocalIpAddresses(_config.Configuration.IgnoreVirtualInterfaces))
|
foreach (var address in _networkManager.GetLocalIpAddresses(_config.Configuration.IgnoreVirtualInterfaces))
|
||||||
{
|
{
|
||||||
if (address.AddressFamily == IpAddressFamily.InterNetworkV6)
|
if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
// Not support IPv6 right now
|
// Not support IPv6 right now
|
||||||
continue;
|
continue;
|
||||||
|
@ -439,7 +441,7 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessMessage(string data, IpEndPointInfo endPoint, IpAddressInfo receivedOnLocalIpAddress)
|
private void ProcessMessage(string data, IPEndPoint endPoint, IPAddress receivedOnLocalIpAddress)
|
||||||
{
|
{
|
||||||
// Responses start with the HTTP version, prefixed with HTTP/ while
|
// Responses start with the HTTP version, prefixed with HTTP/ while
|
||||||
// requests start with a method which can vary and might be one we haven't
|
// requests start with a method which can vary and might be one we haven't
|
||||||
|
@ -481,7 +483,7 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRequestReceived(HttpRequestMessage data, IpEndPointInfo remoteEndPoint, IpAddressInfo receivedOnLocalIpAddress)
|
private void OnRequestReceived(HttpRequestMessage data, IPEndPoint remoteEndPoint, IPAddress receivedOnLocalIpAddress)
|
||||||
{
|
{
|
||||||
//SSDP specification says only * is currently used but other uri's might
|
//SSDP specification says only * is currently used but other uri's might
|
||||||
//be implemented in the future and should be ignored unless understood.
|
//be implemented in the future and should be ignored unless understood.
|
||||||
|
@ -496,7 +498,7 @@ namespace Rssdp.Infrastructure
|
||||||
handlers(this, new RequestReceivedEventArgs(data, remoteEndPoint, receivedOnLocalIpAddress));
|
handlers(this, new RequestReceivedEventArgs(data, remoteEndPoint, receivedOnLocalIpAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnResponseReceived(HttpResponseMessage data, IpEndPointInfo endPoint, IpAddressInfo localIpAddress)
|
private void OnResponseReceived(HttpResponseMessage data, IPEndPoint endPoint, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
var handlers = this.ResponseReceived;
|
var handlers = this.ResponseReceived;
|
||||||
if (handlers != null)
|
if (handlers != null)
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml;
|
|
||||||
using Rssdp.Infrastructure;
|
using Rssdp.Infrastructure;
|
||||||
|
|
||||||
namespace Rssdp
|
namespace Rssdp
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
|
|
||||||
namespace Rssdp.Infrastructure
|
namespace Rssdp.Infrastructure
|
||||||
{
|
{
|
||||||
|
@ -213,7 +210,7 @@ namespace Rssdp.Infrastructure
|
||||||
/// Raises the <see cref="DeviceAvailable"/> event.
|
/// Raises the <see cref="DeviceAvailable"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="DeviceAvailable"/>
|
/// <seealso cref="DeviceAvailable"/>
|
||||||
protected virtual void OnDeviceAvailable(DiscoveredSsdpDevice device, bool isNewDevice, IpAddressInfo localIpAddress)
|
protected virtual void OnDeviceAvailable(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
if (this.IsDisposed) return;
|
if (this.IsDisposed) return;
|
||||||
|
|
||||||
|
@ -295,7 +292,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
#region Discovery/Device Add
|
#region Discovery/Device Add
|
||||||
|
|
||||||
private void AddOrUpdateDiscoveredDevice(DiscoveredSsdpDevice device, IpAddressInfo localIpAddress)
|
private void AddOrUpdateDiscoveredDevice(DiscoveredSsdpDevice device, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
bool isNewDevice = false;
|
bool isNewDevice = false;
|
||||||
lock (_Devices)
|
lock (_Devices)
|
||||||
|
@ -316,7 +313,7 @@ namespace Rssdp.Infrastructure
|
||||||
DeviceFound(device, isNewDevice, localIpAddress);
|
DeviceFound(device, isNewDevice, localIpAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IpAddressInfo localIpAddress)
|
private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
if (!NotificationTypeMatchesFilter(device)) return;
|
if (!NotificationTypeMatchesFilter(device)) return;
|
||||||
|
|
||||||
|
@ -357,7 +354,7 @@ namespace Rssdp.Infrastructure
|
||||||
return _CommunicationsServer.SendMulticastMessage(message, null, cancellationToken);
|
return _CommunicationsServer.SendMulticastMessage(message, null, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessSearchResponseMessage(HttpResponseMessage message, IpAddressInfo localIpAddress)
|
private void ProcessSearchResponseMessage(HttpResponseMessage message, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
if (!message.IsSuccessStatusCode) return;
|
if (!message.IsSuccessStatusCode) return;
|
||||||
|
|
||||||
|
@ -378,7 +375,7 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessNotificationMessage(HttpRequestMessage message, IpAddressInfo localIpAddress)
|
private void ProcessNotificationMessage(HttpRequestMessage message, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0) return;
|
if (String.Compare(message.Method.Method, "Notify", StringComparison.OrdinalIgnoreCase) != 0) return;
|
||||||
|
|
||||||
|
@ -389,7 +386,7 @@ namespace Rssdp.Infrastructure
|
||||||
ProcessByeByeNotification(message);
|
ProcessByeByeNotification(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessAliveNotification(HttpRequestMessage message, IpAddressInfo localIpAddress)
|
private void ProcessAliveNotification(HttpRequestMessage message, IPAddress localIpAddress)
|
||||||
{
|
{
|
||||||
var location = GetFirstHeaderUriValue("Location", message);
|
var location = GetFirstHeaderUriValue("Location", message);
|
||||||
if (location != null)
|
if (location != null)
|
||||||
|
|
|
@ -2,13 +2,10 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using Rssdp;
|
|
||||||
|
|
||||||
namespace Rssdp.Infrastructure
|
namespace Rssdp.Infrastructure
|
||||||
{
|
{
|
||||||
|
@ -199,7 +196,12 @@ namespace Rssdp.Infrastructure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessSearchRequest(string mx, string searchTarget, IpEndPointInfo remoteEndPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken)
|
private void ProcessSearchRequest(
|
||||||
|
string mx,
|
||||||
|
string searchTarget,
|
||||||
|
IPEndPoint remoteEndPoint,
|
||||||
|
IPAddress receivedOnlocalIpAddress,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(searchTarget))
|
if (String.IsNullOrEmpty(searchTarget))
|
||||||
{
|
{
|
||||||
|
@ -258,7 +260,7 @@ namespace Rssdp.Infrastructure
|
||||||
foreach (var device in deviceList)
|
foreach (var device in deviceList)
|
||||||
{
|
{
|
||||||
if (!_sendOnlyMatchedHost ||
|
if (!_sendOnlyMatchedHost ||
|
||||||
_networkManager.IsInSameSubnet(device.ToRootDevice().Address, remoteEndPoint.IpAddress, device.ToRootDevice().SubnetMask))
|
_networkManager.IsInSameSubnet(device.ToRootDevice().Address, remoteEndPoint.Address, device.ToRootDevice().SubnetMask))
|
||||||
{
|
{
|
||||||
SendDeviceSearchResponses(device, remoteEndPoint, receivedOnlocalIpAddress, cancellationToken);
|
SendDeviceSearchResponses(device, remoteEndPoint, receivedOnlocalIpAddress, cancellationToken);
|
||||||
}
|
}
|
||||||
|
@ -276,7 +278,11 @@ namespace Rssdp.Infrastructure
|
||||||
return _Devices.Union(_Devices.SelectManyRecursive<SsdpDevice>((d) => d.Devices));
|
return _Devices.Union(_Devices.SelectManyRecursive<SsdpDevice>((d) => d.Devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendDeviceSearchResponses(SsdpDevice device, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken)
|
private void SendDeviceSearchResponses(
|
||||||
|
SsdpDevice device,
|
||||||
|
IPEndPoint endPoint,
|
||||||
|
IPAddress receivedOnlocalIpAddress,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
bool isRootDevice = (device as SsdpRootDevice) != null;
|
bool isRootDevice = (device as SsdpRootDevice) != null;
|
||||||
if (isRootDevice)
|
if (isRootDevice)
|
||||||
|
@ -296,7 +302,13 @@ namespace Rssdp.Infrastructure
|
||||||
return String.Format("{0}::{1}", udn, fullDeviceType);
|
return String.Format("{0}::{1}", udn, fullDeviceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SendSearchResponse(string searchTarget, SsdpDevice device, string uniqueServiceName, IpEndPointInfo endPoint, IpAddressInfo receivedOnlocalIpAddress, CancellationToken cancellationToken)
|
private async void SendSearchResponse(
|
||||||
|
string searchTarget,
|
||||||
|
SsdpDevice device,
|
||||||
|
string uniqueServiceName,
|
||||||
|
IPEndPoint endPoint,
|
||||||
|
IPAddress receivedOnlocalIpAddress,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var rootDevice = device.ToRootDevice();
|
var rootDevice = device.ToRootDevice();
|
||||||
|
|
||||||
|
@ -333,7 +345,7 @@ namespace Rssdp.Infrastructure
|
||||||
//WriteTrace(String.Format("Sent search response to " + endPoint.ToString()), device);
|
//WriteTrace(String.Format("Sent search response to " + endPoint.ToString()), device);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsDuplicateSearchRequest(string searchTarget, IpEndPointInfo endPoint)
|
private bool IsDuplicateSearchRequest(string searchTarget, IPEndPoint endPoint)
|
||||||
{
|
{
|
||||||
var isDuplicateRequest = false;
|
var isDuplicateRequest = false;
|
||||||
|
|
||||||
|
@ -556,7 +568,7 @@ namespace Rssdp.Infrastructure
|
||||||
|
|
||||||
private class SearchRequest
|
private class SearchRequest
|
||||||
{
|
{
|
||||||
public IpEndPointInfo EndPoint { get; set; }
|
public IPEndPoint EndPoint { get; set; }
|
||||||
public DateTime Received { get; set; }
|
public DateTime Received { get; set; }
|
||||||
public string SearchTarget { get; set; }
|
public string SearchTarget { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Net;
|
||||||
using System.Text;
|
|
||||||
using System.Xml;
|
|
||||||
using Rssdp.Infrastructure;
|
|
||||||
using MediaBrowser.Model.Net;
|
|
||||||
|
|
||||||
namespace Rssdp
|
namespace Rssdp
|
||||||
{
|
{
|
||||||
|
@ -56,12 +52,12 @@ namespace Rssdp
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Address used to check if the received message from same interface with this device/tree. Required.
|
/// Gets or sets the Address used to check if the received message from same interface with this device/tree. Required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IpAddressInfo Address { get; set; }
|
public IPAddress Address { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the SubnetMask used to check if the received message from same interface with this device/tree. Required.
|
/// Gets or sets the SubnetMask used to check if the received message from same interface with this device/tree. Required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IpAddressInfo SubnetMask { get; set; }
|
public IPAddress SubnetMask { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The base URL to use for all relative url's provided in other propertise (and those of child devices). Optional.
|
/// The base URL to use for all relative url's provided in other propertise (and those of child devices). Optional.
|
||||||
|
|
Loading…
Reference in a new issue