Exemplo n.º 1
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="uri">The STUN or TURN server URI the connection is being attempted to.</param>
 /// <param name="id">Needs to be set uniquely for each ICE server used in this session. Gets added to the
 /// transaction ID to facilitate quick matching of STUN requests and responses. Needs to be between
 /// 0 and 9.</param>
 /// <param name="username">Optional. If authentication is required the username to use.</param>
 /// <param name="password">Optional. If authentication is required the password to use.</param>
 internal IceServer(STUNUri uri, int id, string username, string password)
 {
     _uri      = uri;
     _id       = id;
     _username = username;
     _password = password;
     GenerateNewTransactionID();
 }
Exemplo n.º 2
0
 /// <summary>
 /// Resolve method that can be used to request an AAAA result and fallback to a A
 /// lookup if none found.
 /// </summary>
 /// <param name="uri">The URI to lookup.</param>
 /// <param name="preferIPv6">True if IPv6 (AAAA record lookup) is preferred.</param>
 /// <returns>An IPEndPoint or null.</returns>
 public static Task <IPEndPoint> Resolve(STUNUri uri, bool preferIPv6 = false)
 {
     if (preferIPv6)
     {
         // Try AAAA record lookup followed by A record if none found.
         return(Resolve(uri, QueryType.AAAA)
                .ContinueWith(x => x.Result ?? Resolve(uri, QueryType.A).Result));
     }
     else
     {
         return(Resolve(uri, QueryType.A));
     }
 }
Exemplo n.º 3
0
 public static bool TryParse(string uriStr, out STUNUri uri)
 {
     try
     {
         uri = ParseSTUNUri(uriStr);
         return(uri != null);
     }
     catch
     {
         uri = null;
         return(false);
     }
 }
