-
Notifications
You must be signed in to change notification settings - Fork 922
Expand file tree
/
Copy pathDatagramDnsQueryDecoder.cs
More file actions
138 lines (119 loc) · 4.94 KB
/
DatagramDnsQueryDecoder.cs
File metadata and controls
138 lines (119 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
using DotNetty.Buffers;
using DotNetty.Codecs.DNS.Messages;
using DotNetty.Codecs.DNS.Records;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;
using System;
using System.Collections.Generic;
namespace DotNetty.Codecs.DNS
{
/// <summary>
/// Defines the <see cref="DatagramDnsQueryDecoder" />
/// </summary>
public class DatagramDnsQueryDecoder : MessageToMessageDecoder<DatagramPacket>
{
#region 字段
/// <summary>
/// Defines the recordDecoder
/// </summary>
private readonly IDnsRecordDecoder recordDecoder;
#endregion 字段
#region 构造函数
/// <summary>
/// Initializes a new instance of the <see cref="DatagramDnsQueryDecoder"/> class.
/// </summary>
public DatagramDnsQueryDecoder() : this(new DefaultDnsRecordDecoder())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DatagramDnsQueryDecoder"/> class.
/// </summary>
/// <param name="recordDecoder">The recordDecoder<see cref="IDnsRecordDecoder"/></param>
public DatagramDnsQueryDecoder(IDnsRecordDecoder recordDecoder)
{
this.recordDecoder = recordDecoder ?? throw new ArgumentNullException(nameof(recordDecoder));
}
#endregion 构造函数
#region 方法
/// <summary>
/// The Decode
/// </summary>
/// <param name="context">The context<see cref="IChannelHandlerContext"/></param>
/// <param name="message">The message<see cref="DatagramPacket"/></param>
/// <param name="output">The output<see cref="List{object}"/></param>
protected override void Decode(IChannelHandlerContext context, DatagramPacket message, List<object> output)
{
IByteBuffer buffer = message.Content;
IDnsQuery query = NewQuery(message, buffer);
bool success = false;
try
{
int questionCount = buffer.ReadUnsignedShort();
int answerCount = buffer.ReadUnsignedShort();
int authorityRecordCount = buffer.ReadUnsignedShort();
int additionalRecordCount = buffer.ReadUnsignedShort();
DecodeQuestions(query, buffer, questionCount);
DecodeRecords(query, DnsSection.ANSWER, buffer, answerCount);
DecodeRecords(query, DnsSection.AUTHORITY, buffer, authorityRecordCount);
DecodeRecords(query, DnsSection.ADDITIONAL, buffer, additionalRecordCount);
output.Add(query);
success = true;
}
finally
{
if (!success)
query.Release();
}
}
/// <summary>
/// The NewQuery
/// </summary>
/// <param name="packet">The packet<see cref="DatagramPacket"/></param>
/// <param name="buffer">The buffer<see cref="IByteBuffer"/></param>
/// <returns>The <see cref="IDnsQuery"/></returns>
private static IDnsQuery NewQuery(DatagramPacket packet, IByteBuffer buffer)
{
int id = buffer.ReadUnsignedShort();
int flags = buffer.ReadUnsignedShort();
if (flags >> 15 == 1)
throw new CorruptedFrameException("not a query");
IDnsQuery query = new DatagramDnsQuery(
packet.Sender, packet.Recipient, id,
DnsOpCode.From((byte)(flags >> 11 & 0xf)));
query.IsRecursionDesired = (flags >> 8 & 1) == 1;
query.Z = flags >> 4 & 0x7;
return query;
}
/// <summary>
/// The DecodeQuestions
/// </summary>
/// <param name="query">The query<see cref="IDnsQuery"/></param>
/// <param name="buffer">The buffer<see cref="IByteBuffer"/></param>
/// <param name="questionCount">The questionCount<see cref="int"/></param>
private void DecodeQuestions(IDnsQuery query, IByteBuffer buffer, int questionCount)
{
for (int i = questionCount; i > 0; i--)
{
query.AddRecord(DnsSection.QUESTION, recordDecoder.DecodeQuestion(buffer));
}
}
/// <summary>
/// The DecodeRecords
/// </summary>
/// <param name="query">The query<see cref="IDnsQuery"/></param>
/// <param name="section">The section<see cref="DnsSection"/></param>
/// <param name="buffer">The buffer<see cref="IByteBuffer"/></param>
/// <param name="count">The count<see cref="int"/></param>
private void DecodeRecords(IDnsQuery query, DnsSection section, IByteBuffer buffer, int count)
{
for (int i = count; i > 0; i--)
{
IDnsRecord r = recordDecoder.DecodeRecord(buffer);
if (r == null)
break;
query.AddRecord(section, r);
}
}
#endregion 方法
}
}