コード例 #1
0
        public static IMessage Deserialize(ref byte[] Raw)
        {
            var Stream = new DnStream(ref Raw);

            var Message = new Message
            {
                ID = Stream.GetUShort(),

                MessageType         = Stream.GetBit().AsEnum <MessageType>(),
                OperationCode       = Stream.GetBits(4).AsEnum <OperationCode>(),
                AuthoritativeAnswer = Stream.GetBit().AsEnum <AuthoritativeAnswer>(),
                Truncated           = Stream.GetBit().AsBool(),
                RecursionDesired    = Stream.GetBit().AsBool(),

                RecursionAvailable = Stream.GetBit().AsBool(),
                Zero = Stream.GetBit(),
                AuthenticatedData = Stream.GetBit().AsBool(),
                CheckingDisabled  = Stream.GetBit().AsBool(),
                ResponseCode      = Stream.GetBits(4).AsEnum <ResponseCode>(),

                QuestionsCount  = Stream.GetUShort(),
                AnswersCount    = Stream.GetUShort(),
                AuthorityCount  = Stream.GetUShort(),
                AdditionalCount = Stream.GetUShort()
            };

            Message.Questions = GetQuestions(ref Stream, Message.QuestionsCount);
            Message.Answers   = GetAnswers(ref Stream, Message.AnswersCount);

            return(Message);
        }
コード例 #2
0
 private static void Set(ref DnStream Stream, ref Dictionary <string, ushort> Pointers, IEnumerable <IAnswer> Answers)
 {
     foreach (var Answer in Answers)
     {
         Set(ref Stream, ref Pointers, Answer);
     }
 }
コード例 #3
0
 private static void Set(ref DnStream Stream, ref Dictionary <string, ushort> Pointers, IEnumerable <IQuestion> Questions)
 {
     foreach (var Question in Questions)
     {
         Set(ref Stream, ref Pointers, Question);
     }
 }
コード例 #4
0
        private static void Set(ref DnStream Stream, ref Dictionary <string, ushort> Pointers, IQuestion Question)
        {
            Set(ref Stream, ref Pointers, Question.Domain);

            Stream.SetUShort((byte)Question.Type);

            Stream.SetUShort((byte)Question.Class);
        }
