示例#1
0
        static async Task <IDictionary <string, Response> > ResolveInternal(ZeroconfOptions options,
                                                                            Action <string, Response> callback,
                                                                            CancellationToken cancellationToken)
        {
            var requestBytes = GetRequestBytes(options);

            using (options.AllowOverlappedQueries ? Disposable.Empty : await ResolverLock.LockAsync())
            {
                cancellationToken.ThrowIfCancellationRequested();
                var dict = new Dictionary <string, Response>();

                void Converter(IPAddress address, byte[] buffer)
                {
                    var resp       = new Response(buffer);
                    var firstPtr   = resp.RecordsPTR.FirstOrDefault();
                    var name       = firstPtr?.PTRDNAME.Split('.')[0] ?? string.Empty;
                    var addrString = address.ToString();

                    Debug.WriteLine($"IP: {addrString}, {(string.IsNullOrEmpty(name) ? string.Empty : $"Name: {name}, ")}Bytes: {buffer.Length}, IsResponse: {resp.header.QR}");

                    if (resp.header.QR)
                    {
                        var key = $"{addrString}{(string.IsNullOrEmpty(name) ? "" : $": {name}")}";
                        lock (dict)
                        {
                            dict[key] = resp;
                        }

                        callback?.Invoke(key, resp);
                    }
                }

                Debug.WriteLine($"Looking for {string.Join(", ", options.Protocols)} with scantime {options.ScanTime}");

                if (options.Adapter != null)
                {
                    await NetworkInterface.NetworkRequestAsync(requestBytes,
                                                               options.ScanTime,
                                                               options.Retries,
                                                               (int)options.RetryDelay.TotalMilliseconds,
                                                               Converter,
                                                               options.Adapter,
                                                               cancellationToken)
                    .ConfigureAwait(false);
                }
                else
                {
                    await NetworkInterface.NetworkRequestAsync(requestBytes,
                                                               options.ScanTime,
                                                               options.Retries,
                                                               (int)options.RetryDelay.TotalMilliseconds,
                                                               Converter,
                                                               cancellationToken)
                    .ConfigureAwait(false);
                }

                return(dict);
            }
        }
        static byte[] GetRequestBytes(ZeroconfOptions options)
        {
            var req       = new Request();
            var queryType = options.ScanQueryType == ScanQueryType.Ptr ? QType.PTR : QType.ANY;

            foreach (var protocol in options.Protocols)
            {
                var question = new Question(protocol, queryType, QClass.IN);

                req.AddQuestion(question);
            }

            return(req.Data);
        }
示例#3
0
        static byte[] GetRequestBytes(ZeroconfOptions options)
        {
            var req       = new Request();
            var classType = options.ScanClassType == ScanClassType.In ? QClass.IN : QClass.ANY;

            foreach (var protocol in options.Protocols)
            {
                foreach (var queryType in options.ScanQueryTypes)
                {
                    var question = new Question(protocol, ScanQueryToQType(queryType), classType);
                    req.AddQuestion(question);
                }
            }

            return(req.Data);
        }
示例#4
0
        static async Task <IDictionary <string, Response> > ResolveInternal(ZeroconfOptions options,
                                                                            Action <string, Response> callback,
                                                                            CancellationToken cancellationToken)
        {
            var requestBytes = GetRequestBytes(options);

            using (await ResolverLock.LockAsync())
            {
                cancellationToken.ThrowIfCancellationRequested();
                var dict = new Dictionary <string, Response>();

                Action <string, byte[]> converter =
                    (address, buffer) =>
                {
                    var resp = new Response(buffer);
                    Debug.WriteLine($"IP: {address}, Bytes: {buffer.Length}, IsResponse: {resp.header.QR}");

                    if (resp.header.QR)
                    {
                        lock (dict)
                        {
                            dict[address] = resp;
                        }

                        callback?.Invoke(address, resp);
                    }
                };

                Debug.WriteLine($"Looking for {string.Join(", ", options.Protocols)} with scantime {options.ScanTime}");

                await NetworkInterface.NetworkRequestAsync(requestBytes,
                                                           options.ScanTime,
                                                           options.Retries,
                                                           (int)options.RetryDelay.TotalMilliseconds,
                                                           converter,
                                                           cancellationToken)
                .ConfigureAwait(false);

                return(dict);
            }
        }
