void ResolveHost(DnsQuestion question) { IPAddress address; if (IPAddress.TryParse(question.QueryName, out address)) { Console.WriteLine("Ignored question for IP {0}.", address); Cache.Add(question, new DnsCacheEntry { Data = address.GetAddressBytes(), TimeToLive = TimeSpan.FromMinutes(1) }); } else { byte[] addr = HostsFile[question.QueryName]; if (addr == null) { byte[] pkt = new DnsPacket { RecursionDesired = true, Questions = new [] { question } }.ToByteArray(); Console.WriteLine("Question for {0}", question.QueryName); foreach (UdpClient upstream in Upstreams) { upstream.Send(pkt, pkt.Length); } } else { Console.WriteLine("Found {0} in hosts file.", question.QueryName); Cache.Add(question, new DnsCacheEntry { Data = addr, TimeToLive = HostsFile.TimeToLive }); } } }
void ReadCallback(IAsyncResult iar) { IPEndPoint endPoint = new IPEndPoint(Address, Port); byte[] data = Listener.EndReceive(iar, ref endPoint); Listener.BeginReceive(ReadCallback, null); DnsPacket packet = new DnsPacket(data); List <Task <DnsResourceRecord> > answers = new List <Task <DnsResourceRecord> >(); foreach (DnsQuestion question in packet.Questions) { if (question.QueryName.EndsWith(".proxyconfigurer.localhost")) { string query = question.QueryName.Substring(0, question.QueryName.Length - ".proxyconfigurer.localhost".Length); string[] parts = query.Split('.'); string last = parts[parts.Length - 1]; ushort nonce; if (last.StartsWith('n') && ushort.TryParse(last.Substring(1), out nonce)) { if (parts[0] == "p") { answers.Add(Handler.GetConfigurationPacket(nonce).ContinueWith(t => new DnsResourceRecord { Name = question.QueryName, Type = question.Type, Class = question.Class, TimeToLive = t.Result.Item2, Data = t.Result.Item1 })); } else { answers.Add(Handler.ResolveHost(nonce, int.Parse(parts[0].Substring(1))).ContinueWith(t => { Task <DnsResourceRecord> task = Cache[new DnsQuestion { QueryName = t.Result.Item1, Type = question.Type, Class = question.Class }]; task.Wait(); task.Result.Name = question.QueryName; task.Result.TimeToLive = Math.Min(task.Result.TimeToLive, t.Result.Item2); return(task.Result); })); } } else { answers.Add(Handler.GetFirstConfigurationPacket(query).ContinueWith(t => new DnsResourceRecord { Name = question.QueryName, Type = question.Type, Class = question.Class, TimeToLive = t.Result.Item2, Data = t.Result.Item1 })); } } else { answers.Add(Cache[question]); } Console.WriteLine("Query for {0}", question.QueryName); } Task.WhenAll(answers).ContinueWith(t => { byte[] pkt = new DnsPacket { Identification = packet.Identification, QueryResponse = true, Questions = packet.Questions, Answers = t.Result }.ToByteArray(); Listener.Send(pkt, pkt.Length, endPoint); }); }