private void OnReceive(IAsyncResult ar)
        {
            lock (this)
            {
                int length;
                try
                {
                    if (_socket == null)
                    {
                        return;
                    }
                    length = _socket.EndReceive(ar);
                }
                catch (Exception)
                {
                    return;
                }
                var stream = new MemoryStream(_buffer, 0, length);
                var reader = new DnsMessageReader(stream);
                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 && header.IsAuthorativeAnswer)
                {
                    for (int i = 0; i < header.QuestionCount; i++)
                    {
                        reader.ReadQuestion();
                    }

                    _packetServiceInfos.Clear();
                    _packetHostAddresses.Clear();

                    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.Information.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.Information.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;
                                    }
                                }
                            }
                        }
                    }
                    HandlePacketHostAddresses();
                    HandlePacketServiceInfos();
                }
                StartReceive();
            }
        }
Exemple #2
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();
            }
        }