Exemplo n.º 4
0
        /// <summary>
        /// Resolve method that performs either an A or AAAA record lookup. If required
        /// a SRV record lookup will be performed prior to the A or AAAA lookup.
        /// </summary>
        /// <param name="uri">The STUN uri to lookup.</param>
        /// <param name="queryType">Whether the address lookup should be A or AAAA.</param>
        /// <returns>An IPEndPoint or null.</returns>
        private static async Task <IPEndPoint> Resolve(STUNUri uri, QueryType queryType)
        {
            if (uri == null || String.IsNullOrWhiteSpace(uri.Host))
            {
                throw new ArgumentNullException("uri", "DNS resolve was supplied an empty input.");
            }

            if (IPAddress.TryParse(uri.Host, out var ipAddress))
            {
                // Target is already an IP address, no DNS lookup required.
                return(new IPEndPoint(ipAddress, uri.Port));
            }
            else
            {
                if (!uri.Host.Contains(".") || uri.Host.EndsWith(MDNS_TLD))
                {
                    AddressFamily family = (queryType == QueryType.AAAA) ? AddressFamily.InterNetworkV6 :
                                           AddressFamily.InterNetwork;

                    // The lookup is for a local network host. Use the OS DNS logic as the
                    // main DNS client can be configured to use external DNS servers that won't
                    // be able to lookup this hostname.

                    IPHostEntry hostEntry = null;

                    try
                    {
                        hostEntry = Dns.GetHostEntry(uri.Host);
                    }
                    catch (SocketException)
                    {
                        // Socket exception gets thrown for failed lookups,
                    }

                    if (hostEntry != null)
                    {
                        var addressList = hostEntry.AddressList;

                        if (addressList?.Length == 0)
                        {
                            logger.LogWarning($"Operating System DNS lookup failed for {uri.Host}.");
                            return(null);
                        }
                        else
                        {
                            if (addressList.Any(x => x.AddressFamily == family))
                            {
                                var addressResult = addressList.First(x => x.AddressFamily == family);
                                return(new IPEndPoint(addressResult, uri.Port));
                            }
                            else
                            {
                                // Didn't get a result for the preferred address family so just use the
                                // first available result.
                                var addressResult = addressList.First();
                                return(new IPEndPoint(addressResult, uri.Port));
                            }
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    if (uri.ExplicitPort)
                    {
                        return(HostQuery(uri.Host, uri.Port, queryType));
                    }
                    else
                    {
                        try
                        {
                            ServiceHostEntry srvResult = null;
                            // No explicit port so use a SRV -> (A | AAAA -> A) record lookup.
                            var result = await _lookupClient.ResolveServiceAsync(uri.Host, uri.Scheme.ToString(), uri.Protocol.ToString().ToLower()).ConfigureAwait(false);

                            if (result == null || result.Count() == 0)
                            {
                                logger.LogDebug($"STUNDns SRV lookup returned no results for {uri}.");
                            }
                            else
                            {
                                srvResult = result.OrderBy(y => y.Priority).ThenByDescending(w => w.Weight).FirstOrDefault();
                            }

                            string host = uri.Host; // If no SRV results then fallback is to lookup the hostname directly.
                            int    port = uri.Port; // If no SRV results then fallback is to use the default port.

                            if (srvResult != null)
                            {
                                host = srvResult.HostName;
                                port = srvResult.Port;
                            }

                            return(HostQuery(host, port, queryType));
                        }
                        catch (Exception e)
                        {
                            logger.LogDebug($"STUNDns SRV lookup failure for {uri}. {e?.InnerException?.Message}");
                            return(null);
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
 /// <summary>
 /// Resolve method that can be used to request an AAAA result and fallback to a A
 /// lookup if none found.
 /// </summary>
 /// <param name="uri">The URI to lookup.</param>
 /// <param name="preferIPv6">True if IPv6 (AAAA record lookup) is preferred.</param>
 /// <returns>An IPEndPoint or null.</returns>
 public static Task <IPEndPoint> Resolve(STUNUri uri, bool preferIPv6 = false)
 {
     return(Resolve(uri, preferIPv6 ? QueryType.AAAA : QueryType.A));
 }
Exemplo n.º 6
0
        /// <summary>
        /// Resolve method that performs either an A or AAAA record lookup. If required
        /// a SRV record lookup will be performed prior to the A or AAAA lookup.
        /// </summary>
        /// <param name="uri">The STUN uri to lookup.</param>
        /// <param name="queryType">Whether the address lookup should be A or AAAA.</param>
        /// <returns>An IPEndPoint or null.</returns>
        public static Task <IPEndPoint> Resolve(STUNUri uri, QueryType queryType)
        {
            if (uri == null || String.IsNullOrWhiteSpace(uri.Host))
            {
                throw new ArgumentNullException("uri", "DNS resolve was supplied an empty input.");
            }

            if (IPAddress.TryParse(uri.Host, out var ipAddress))
            {
                // Target is already an IP address, no DNS lookup required.
                return(Task.FromResult(new IPEndPoint(ipAddress, uri.Port)));
            }
            else
            {
                if (!uri.Host.Contains(".") || uri.Host.EndsWith(MDNS_TLD))
                {
                    AddressFamily family = (queryType == QueryType.AAAA) ? AddressFamily.InterNetworkV6 :
                                           AddressFamily.InterNetwork;

                    // The lookup is for a local network host. Use the OS DNS logic as the
                    // main DNS client can be configured to use external DNS servers that won't
                    // be able to lookup this hostname.

                    IPHostEntry hostEntry = null;

                    try
                    {
                        hostEntry = Dns.GetHostEntry(uri.Host);
                    }
                    catch (SocketException)
                    {
                        // Socket exception gets thrown for failed lookups,
                    }

                    if (hostEntry != null)
                    {
                        var addressList = hostEntry.AddressList;

                        if (addressList?.Length == 0)
                        {
                            logger.LogWarning($"Operating System DNS lookup failed for {uri.Host}.");
                            return(Task.FromResult <IPEndPoint>(null));
                        }
                        else
                        {
                            if (addressList.Any(x => x.AddressFamily == family))
                            {
                                var addressResult = addressList.First(x => x.AddressFamily == family);
                                return(Task.FromResult(new IPEndPoint(addressResult, uri.Port)));
                            }
                            else
                            {
                                return(Task.FromResult <IPEndPoint>(null));
                            }
                        }
                    }
                    else
                    {
                        return(Task.FromResult <IPEndPoint>(null));
                    }
                }
                else
                {
                    if (uri.ExplicitPort)
                    {
                        // If the URI has an explicit port then it indicates SRV records should not be used.
                        return(_lookupClient.QueryAsync(uri.Host, queryType)
                               .ContinueWith <IPEndPoint>(x =>
                        {
                            var addrRecord = x.Result.Answers.FirstOrDefault();
                            return GetFromLookupResult(addrRecord, uri.Port);
                        }));
                    }
                    else
                    {
                        // No explicit port so use a SRV -> (A | AAAA) record lookup.
                        return(_lookupClient.ResolveServiceAsync(uri.Host, uri.Scheme.ToString(), uri.Protocol)
                               .ContinueWith <IPEndPoint>(x =>
                        {
                            var srvResult = x.Result.OrderBy(y => y.Priority).ThenByDescending(w => w.Weight).FirstOrDefault();

                            string host = uri.Host;     // If no SRV results then fallback is to lookup the hostname directly.
                            int port = uri.Port;        // If no SRV results then fallback is to use the default port.

                            if (srvResult != null)
                            {
                                host = srvResult.HostName;
                                port = srvResult.Port;
                            }

                            var addrRecord = _lookupClient.Query(host, queryType).Answers.FirstOrDefault();
                            return GetFromLookupResult(addrRecord, uri.Port);
                        }));
                    }
                }
            }
        }
Exemplo n.º 7
0
 public static bool AreEqual(STUNUri uri1, STUNUri uri2)
 {
     return(uri1 == uri2);
 }
Exemplo n.º 8
0
        public static STUNUri ParseSTUNUri(string uri)
        {
            STUNUri stunUri = new STUNUri();

            if (String.IsNullOrEmpty(uri))
            {
                throw new ApplicationException("A STUN URI cannot be parsed from an empty string.");
            }
            else
            {
                uri = uri.Trim();

                // If the scheme is included it needs to be within the first 5 characters.
                if (uri.Length > SCHEME_MAX_LENGTH + 2)
                {
                    string schemeStr = uri.Substring(0, SCHEME_MAX_LENGTH + 1);
                    int    colonPosn = schemeStr.IndexOf(SCHEME_ADDR_SEPARATOR);

                    if (colonPosn == -1)
                    {
                        // No scheme has been specified, use default.
                        stunUri.Scheme = DefaultSTUNScheme;
                    }
                    else
                    {
                        if (!Enum.TryParse <STUNSchemesEnum>(schemeStr.Substring(0, colonPosn), true,
                                                             out stunUri.Scheme))
                        {
                            stunUri.Scheme = DefaultSTUNScheme;
                        }

                        uri = uri.Substring(colonPosn + 1);
                    }
                }

                if (uri.IndexOf(':') != -1)
                {
                    stunUri.ExplicitPort = true;

                    if (IPSocket.TryParseIPEndPoint(uri, out var ipEndPoint))
                    {
                        if (ipEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
                        {
                            stunUri.Host = $"[{ipEndPoint.Address}]";
                        }
                        else
                        {
                            stunUri.Host = ipEndPoint.Address.ToString();
                        }

                        stunUri.Port = ipEndPoint.Port;
                    }
                    else
                    {
                        stunUri.Host = uri.Substring(0, uri.LastIndexOf(':'));
                        if (!Int32.TryParse(uri.Substring(uri.LastIndexOf(':') + 1), out stunUri.Port))
                        {
                            stunUri.Port = STUNConstants.GetPortForScheme(stunUri.Scheme);
                        }
                    }
                }
                else
                {
                    stunUri.Host = uri?.Trim();
                    stunUri.Port = STUNConstants.GetPortForScheme(stunUri.Scheme);
                }
            }

            return(stunUri);
        }