示例#5
0
        static async Task <IDictionary <string, Response> > ResolveInternal(ZeroconfOptions options,
                                                                            Action <string, Response> callback,
                                                                            CancellationToken cancellationToken)
        {
            var requestBytes = GetRequestBytes(options);

            using (options.AllowOverlappedQueries ? Disposable.Empty : await ResolverLock.LockAsync())
            {
                cancellationToken.ThrowIfCancellationRequested();
                var dict = new Dictionary <string, Response>();

                void Converter(IPAddress address, byte[] buffer)
                {
                    var resp       = new Response(buffer);
                    var firstPtr   = resp.RecordsPTR.FirstOrDefault();
                    var name       = firstPtr?.PTRDNAME.Split('.')[0] ?? string.Empty;
                    var addrString = address.ToString();

                    Debug.WriteLine($"IP: {addrString}, {(string.IsNullOrEmpty(name) ? string.Empty : $"Name: {name}, ")}Bytes: {buffer.Length}, IsResponse: {resp.header.QR}");

                    if (resp.header.QR)
                    {
                        // see if the IP is the same as the A to filter out dups that might echo from other interfaces


                        var aRec           = resp.RecordsA.FirstOrDefault();
                        var additionalARec = resp.Additionals.FirstOrDefault(arr => arr.Type == Type.A)?.RECORD as RecordA;

                        // if we have an aRec or additionalARec, check those
                        bool?matches = null;
                        if (aRec != null || additionalARec != null)
                        {
                            matches = string.Equals(aRec?.Address, addrString, StringComparison.OrdinalIgnoreCase) ||
                                      string.Equals(additionalARec?.Address, addrString, StringComparison.OrdinalIgnoreCase);
                        }

                        if (matches ?? true)
                        {
                            var key = $"{addrString}{(string.IsNullOrEmpty(name) ? "" : $": {name}")}";
                            lock (dict)
                            {
                                dict[key] = resp;
                            }

                            callback?.Invoke(key, resp);
                        }
                    }
                }

                Debug.WriteLine($"Looking for {string.Join(", ", options.Protocols)} with scantime {options.ScanTime}");

                await NetworkInterface.NetworkRequestAsync(requestBytes,
                                                           options.ScanTime,
                                                           options.Retries,
                                                           (int)options.RetryDelay.TotalMilliseconds,
                                                           Converter,
                                                           cancellationToken)
                .ConfigureAwait(false);

                return(dict);
            }
        }
示例#6
0
        static async Task <IDictionary <string, Response> > ResolveInternal(ZeroconfOptions options,
                                                                            Action <string, Response> callback,
                                                                            CancellationToken cancellationToken)
        {
            var requestBytes = GetRequestBytes(options);

            using (options.AllowOverlappedQueries ? Disposable.Empty : await ResolverLock.LockAsync())
            {
                cancellationToken.ThrowIfCancellationRequested();
                var dict = new Dictionary <string, Response>();

                void Converter(IPAddress address, byte[] buffer)
                {
                    var resp       = new Response(buffer);
                    var firstPtr   = resp.RecordsPTR.FirstOrDefault();
                    var name       = firstPtr?.PTRDNAME.Split('.')[0] ?? string.Empty;
                    var addrString = address.ToString();

                    Debug.WriteLine($"IP: {addrString}, {(string.IsNullOrEmpty(name) ? string.Empty : $"Name: {name}, ")}Bytes: {buffer.Length}, IsResponse: {resp.header.QR}");

                    if (resp.header.QR)
                    {
                        // see if the IP is the same as the A to filter out dups that might echo from other interfaces


                        var aRec           = resp.RecordsA.FirstOrDefault();
                        var additionalARec = resp.Additionals.FirstOrDefault(arr => arr.Type == Type.A)?.RECORD as RecordA;

                        // if we have an aRec or additionalARec, check those
                        bool?matches = null;
                        if (aRec != null || additionalARec != null)
                        {
                            matches = string.Equals(aRec?.Address, addrString, StringComparison.OrdinalIgnoreCase) ||
                                      string.Equals(additionalARec?.Address, addrString, StringComparison.OrdinalIgnoreCase);
                        }

                        if (matches ?? true)
                        {
                            // Key is IP Address. Multiple responses from the same IP mean truncated DNS response packets.
                            // Reassemble them here...this does break the header and raw fields but downstream
                            // just uses the lists of records.
                            var key = $"{addrString}";// {(string.IsNullOrEmpty(name) ? "" : $": {name}")}";
                            lock (dict)
                            {
                                Response prevresp = null;
                                if (!dict.TryGetValue(key, out prevresp))
                                {
                                    dict[key] = resp;
                                }
                                else
                                {
                                    // Add the new response records to the previous
                                    prevresp.Answers.AddRange(resp.Answers);
                                }
                            }

                            callback?.Invoke(key, resp);
                        }
                    }
                }

                Debug.WriteLine($"Looking for {string.Join(", ", options.Protocols)} with scantime {options.ScanTime}");

                // If there isn't a forced adapter, check all devices
                if (options.Adapter == null)
                {
                    await NetworkInterface.NetworkRequestAsync(requestBytes,
                                                               options.ScanTime,
                                                               options.Retries,
                                                               (int)options.RetryDelay.TotalMilliseconds,
                                                               Converter,
                                                               cancellationToken)
                    .ConfigureAwait(false);
                }
                else
                {
                    await NetworkInterface.NetworkRequestAsync(requestBytes,
                                                               options.ScanTime,
                                                               options.Retries,
                                                               (int)options.RetryDelay.TotalMilliseconds,
                                                               Converter,
                                                               options.Adapter,
                                                               cancellationToken)
                    .ConfigureAwait(false);
                }

                return(dict);
            }
        }