예제 #1
0
        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;
                    }
                }
            }
        }
예제 #2
0
        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);
                        }
                    }
                }
            }
        }
예제 #3
0
        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();
            }
        }