diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs index 9462674c30..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,46 +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, - - PreferIpv4 = true - - }).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) @@ -96,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); + } } } @@ -106,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) { @@ -128,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) @@ -144,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;