Ejemplo n.º 1
0
        /// <summary>
        /// Attempts to parse a subnet from CIDR notation in the form of <i>ip-address</i>/<i>prefix</i>,
        /// where <i>prefix</i> is the network prefix length in bits.
        /// </summary>
        /// <param name="input">The input string.</param>
        /// <param name="cidr">The parsed <see cref="NetworkCidr"/>.</param>
        /// <returns><c>true</c> if the operation was successful.</returns>
        public static bool TryParse(string input, out NetworkCidr cidr)
        {
            cidr = null;

            if (string.IsNullOrEmpty(input))
            {
                return(false);
            }

            var slashPos = input.IndexOf('/');

            if (slashPos <= 0)
            {
                return(false);
            }

            if (!NetHelper.TryParseIPv4Address(input.Substring(0, slashPos), out var address))
            {
                return(false);
            }

            if (!int.TryParse(input.Substring(slashPos + 1), out var prefixLength) || prefixLength < 0 || prefixLength > 32)
            {
                return(false);
            }

            cidr = new NetworkCidr();

            cidr.Initialize(address, prefixLength);

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Parses a subnet from CIDR notation in the form of <i>ip-address</i>/<i>prefix</i>,
        /// where <i>prefix</i> is the network prefix length in bits.
        /// </summary>
        /// <param name="input">The input string.</param>
        /// <returns>The parsed <see cref="NetworkCidr"/>.</returns>
        /// <exception cref="ArgumentException">Thrown if the input is not correctly formatted.</exception>
        public static NetworkCidr Parse(string input)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(input), nameof(input));

            var slashPos = input.IndexOf('/');

            if (slashPos <= 0)
            {
                throw new ArgumentException($"Invalid CIDR [{input}].", nameof(input));
            }

            if (!NetHelper.TryParseIPv4Address(input.Substring(0, slashPos), out var address))
            {
                throw new ArgumentException($"Invalid CIDR [{input}].", nameof(input));
            }

            if (!int.TryParse(input.Substring(slashPos + 1), out var prefixLength) || prefixLength < 0 || prefixLength > 32)
            {
                throw new ArgumentException($"Invalid CIDR [{input}].", nameof(input));
            }

            var cidr = new NetworkCidr();

            cidr.Initialize(address, prefixLength);

            return(cidr);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Attempts to resolve an IP address or fully qualified domain name
        /// into host IP addresses.
        /// </summary>
        /// <param name="addressOrFQDN">The IP address or FQDN.</param>
        /// <param name="noCache">
        /// Optionally specify that the method is not to answer from the cache,
        /// even if the cache is enabled.
        /// </param>
        /// <returns>An empty result set if the lookup failed.</returns>
        public async Task <IEnumerable <IPAddress> > LookupAsync(string addressOrFQDN, bool noCache = false)
        {
            await SyncContext.Clear;

            // We can short-circuit things if the parameter is an IP address.

            if (NetHelper.TryParseIPv4Address(addressOrFQDN, out var address))
            {
                return(new IPAddress[] { address });
            }

            // Try to answer from the cache, if enabled.

            if (cache != null && !noCache)
            {
                lock (cache)
                {
                    if (cache.TryGetValue(addressOrFQDN, out var answer))
                    {
                        if (answer.TTD > SysTime.Now)
                        {
                            // The answer hasn't expired yet, so we'll return it.

                            return(answer.Addresses);
                        }
                    }
                }
            }

            // We're going to submit requests to all DNS clients in parallel and
            // return replies from the first one that answers.

            var readyEvent = new AsyncAutoResetEvent();
            var sync       = new object();
            var pending    = clients.Length;
            var results    = (IList <IPAddress>)null;

            foreach (var client in clients)
            {
                var task = Task.Run(
                    async() =>
                {
                    try
                    {
                        var addresses = await client.Lookup(addressOrFQDN);

                        if (addresses.Count > 0)
                        {
                            lock (sync)
                            {
                                if (results == null)
                                {
                                    results = addresses;
                                }
                            }
                        }

                        Interlocked.Decrement(ref pending);
                        readyEvent.Set();
                    }
                    catch (ResponseException)
                    {
                        // $todo(jefflill):
                        //
                        // I wish the underlying [DnsClient] didn't throw exceptions.  Perhaps
                        // I could extend the implementation to implement [TryResolve()].

                        Interlocked.Decrement(ref pending);
                        readyEvent.Set();
                    }
                });
            }

            while (pending > 0)
            {
                await readyEvent.WaitAsync();

                if (results != null)
                {
                    return(results);
                }
            }

            return(null);
        }