internal static ResourceRecord ReadFrom(PacketReader reader) { string name = reader.ReadName(); RecordType type = (RecordType)reader.ReadUShort(); RecordClass rClass = (RecordClass)reader.ReadUShort(); DateTime expiry = DateTime.UtcNow + TimeSpan.FromSeconds(reader.ReadInt()); switch (type) { case RecordType.Pointer: return new PointerRecord(name, type, rClass, expiry, reader); case RecordType.CanonicalName: return new CanonicalNameRecord(name, type, rClass, expiry, reader); case RecordType.Address: return new IP4AddressRecord(name, type, rClass, expiry, reader); case RecordType.Text: return new TextRecord(name, type, rClass, expiry, reader); case RecordType.Service: return new ServiceRecord(name, type, rClass, expiry, reader); default: int len = reader.ReadUShort(); reader.Position += len; return new ResourceRecord(name, type, rClass, expiry); } }
public static Message Read(PacketReader reader) { Message result = new Message(); result.TransactionId = reader.ReadUShort(); result.Flags = new MessageFlags(reader.ReadUShort()); ushort questions = reader.ReadUShort(); ushort answers = reader.ReadUShort(); ushort authorityRecords = reader.ReadUShort(); ushort additionalRecords = reader.ReadUShort(); for (int i = 0; i < questions; ++i) { result.Questions.Add(Question.ReadFrom(reader)); } for (int i = 0; i < answers; ++i) { result.Answers.Add(ResourceRecord.ReadFrom(reader)); } for (int i = 0; i < authorityRecords; ++i) { result.AuthorityRecords.Add(ResourceRecord.ReadFrom(reader)); } for (int i = 0; i < additionalRecords; ++i) { result.AdditionalRecords.Add(ResourceRecord.ReadFrom(reader)); } return result; }
internal IP4AddressRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader) : base(name, type, rClass, expiry) { ushort dataLen = reader.ReadUShort(); int pos = reader.Position; _address = new IPAddress(reader.ReadBytes(dataLen)); reader.Position = pos + dataLen; }
internal PointerRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader) : base(name, type, rClass, expiry) { ushort dataLen = reader.ReadUShort(); int pos = reader.Position; _targetName = reader.ReadName(); reader.Position = pos + dataLen; }
internal ServiceRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader) : base(name, type, rClass, expiry) { ushort dataLen = reader.ReadUShort(); int pos = reader.Position; _priority = reader.ReadUShort(); _weight = reader.ReadUShort(); _port = reader.ReadUShort(); _target = reader.ReadName(); reader.Position = pos + dataLen; }
internal TextRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader) : base(name, type, rClass, expiry) { _values = new Dictionary<string, byte[]>(); ushort dataLen = reader.ReadUShort(); int pos = reader.Position; while (reader.Position < pos + dataLen) { int valueLen = reader.ReadByte(); byte[] valueBinary = reader.ReadBytes(valueLen); StoreValue(valueBinary); } }
private void ReceiveCallback(IAsyncResult ar) { try { IPEndPoint sender = null; byte[] packetBytes; lock (_udpClient) { packetBytes = _udpClient.EndReceive(ar, ref sender); } PacketReader reader = new PacketReader(packetBytes); Message msg = Message.Read(reader); lock (_transactions) { Transaction transaction; _transactions.TryGetValue(msg.TransactionId, out transaction); foreach (var answer in msg.AdditionalRecords) { AddRecord(_cache, answer); } foreach (var answer in msg.Answers) { if (transaction != null) { transaction.Answers.Add(answer); } AddRecord(_cache, answer); } } } finally { lock (_udpClient) { _udpClient.BeginReceive(ReceiveCallback, null); } } }
/// <summary> /// Looks up a record in DNS. /// </summary> /// <param name="name">The name to lookup</param> /// <param name="type">The type of record requested</param> /// <returns>The records returned by the DNS server, if any</returns> public override ResourceRecord[] Lookup(string name, RecordType type) { ushort transactionId = _nextTransId++; string normName = NormalizeDomainName(name); using (UdpClient udpClient = new UdpClient(0)) { IAsyncResult result = udpClient.BeginReceive(null, null); PacketWriter writer = new PacketWriter(1800); Message msg = new Message(); msg.TransactionId = transactionId; msg.Flags = new MessageFlags(false, OpCode.Query, false, false, false, false, ResponseCode.Success); msg.Questions.Add(new Question() { Name = normName, Type = type, Class = RecordClass.Internet }); msg.WriteTo(writer); byte[] msgBytes = writer.GetBytes(); foreach (var server in _servers) { udpClient.Send(msgBytes, msgBytes.Length, server); } for (int i = 0; i < maxRetries; ++i) { DateTime now = DateTime.UtcNow; while (result.AsyncWaitHandle.WaitOne(Math.Max(responseTimeout - (DateTime.UtcNow - now).Milliseconds, 0))) { try { IPEndPoint sourceEndPoint = null; byte[] packetBytes = udpClient.EndReceive(result, ref sourceEndPoint); PacketReader reader = new PacketReader(packetBytes); Message response = Message.Read(reader); if (response.TransactionId == transactionId) { return response.Answers.ToArray(); } } catch { // Do nothing - bad packet (probably...) } } } } return null; }
internal CanonicalNameRecord(string name, RecordType type, RecordClass rClass, DateTime expiry, PacketReader reader) : base(name, type, rClass, expiry) { ushort dataLen = reader.ReadUShort(); int pos = reader.Position; _canonicalName = reader.ReadName(); reader.Position = pos + dataLen; }