コード例 #5
0
 private static IRecord GetRecord(ref DnStream Stream, RecordType RecordType)
 {
     return(RecordType switch
     {
         RecordType.A => GetA(ref Stream),
         RecordType.CNAME => GetCNAME(ref Stream),
         RecordType.AAAA => GetAAAA(ref Stream),
         _ => throw new ArgumentOutOfRangeException(nameof(RecordType), RecordType, null)
     });
コード例 #6
0
        private static IDomain GetDomain(ref DnStream Stream)
        {
            var Domain = new Domain()
            {
                Labels = GetLabels(ref Stream),
            };

            return(Domain);
        }
コード例 #7
0
        private static IQuestion GetQuestion(ref DnStream Stream)
        {
            var Question = new Question()
            {
                Domain = GetDomain(ref Stream),
                Type   = Stream.GetUShort().AsEnum <RecordType>(),
                Class  = Stream.GetUShort().AsEnum <RecordClass>()
            };

            return(Question);
        }
コード例 #8
0
        private static IEnumerable <string> GetLabels(ref DnStream Stream)
        {
            var Labels = new List <string>();

            while (true)
            {
                var LabelType = Stream.GetBits(2).AsEnum <LabelType>();

                switch (LabelType)
                {
                case LabelType.Normal:
                {
                    var Length = Stream.GetBits(6);

                    if (Length == 0)
                    {
                        return(Labels);
                    }


                    var Label = Stream.GetString(Length);

                    Labels.Add(Label);

                    break;
                }

                case LabelType.Compressed:
                {
                    var Pointer = (ushort)(Stream.GetBits(6) + Stream.GetByte());

                    if (Pointer >= Stream.BytePosition - 2)
                    {
                        throw new ArgumentOutOfRangeException(nameof(Pointer), Pointer, "Compressed Label Infinite Loop Detected.");
                    }

                    var Position = Stream.BytePosition;

                    Stream.Seek(Pointer);

                    Labels.AddRange(GetLabels(ref Stream));

                    Stream.Seek(Position);

                    return(Labels);
                }

                default:
                    throw new ArgumentOutOfRangeException(nameof(LabelType), LabelType, null);
                }
            }
        }
コード例 #9
0
        private static IEnumerable <IAnswer> GetAnswers(ref DnStream Stream, ushort Count)
        {
            var Answers = new List <IAnswer>();

            do
            {
                var Answer = GetAnswer(ref Stream);

                Answers.Add(Answer);
            }while (Answers.Count < Count);

            return(Answers);
        }
コード例 #10
0
        private static IEnumerable <IQuestion> GetQuestions(ref DnStream Stream, ushort Count)
        {
            var Questions = new List <IQuestion>();

            do
            {
                var Question = GetQuestion(ref Stream);

                Questions.Add(Question);
            }while (Questions.Count < Count);

            return(Questions);
        }
コード例 #11
0
        private static void Set(ref DnStream Stream, ref Dictionary <string, ushort> Pointers, IAnswer Answer)
        {
            Set(ref Stream, ref Pointers, Answer.Domain);

            Stream.SetUShort((byte)Answer.Type);

            Stream.SetUShort((byte)Answer.Class);

            Stream.SetTimeSpan(Answer.TimeToLive);

            Stream.SetUShort(Answer.Length);

            Set(ref Stream, ref Pointers, Answer.Record);
        }
コード例 #12
0
        private static IAnswer GetAnswer(ref DnStream Stream)
        {
            var Answer = new Answer()
            {
                Domain     = GetDomain(ref Stream),
                Type       = Stream.GetUShort().AsEnum <RecordType>(),
                Class      = Stream.GetUShort().AsEnum <RecordClass>(),
                TimeToLive = Stream.GetTimeSpan(),
                Length     = Stream.GetUShort(),
            };

            Answer.Record = GetRecord(ref Stream, Answer.Type);

            return(Answer);
        }
コード例 #13
0
        public static byte[] Serialize(ref IMessage Message)
        {
            var Size = SizeOf(ref Message);

            var Stream = new DnStream(Size);

            var Pointers = new Dictionary <string, ushort>();

            Stream.SetUShort(Message.ID);

            Stream.SetBit((byte)Message.MessageType);
            Stream.SetBits(4, (byte)Message.OperationCode);
            Stream.SetBit((byte)Message.AuthoritativeAnswer);
            Stream.SetBit(Convert.ToByte(Message.Truncated));
            Stream.SetBit(Convert.ToByte(Message.RecursionDesired));

            Stream.SetBit(Convert.ToByte(Message.RecursionAvailable));
            Stream.SetBit(Message.Zero);
            Stream.SetBit(Convert.ToByte(Message.AuthenticatedData));
            Stream.SetBit(Convert.ToByte(Message.CheckingDisabled));
            Stream.SetBits(4, (byte)Message.ResponseCode);

            Stream.SetUShort((ushort)Message.Questions.Count());
            Stream.SetUShort((ushort)Message.Answers.Count());

            Stream.SetUShort((ushort)Message.Authority.Count());
            Stream.SetUShort((ushort)Message.Additional.Count());

            Set(ref Stream, ref Pointers, Message.Questions);

            Set(ref Stream, ref Pointers, Message.Answers);

            Set(ref Stream, ref Pointers, Message.Authority);

            Set(ref Stream, ref Pointers, Message.Additional);

            return(Stream.ToArray());
        }
コード例 #14
0
        private static void Set(ref DnStream Stream, ref Dictionary <string, ushort> Pointers, IEnumerable <string> Labels)
        {
            var Domain = string.Join('.', Labels);

            foreach (var Label in Labels)
            {
                var SubDomain = Domain.Substring(Domain.IndexOf(Label));

                if (Pointers.ContainsKey(SubDomain))
                {
                    Stream.SetBits(2, (byte)LabelType.Compressed);

                    var Bytes = new byte[2];

                    BinaryPrimitives.WriteUInt16BigEndian(Bytes, Pointers[SubDomain]);

                    Stream.SetBits(6, Bytes[0]);

                    Stream.SetByte(Bytes[1]);

                    return;
                }
                else
                {
                    Pointers.Add(SubDomain, Stream.BytePosition);

                    Stream.SetBits(2, (byte)LabelType.Normal);

                    Stream.SetBits(6, (byte)Label.Length);

                    Stream.SetString(Label);
                }
            }

            Stream.SetByte(0);
        }
コード例 #15
0
 private static void Set(ref DnStream Stream, ref Dictionary <string, ushort> Pointers, IDomain Domain)
 {
     Set(ref Stream, ref Pointers, Domain.Labels);
 }