private void HandlePacketHostAddresses() { foreach (var hostAddressKV in _packetHostAddresses) { Name name = hostAddressKV.Key; HostAddresses hostAddresses = hostAddressKV.Value; HostInfo hostInfo; _hostInfos.TryGetValue(name, out hostInfo); if (hostInfo == null) { return; } List <IPAddress> packetAddresses = new List <IPAddress>(); if (hostAddresses.IPv4Addresses == null) { if (hostInfo.Addresses != null) { packetAddresses.AddRange(hostInfo.Addresses.Where(a => a.AddressFamily == AddressFamily.InterNetwork)); } } else { packetAddresses.AddRange(hostAddresses.IPv4Addresses); } if (hostAddresses.IPv6Addresses == null) { if (hostInfo.Addresses != null) { packetAddresses.AddRange(hostInfo.Addresses.Where(a => a.AddressFamily == AddressFamily.InterNetworkV6)); } } else { packetAddresses.AddRange(hostAddresses.IPv6Addresses); } if (packetAddresses.Count == 0) { _hostInfos.Remove(name); foreach (var service in hostInfo.ServiceInfos) { PacketRemovesService(service.Name); } } else { var addresses = hostInfo.Addresses; bool same = (addresses != null) && (addresses.Count == packetAddresses.Count) && (addresses.TrueForAll(packetAddresses.Contains)); if (!same) { foreach (var service in hostInfo.ServiceInfos) { ServiceInfo newService = FindOrCreatePacketService(service.Name); newService.Addresses = packetAddresses; } hostInfo.Addresses = packetAddresses; } } } }
private void HandlePacketServiceInfos() { foreach (var serviceKV in _packetServiceInfos) { Name packetName = serviceKV.Key; ServiceInfo packetService = serviceKV.Value; if (packetService == null) { RemoveService(packetName); } else { bool modified = false; bool wasComplete = false; ServiceInfo service; _serviceInfos.TryGetValue(packetName, out service); if (service == null) { service = packetService; _serviceInfos.Add(packetName, service); _serviceHandlers[packetName.SubName(1)].ServiceInfos.Add(service); if (service.HostName != null) { AddServiceHostInfo(service); } modified = true; } else { service.OpenQueryCount = 0; wasComplete = service.IsComplete; if (packetService.Port != -1 && service.Port != packetService.Port) { service.Port = packetService.Port; modified = true; } if (packetService.Name.ToString() != service.Name.ToString()) { service.Name = packetService.Name; modified = true; } if (packetService.Txt != null && (service.Txt == null || !packetService.Txt.SequenceEqual(service.Txt))) { service.Txt = packetService.Txt; modified = true; } if (packetService.HostName != null && (service.HostName == null || service.HostName.ToString() != packetService.HostName.ToString())) { if (service.HostName != null) { ClearServiceHostInfo(service); } service.HostName = packetService.HostName; AddServiceHostInfo(service); modified = true; } if (packetService.Addresses != null) { service.Addresses = packetService.Addresses; modified = true; } } if (modified) { if (wasComplete != service.IsComplete) { if (wasComplete) { ServiceBrowser.OnServiceRemoved(service); } else { ServiceBrowser.OnServiceAdded(service); } } else if (service.IsComplete) { ServiceBrowser.OnServiceChanged(service); } } } } }
private void OnReceive(IAsyncResult ar) #endif { lock (this) { #if NETSTANDARD1_3 if (args.SocketError != SocketError.Success || _socket == null) { return; } int length = args.BytesTransferred; #else int length; try { if (_socket == null) { return; } length = _socket.EndReceive(ar); } catch (Exception) { return; } #endif var stream = new MemoryStream(_buffer, 0, length); var reader = new DnsMessageReader(stream); bool validPacket = true; _packetServiceInfos.Clear(); _packetHostAddresses.Clear(); try { Header header = reader.ReadHeader(); if (header.IsQuery && header.AnswerCount == 0) { for (int i = 0; i < header.QuestionCount; i++) { Question question = reader.ReadQuestion(); Name serviceName = question.QName; if (_serviceHandlers.ContainsKey(serviceName)) { if (header.TransactionID != _lastQueryId) { OnServiceQuery(serviceName); } } } } if (header.IsResponse && header.IsNoError) { for (int i = 0; i < header.QuestionCount; i++) { reader.ReadQuestion(); } for (int i = 0; i < (header.AnswerCount + header.AuthorityCount + header.AdditionalCount); i++) { RecordHeader recordHeader = reader.ReadRecordHeader(); if ((recordHeader.Type == RecordType.A) || (recordHeader.Type == RecordType.AAAA)) // A or AAAA { IPAddress address = reader.ReadARecord(); if (address.AddressFamily == AddressFamily.InterNetworkV6) { if (!NetworkInterface.Supports(NetworkInterfaceComponent.IPv6)) { continue; } // Mono does not support IPv6 properties and always throws NotImplementedException. // Lets handle the case as with Supports. try { address.ScopeId = NetworkInterface.GetIPProperties().GetIPv6Properties().Index; } catch (NotImplementedException) { continue; } } OnARecord(recordHeader.Name, address, recordHeader.Ttl); } else if ((recordHeader.Type == RecordType.SRV) || (recordHeader.Type == RecordType.TXT) || (recordHeader.Type == RecordType.PTR)) { Name serviceName; Name instanceName; if (recordHeader.Type == RecordType.PTR) { serviceName = recordHeader.Name; instanceName = reader.ReadPtrRecord(); } else { instanceName = recordHeader.Name; serviceName = instanceName.SubName(1); } if (_serviceHandlers.ContainsKey(serviceName)) { if (recordHeader.Ttl == 0) { PacketRemovesService(instanceName); } else { ServiceInfo service = FindOrCreatePacketService(instanceName); if (recordHeader.Type == RecordType.SRV) { SrvRecord srvRecord = reader.ReadSrvRecord(); service.HostName = srvRecord.Target; service.Port = srvRecord.Port; } else if (recordHeader.Type == RecordType.TXT) { List <string> txts = reader.ReadTxtRecord(); service.Txt = txts; } } } } } } } catch { validPacket = false; } if (validPacket) { HandlePacketHostAddresses(); HandlePacketServiceInfos(); } StartReceive(); } }