/// <summary> /// Deal with incoming response packets. All answers /// are held in the cache, and listeners are notified. /// </summary> /// <param name="msg">Message.</param> public void HandleResponse(DNSIncoming msg) { long now = Utilities.CurrentTimeMilliseconds(); foreach (DNSRecord record in msg.Answers) { bool expired = record.IsExpired(now); if (this.Cache.Entries().Contains(record)) { if (expired) { this.Cache.Remove(record); } else { DNSRecord entry = (DNSRecord)this.Cache.Get(record); if (entry != null) { entry.ResetTTL(record); } } } else { this.Cache.Add(record); } } foreach (DNSRecord record in msg.Answers) { UpdateRecord(now, record); } }
public void AddAnswer(DNSIncoming incoming, DNSRecord record) { if (!record.SuppressedBy(incoming)) { AddAnswerAtTime(record, 0); } }
/// <summary> /// Returns true if any answer in a message can suffice for the /// information held in this record /// </summary> /// <returns><c>true</c>, if supressed, <c>false</c> otherwise.</returns> /// <param name="incoming">Incoming.</param> public bool SuppressedBy(DNSIncoming incoming) { foreach (DNSRecord record in incoming.Answers) { if (SuppressedByAnswer(record)) { return(true); } } return(false); }
public void HandleRead(Socket socket) { int recvSize = 0; byte[] buf = new byte[Constants.MAX_MSG_ABSOLUTE]; EndPoint remoteEp = new IPEndPoint(0, 0); try { recvSize = socket.ReceiveFrom(buf, ref remoteEp); } catch (SocketException e) { Console.WriteLine("HandleRead: Threw {0}", e); return; } Console.WriteLine("Received {0} bytes from {1}", recvSize, remoteEp); Array.Resize <byte>(ref buf, recvSize); this.data = buf; DNSIncoming msg = new DNSIncoming(buf); if (!msg.Valid) { Console.WriteLine("Incoming msg not valid..."); } else if (msg.IsQuery) { // Always multicast responses if (((IPEndPoint)remoteEp).Port == Constants.MDNS_PORT) { this.zc.HandleQuery(msg, Constants.MDNS_ADDRESS, Constants.MDNS_PORT); } // If it's not a multicast query, reply via unicast // and multicast else if (((IPEndPoint)remoteEp).Port == Constants.DNS_PORT) { this.zc.HandleQuery(msg, ((IPEndPoint)remoteEp).Address, ((IPEndPoint)remoteEp).Port); this.zc.HandleQuery(msg, Constants.MDNS_ADDRESS, Constants.MDNS_PORT); } } else { this.zc.HandleResponse(msg); } }
/// <summary> /// Deal with incoming query packets. Provides a response if /// possible. /// </summary> /// <param name="msg">Message.</param> /// <param name="address">Address.</param> /// <param name="port">Port.</param> public void HandleQuery(DNSIncoming msg, IPAddress address, int port) { DNSOutgoing outgoing = null; // Support unicast client responses if (port != Constants.MDNS_PORT) { outgoing = new DNSOutgoing((ushort)QueryFlags.Response | (ushort)Flags.AA, multicast: false); foreach (DNSQuestion question in msg.Questions) { outgoing.AddQuestion(question); } } foreach (DNSQuestion question in msg.Questions) { if (question.Type == DNSType.PTR) { if (question.Name == "_services._dns-sd._udp.local.") { foreach (string stype in this.serviceTypes.Keys) { if (outgoing == null) { outgoing = new DNSOutgoing((ushort)QueryFlags.Response | (ushort)Flags.AA); } outgoing.AddAnswer(msg, new DNSPointer( "_services._dns-sd._udp.local.", DNSType.PTR, DNSClass.IN, Constants.DNS_TTL, stype)); } } foreach (ServiceInfo service in this.services.Values) { if (question.Name == service.Type) { if (outgoing == null) { outgoing = new DNSOutgoing((ushort)QueryFlags.Response | (ushort)Flags.AA); } outgoing.AddAnswer(msg, new DNSPointer( service.Type, DNSType.PTR, DNSClass.IN, Constants.DNS_TTL, service.Name)); } } } else { if (outgoing == null) { outgoing = new DNSOutgoing((ushort)QueryFlags.Response | (ushort)Flags.AA); } // Answer A record queries for any service addresses we know if (question.Type == DNSType.A || question.Type == DNSType.ANY) { foreach (ServiceInfo s in this.services.Values) { if (s.Server == question.Name.ToLower()) { outgoing.AddAnswer(msg, new DNSAddress( question.Name, DNSType.A, DNSClass.IN | DNSClass.UNIQUE, Constants.DNS_TTL, Utilities.AddressToBytes(s.Address))); } } } if (!this.services.ContainsKey(question.Name.ToLower())) { continue; } ServiceInfo service = this.services[question.Name.ToLower()]; if (question.Type == DNSType.SRV || question.Type == DNSType.ANY) { outgoing.AddAnswer(msg, new DNSService( question.Name, DNSType.SRV, DNSClass.IN | DNSClass.UNIQUE, Constants.DNS_TTL, service.Priority, service.Weight, service.Port, service.Server)); } if (question.Type == DNSType.TXT || question.Type == DNSType.ANY) { outgoing.AddAnswer(msg, new DNSText( question.Name, DNSType.TXT, DNSClass.IN | DNSClass.UNIQUE, Constants.DNS_TTL, service.Text)); } if (question.Type == DNSType.SRV) { outgoing.AddAdditionalAnswer(new DNSAddress( service.Server, DNSType.A, DNSClass.IN | DNSClass.UNIQUE, Constants.DNS_TTL, Utilities.AddressToBytes(service.Address))); } } } if (outgoing != null && outgoing.Answers.Count > 0) { outgoing.ID = msg.ID; Send(outgoing, address, port); } }