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); }
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); }
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); } }
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); } }
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); } }