using DnsClient.Protocol;
using System.Linq;
namespace DnsClient
{
///
/// The header section of a .
///
public class DnsResponseHeader
{
private readonly ushort _flags = 0;
///
/// Gets the number of additional records in the .
///
///
/// The number of additional records.
///
public int AdditionalCount { get; }
///
/// Gets the number of answer records in the .
///
///
/// The number of answer records.
///
public int AnswerCount { get; }
///
/// Gets a value indicating whether the future use flag is set.
///
///
/// The future use flag.
///
public bool FutureUse => HasFlag(DnsHeaderFlag.FutureUse);
///
/// Gets a value indicating whether this instance has authority answers.
///
///
/// true if this instance has authority answers; otherwise, false.
///
public bool HasAuthorityAnswer => HasFlag(DnsHeaderFlag.HasAuthorityAnswer);
internal DnsHeaderFlag HeaderFlags => (DnsHeaderFlag)_flags;
///
/// Gets the identifier.
///
///
/// The identifier.
///
public int Id { get; }
///
/// Gets a value indicating whether the result is authentic data.
///
///
/// true if the result is authentic; otherwise, false.
///
public bool IsAuthenticData => HasFlag(DnsHeaderFlag.IsAuthenticData);
///
/// Gets a value indicating whether checking is disabled.
///
///
/// true if checking is disabled; otherwise, false.
///
public bool IsCheckingDisabled => HasFlag(DnsHeaderFlag.IsCheckingDisabled);
///
/// Gets a value indicating whether this instance has a query.
///
///
/// true if this instance has a query; otherwise, false.
///
public bool HasQuery => HasFlag(DnsHeaderFlag.HasQuery);
///
/// Gets the number of name servers.
///
///
/// The number of name servers.
///
public int NameServerCount { get; }
///
/// Gets the kind of query defined by .
///
///
/// The query kind.
///
public DnsOpCode OPCode => (DnsOpCode)((DnsHeader.OPCodeMask & _flags) >> DnsHeader.OPCodeShift);
///
/// Gets the number of questions of the .
///
///
/// The number of questions.
///
public int QuestionCount { get; }
///
/// Gets a value indicating whether recursion is available on the DNS server.
///
///
/// true if recursion is available; otherwise, false.
///
public bool RecursionAvailable => HasFlag(DnsHeaderFlag.RecursionAvailable);
///
/// Gets the response code.
///
///
/// The response code.
///
public DnsResponseCode ResponseCode => (DnsResponseCode)(_flags & DnsHeader.RCodeMask);
///
/// Gets a value indicating whether the result was truncated.
///
///
/// true if the result was truncated; otherwise, false.
///
public bool ResultTruncated => HasFlag(DnsHeaderFlag.ResultTruncated);
///
/// Gets a value indicating whether recursion desired flag was set by the request.
///
///
/// true if the recursion desired flag was set; otherwise, false.
///
public bool RecursionDesired => HasFlag(DnsHeaderFlag.RecursionDesired);
///
/// Initializes a new instance of the class.
///
/// The identifier.
/// The flags.
/// The question count.
/// The answer count.
/// The additional count.
/// The server count.
public DnsResponseHeader(int id, ushort flags, int questionCount, int answerCount, int additionalCount, int serverCount)
{
Id = id;
_flags = flags;
QuestionCount = questionCount;
AnswerCount = answerCount;
AdditionalCount = additionalCount;
NameServerCount = serverCount;
}
private bool HasFlag(DnsHeaderFlag flag) => (HeaderFlags & flag) != 0;
///
/// Returns a that represents this instance.
///
///
/// A that represents this instance.
///
public override string ToString()
{
var head = $";; ->>HEADER<<- opcode: {OPCode}, status: {DnsResponseCodeText.GetErrorText(ResponseCode)}, id: {Id}";
var flags = new string[] {
HasQuery ? "qr" : "",
HasAuthorityAnswer ? "aa" : "",
RecursionDesired ? "rd" : "",
RecursionAvailable ? "ra" : "",
ResultTruncated ? "tc" : "",
IsCheckingDisabled ? "cd" : "",
IsAuthenticData ? "ad" : ""
};
var flagsString = string.Join(" ", flags.Where(p => p != ""));
return $"{head}\r\n;; flags: {flagsString}; QUERY: {QuestionCount}, " +
$"ANSWER: {AnswerCount}, AUTORITY: {NameServerCount}, ADDITIONAL: {AdditionalCount}";
}
}
}