using DNS.Protocol.ResourceRecords; using DNS.Protocol.Utils; using System; using System.Collections.Generic; using System.Linq; namespace DNS.Protocol { public class Request : IRequest { private static readonly Random RANDOM = new Random(); private IList questions; private Header header; private IList additional; public static Request FromArray(byte[] message) { Header header = Header.FromArray(message); int offset = header.Size; if (header.Response || header.QuestionCount == 0 || header.AnswerRecordCount + header.AuthorityRecordCount > 0 || header.ResponseCode != ResponseCode.NoError) { throw new ArgumentException("Invalid request message"); } return new Request(header, Question.GetAllFromArray(message, offset, header.QuestionCount, out offset), ResourceRecordFactory.GetAllFromArray(message, offset, header.AdditionalRecordCount, out offset)); } public Request(Header header, IList questions, IList additional) { this.header = header; this.questions = questions; this.additional = additional; } public Request() { this.questions = new List(); this.header = new Header(); this.additional = new List(); this.header.OperationCode = OperationCode.Query; this.header.Response = false; this.header.Id = RANDOM.Next(UInt16.MaxValue); } public Request(IRequest request) { this.header = new Header(); this.questions = new List(request.Questions); this.additional = new List(request.AdditionalRecords); this.header.Response = false; Id = request.Id; OperationCode = request.OperationCode; RecursionDesired = request.RecursionDesired; } public IList Questions { get { return questions; } } public IList AdditionalRecords { get { return additional; } } public int Size { get { return header.Size + questions.Sum(q => q.Size) + additional.Sum(a => a.Size); } } public int Id { get { return header.Id; } set { header.Id = value; } } public OperationCode OperationCode { get { return header.OperationCode; } set { header.OperationCode = value; } } public bool RecursionDesired { get { return header.RecursionDesired; } set { header.RecursionDesired = value; } } public byte[] ToArray() { UpdateHeader(); ByteStream result = new ByteStream(Size); result .Append(header.ToArray()) .Append(questions.Select(q => q.ToArray())) .Append(additional.Select(a => a.ToArray())); return result.ToArray(); } public override string ToString() { UpdateHeader(); return ObjectStringifier.New(this) .Add("Header", header) .Add("Questions", "AdditionalRecords") .ToString(); } private void UpdateHeader() { header.QuestionCount = questions.Count; header.AdditionalRecordCount = additional.Count; } } }