diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index c3b0314480..4f3e3fb283 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -196,9 +196,13 @@ namespace MediaBrowser.Api return name; } - return libraryManager.RootFolder - .GetRecursiveChildren(i => i is IHasArtist) - .Cast() + var items = libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name } + }); + + return items + .OfType() .SelectMany(i => i.AllArtists) .DistinctNames() .FirstOrDefault(i => @@ -239,8 +243,12 @@ namespace MediaBrowser.Api return name; } - return libraryManager.RootFolder - .GetRecursiveChildren(i => i is Game) + var items = libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new[] { typeof(Game).Name } + }); + + return items .SelectMany(i => i.Genres) .DistinctNames() .FirstOrDefault(i => diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index c30cdf1a73..f9dbd766f8 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -126,6 +126,23 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager } } + private void AddIpv4Option(HttpWebRequest request, HttpRequestOptions options) + { + if (!options.PreferIpv4) + { + return; + } + + request.ServicePoint.BindIPEndPointDelegate = (servicePount, remoteEndPoint, retryCount) => + { + if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork) + { + return new IPEndPoint(IPAddress.Any, 0); + } + throw new InvalidOperationException("no IPv4 address"); + }; + } + private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression) { var request = CreateWebRequest(options.Url); @@ -133,6 +150,8 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager if (httpWebRequest != null) { + AddIpv4Option(httpWebRequest, options); + AddRequestHeaders(httpWebRequest, options); httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None; diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs index 8c1f63e534..75368a5fc3 100644 --- a/MediaBrowser.Common/Net/HttpRequestOptions.cs +++ b/MediaBrowser.Common/Net/HttpRequestOptions.cs @@ -96,6 +96,7 @@ namespace MediaBrowser.Common.Net public TimeSpan CacheLength { get; set; } public int TimeoutMs { get; set; } + public bool PreferIpv4 { get; set; } private string GetHeaderValue(string name) { diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index a33e1d6c17..0b092397fe 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -100,13 +100,13 @@ namespace MediaBrowser.Providers.Omdb if (enableMultipleResults) { url += "&s=" + WebUtility.UrlEncode(name); + isSearch = true; } else { url += "&t=" + WebUtility.UrlEncode(name); } url += "&type=" + type; - isSearch = true; } else { diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs index 12de5f6ef1..1b951374ef 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs @@ -8,6 +8,7 @@ using MediaBrowser.Model.Net; using System; using System.IO; using System.Net; +using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -47,44 +48,26 @@ namespace MediaBrowser.Server.Implementations.Connect _timer = new PeriodicTimer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3)); } - private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.emby.media/service/ip" }; + private readonly string[] _ipLookups = + { + "http://bot.whatismyipaddress.com", + "https://connect.emby.media/service/ip" + }; private async void TimerCallback(object state) { - var index = 0; + IPAddress validIpAddress = null; foreach (var ipLookupUrl in _ipLookups) { try { - // Sometimes whatismyipaddress might fail, but it won't do us any good having users raise alarms over it. - var logErrors = index > 0; + validIpAddress = await GetIpAddress(ipLookupUrl).ConfigureAwait(false); -#if DEBUG - logErrors = true; -#endif - using (var stream = await _httpClient.Get(new HttpRequestOptions + // Try to find the ipv4 address, if present + if (validIpAddress.AddressFamily == AddressFamily.InterNetwork) { - Url = ipLookupUrl, - UserAgent = "Emby/" + _appHost.ApplicationVersion, - LogErrors = logErrors, - - // Seeing block length errors with our server - EnableHttpCompression = false - - }).ConfigureAwait(false)) - { - using (var reader = new StreamReader(stream)) - { - var address = await reader.ReadToEndAsync().ConfigureAwait(false); - - if (IsValid(address, ipLookupUrl)) - { - ((ConnectManager)_connectManager).OnWanAddressResolved(address); - CacheAddress(address); - return; - } - } + break; } } catch (HttpException) @@ -94,8 +77,66 @@ namespace MediaBrowser.Server.Implementations.Connect { _logger.ErrorException("Error getting connection info", ex); } + } - index++; + // If this produced an ipv6 address, try again + if (validIpAddress == null || validIpAddress.AddressFamily == AddressFamily.InterNetworkV6) + { + foreach (var ipLookupUrl in _ipLookups) + { + try + { + validIpAddress = await GetIpAddress(ipLookupUrl, true).ConfigureAwait(false); + + // Try to find the ipv4 address, if present + if (validIpAddress.AddressFamily == AddressFamily.InterNetwork) + { + break; + } + } + catch (HttpException) + { + } + catch (Exception ex) + { + _logger.ErrorException("Error getting connection info", ex); + } + } + } + + if (validIpAddress != null) + { + ((ConnectManager)_connectManager).OnWanAddressResolved(validIpAddress); + CacheAddress(validIpAddress); + } + } + + private async Task GetIpAddress(string lookupUrl, bool preferIpv4 = false) + { + // Sometimes whatismyipaddress might fail, but it won't do us any good having users raise alarms over it. + var logErrors = false; + +#if DEBUG + logErrors = true; +#endif + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = lookupUrl, + UserAgent = "Emby/" + _appHost.ApplicationVersion, + LogErrors = logErrors, + + // Seeing block length errors with our server + EnableHttpCompression = false, + PreferIpv4 = preferIpv4 + + }).ConfigureAwait(false)) + { + using (var reader = new StreamReader(stream)) + { + var addressString = await reader.ReadToEndAsync().ConfigureAwait(false); + + return IPAddress.Parse(addressString); + } } } @@ -104,14 +145,14 @@ namespace MediaBrowser.Server.Implementations.Connect get { return Path.Combine(_appPaths.DataPath, "wan.txt"); } } - private void CacheAddress(string address) + private void CacheAddress(IPAddress address) { var path = CacheFilePath; try { _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); - _fileSystem.WriteAllText(path, address, Encoding.UTF8); + _fileSystem.WriteAllText(path, address.ToString(), Encoding.UTF8); } catch (Exception ex) { @@ -126,10 +167,11 @@ namespace MediaBrowser.Server.Implementations.Connect try { var endpoint = _fileSystem.ReadAllText(path, Encoding.UTF8); + IPAddress ipAddress; - if (IsValid(endpoint, "cache")) + if (IPAddress.TryParse(endpoint, out ipAddress)) { - ((ConnectManager)_connectManager).OnWanAddressResolved(endpoint); + ((ConnectManager)_connectManager).OnWanAddressResolved(ipAddress); } } catch (IOException) @@ -142,19 +184,6 @@ namespace MediaBrowser.Server.Implementations.Connect } } - private bool IsValid(string address, string source) - { - IPAddress ipAddress; - var valid = IPAddress.TryParse(address, out ipAddress); - - if (!valid) - { - _logger.Error("{0} is not a valid ip address. Source: {1}", address, source); - } - - return valid; - } - public void Dispose() { if (_timer != null) diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 618b7ffc5e..ac0d2c569f 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -19,6 +19,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net; +using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -53,7 +54,7 @@ namespace MediaBrowser.Server.Implementations.Connect get { return _data.AccessKey; } } - public string DiscoveredWanIpAddress { get; private set; } + private IPAddress DiscoveredWanIpAddress { get; set; } public string WanIpAddress { @@ -61,9 +62,16 @@ namespace MediaBrowser.Server.Implementations.Connect { var address = _config.Configuration.WanDdns; - if (string.IsNullOrWhiteSpace(address)) + if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null) { - address = DiscoveredWanIpAddress; + if (DiscoveredWanIpAddress.AddressFamily == AddressFamily.InterNetworkV6) + { + address = "[" + DiscoveredWanIpAddress + "]"; + } + else + { + address = DiscoveredWanIpAddress.ToString(); + } } return address; @@ -81,12 +89,6 @@ namespace MediaBrowser.Server.Implementations.Connect if (!ip.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && !ip.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) { - // Handle ipv6 - if (ip.IndexOf(':') != -1) - { - ip = "[" + ip + "]"; - } - ip = (_appHost.EnableHttps ? "https://" : "http://") + ip; } @@ -130,7 +132,7 @@ namespace MediaBrowser.Server.Implementations.Connect LoadCachedData(); } - internal void OnWanAddressResolved(string address) + internal void OnWanAddressResolved(IPAddress address) { DiscoveredWanIpAddress = address; diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index c417cc09c4..cdeb6dfa86 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -100,7 +100,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { if (string.IsNullOrWhiteSpace(info.M3UUrl)) { - //return; + return; } await _liveTvManager.SaveTunerHost(new TunerHostInfo