205 lines
6.2 KiB
C#
205 lines
6.2 KiB
C#
using Unosquare.Swan.Formatters;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace Unosquare.Swan.Networking {
|
|
/// <summary>
|
|
/// DnsClient Response inner class.
|
|
/// </summary>
|
|
internal partial class DnsClient {
|
|
public class DnsClientResponse : IDnsResponse {
|
|
private readonly DnsResponse _response;
|
|
private readonly Byte[] _message;
|
|
|
|
internal DnsClientResponse(DnsClientRequest request, DnsResponse response, Byte[] message) {
|
|
this.Request = request;
|
|
|
|
this._message = message;
|
|
this._response = response;
|
|
}
|
|
|
|
public DnsClientRequest Request {
|
|
get;
|
|
}
|
|
|
|
public Int32 Id {
|
|
get => this._response.Id;
|
|
set {
|
|
}
|
|
}
|
|
|
|
public IList<IDnsResourceRecord> AnswerRecords => this._response.AnswerRecords;
|
|
|
|
public IList<IDnsResourceRecord> AuthorityRecords =>
|
|
new ReadOnlyCollection<IDnsResourceRecord>(this._response.AuthorityRecords);
|
|
|
|
public IList<IDnsResourceRecord> AdditionalRecords =>
|
|
new ReadOnlyCollection<IDnsResourceRecord>(this._response.AdditionalRecords);
|
|
|
|
public Boolean IsRecursionAvailable {
|
|
get => this._response.IsRecursionAvailable;
|
|
set {
|
|
}
|
|
}
|
|
|
|
public Boolean IsAuthorativeServer {
|
|
get => this._response.IsAuthorativeServer;
|
|
set {
|
|
}
|
|
}
|
|
|
|
public Boolean IsTruncated {
|
|
get => this._response.IsTruncated;
|
|
set {
|
|
}
|
|
}
|
|
|
|
public DnsOperationCode OperationCode {
|
|
get => this._response.OperationCode;
|
|
set {
|
|
}
|
|
}
|
|
|
|
public DnsResponseCode ResponseCode {
|
|
get => this._response.ResponseCode;
|
|
set {
|
|
}
|
|
}
|
|
|
|
public IList<DnsQuestion> Questions => new ReadOnlyCollection<DnsQuestion>(this._response.Questions);
|
|
|
|
public Int32 Size => this._message.Length;
|
|
|
|
public Byte[] ToArray() => this._message;
|
|
|
|
public override String ToString() => this._response.ToString();
|
|
}
|
|
|
|
public class DnsResponse : IDnsResponse {
|
|
private DnsHeader _header;
|
|
|
|
public DnsResponse(
|
|
DnsHeader header,
|
|
IList<DnsQuestion> questions,
|
|
IList<IDnsResourceRecord> answers,
|
|
IList<IDnsResourceRecord> authority,
|
|
IList<IDnsResourceRecord> additional) {
|
|
this._header = header;
|
|
this.Questions = questions;
|
|
this.AnswerRecords = answers;
|
|
this.AuthorityRecords = authority;
|
|
this.AdditionalRecords = additional;
|
|
}
|
|
|
|
public IList<DnsQuestion> Questions {
|
|
get;
|
|
}
|
|
|
|
public IList<IDnsResourceRecord> AnswerRecords {
|
|
get;
|
|
}
|
|
|
|
public IList<IDnsResourceRecord> AuthorityRecords {
|
|
get;
|
|
}
|
|
|
|
public IList<IDnsResourceRecord> AdditionalRecords {
|
|
get;
|
|
}
|
|
|
|
public Int32 Id {
|
|
get => this._header.Id;
|
|
set => this._header.Id = value;
|
|
}
|
|
|
|
public Boolean IsRecursionAvailable {
|
|
get => this._header.RecursionAvailable;
|
|
set => this._header.RecursionAvailable = value;
|
|
}
|
|
|
|
public Boolean IsAuthorativeServer {
|
|
get => this._header.AuthorativeServer;
|
|
set => this._header.AuthorativeServer = value;
|
|
}
|
|
|
|
public Boolean IsTruncated {
|
|
get => this._header.Truncated;
|
|
set => this._header.Truncated = value;
|
|
}
|
|
|
|
public DnsOperationCode OperationCode {
|
|
get => this._header.OperationCode;
|
|
set => this._header.OperationCode = value;
|
|
}
|
|
|
|
public DnsResponseCode ResponseCode {
|
|
get => this._header.ResponseCode;
|
|
set => this._header.ResponseCode = value;
|
|
}
|
|
|
|
public Int32 Size
|
|
=> this._header.Size +
|
|
this.Questions.Sum(q => q.Size) +
|
|
this.AnswerRecords.Sum(a => a.Size) +
|
|
this.AuthorityRecords.Sum(a => a.Size) +
|
|
this.AdditionalRecords.Sum(a => a.Size);
|
|
|
|
public static DnsResponse FromArray(Byte[] message) {
|
|
DnsHeader header = DnsHeader.FromArray(message);
|
|
Int32 offset = header.Size;
|
|
|
|
if(!header.Response || header.QuestionCount == 0) {
|
|
throw new ArgumentException("Invalid response message");
|
|
}
|
|
|
|
return header.Truncated
|
|
? new DnsResponse(header,
|
|
DnsQuestion.GetAllFromArray(message, offset, header.QuestionCount),
|
|
new List<IDnsResourceRecord>(),
|
|
new List<IDnsResourceRecord>(),
|
|
new List<IDnsResourceRecord>())
|
|
: new DnsResponse(header,
|
|
DnsQuestion.GetAllFromArray(message, offset, header.QuestionCount, out offset),
|
|
DnsResourceRecordFactory.GetAllFromArray(message, offset, header.AnswerRecordCount, out offset),
|
|
DnsResourceRecordFactory.GetAllFromArray(message, offset, header.AuthorityRecordCount, out offset),
|
|
DnsResourceRecordFactory.GetAllFromArray(message, offset, header.AdditionalRecordCount, out _));
|
|
}
|
|
|
|
public Byte[] ToArray() {
|
|
this.UpdateHeader();
|
|
MemoryStream result = new MemoryStream(this.Size);
|
|
|
|
_ = result
|
|
.Append(this._header.ToArray())
|
|
.Append(this.Questions.Select(q => q.ToArray()))
|
|
.Append(this.AnswerRecords.Select(a => a.ToArray()))
|
|
.Append(this.AuthorityRecords.Select(a => a.ToArray()))
|
|
.Append(this.AdditionalRecords.Select(a => a.ToArray()));
|
|
|
|
return result.ToArray();
|
|
}
|
|
|
|
public override String ToString() {
|
|
this.UpdateHeader();
|
|
|
|
return Json.SerializeOnly(
|
|
this,
|
|
true,
|
|
nameof(this.Questions),
|
|
nameof(this.AnswerRecords),
|
|
nameof(this.AuthorityRecords),
|
|
nameof(this.AdditionalRecords));
|
|
}
|
|
|
|
private void UpdateHeader() {
|
|
this._header.QuestionCount = this.Questions.Count;
|
|
this._header.AnswerRecordCount = this.AnswerRecords.Count;
|
|
this._header.AuthorityRecordCount = this.AuthorityRecords.Count;
|
|
this._header.AdditionalRecordCount = this.AdditionalRecords.Count;
|
|
}
|
|
}
|
|
}
|
|
} |