-
Notifications
You must be signed in to change notification settings - Fork 922
Expand file tree
/
Copy pathDatagramDnsQueryEncoder.cs
More file actions
137 lines (120 loc) · 4.87 KB
/
DatagramDnsQueryEncoder.cs
File metadata and controls
137 lines (120 loc) · 4.87 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
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;
using System.Net;
namespace DotNetty.Codecs.DNS
{
/// <summary>
/// Defines the <see cref="DatagramDnsQueryEncoder" />
/// </summary>
public class DatagramDnsQueryEncoder : MessageToMessageEncoder<IAddressedEnvelope<IDnsQuery>>
{
#region 字段
/// <summary>
/// Defines the recordEncoder
/// </summary>
private readonly IDnsRecordEncoder recordEncoder;
#endregion 字段
#region 构造函数
/// <summary>
/// Initializes a new instance of the <see cref="DatagramDnsQueryEncoder"/> class.
/// </summary>
public DatagramDnsQueryEncoder() : this(new DefaultDnsRecordEncoder())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DatagramDnsQueryEncoder"/> class.
/// </summary>
/// <param name="recordEncoder">The recordEncoder<see cref="IDnsRecordEncoder"/></param>
public DatagramDnsQueryEncoder(IDnsRecordEncoder recordEncoder)
{
this.recordEncoder = recordEncoder ?? throw new ArgumentNullException(nameof(recordEncoder));
}
#endregion 构造函数
#region 方法
/// <summary>
/// The Encode
/// </summary>
/// <param name="context">The context<see cref="IChannelHandlerContext"/></param>
/// <param name="message">The message<see cref="IAddressedEnvelope{IDnsQuery}"/></param>
/// <param name="output">The output<see cref="List{object}"/></param>
protected override void Encode(IChannelHandlerContext context, IAddressedEnvelope<IDnsQuery> message, List<object> output)
{
EndPoint recipient = message.Recipient;
IDnsQuery query = message.Content;
IByteBuffer buffer = AllocateBuffer(context, message);
bool success = false;
try
{
EncodeHeader(query, buffer);
EncodeQuestions(query, buffer);
EncodeRecords(query, DnsSection.ADDITIONAL, buffer);
success = true;
}
finally
{
if (!success)
buffer.Release();
}
output.Add(new DatagramPacket(buffer, recipient, null));
}
/// <summary>
/// The AllocateBuffer
/// </summary>
/// <param name="ctx">The ctx<see cref="IChannelHandlerContext"/></param>
/// <param name="message">The message<see cref="IAddressedEnvelope{IDnsQuery}"/></param>
/// <returns>The <see cref="IByteBuffer"/></returns>
private IByteBuffer AllocateBuffer(IChannelHandlerContext ctx,
IAddressedEnvelope<IDnsQuery> message) => ctx.Allocator.Buffer(1024);
/// <summary>
/// The EncodeHeader
/// </summary>
/// <param name="query">The query<see cref="IDnsQuery"/></param>
/// <param name="buffer">The buffer<see cref="IByteBuffer"/></param>
private void EncodeHeader(IDnsQuery query, IByteBuffer buffer)
{
buffer.WriteShort(query.Id);
int flags = 0;
flags |= (query.OpCode.ByteValue & 0xFF) << 14;
if (query.IsRecursionDesired)
flags |= 1 << 8;
buffer.WriteShort(flags);
buffer.WriteShort(query.Count(DnsSection.QUESTION));
buffer.WriteShort(0);
buffer.WriteShort(0);
buffer.WriteShort(query.Count(DnsSection.ADDITIONAL));
}
/// <summary>
/// The EncodeQuestions
/// </summary>
/// <param name="query">The query<see cref="IDnsQuery"/></param>
/// <param name="buffer">The buffer<see cref="IByteBuffer"/></param>
private void EncodeQuestions(IDnsQuery query, IByteBuffer buffer)
{
int count = query.Count(DnsSection.QUESTION);
for (int i = 0; i < count; i++)
{
recordEncoder.EncodeQuestion(query.GetRecord<IDnsQuestion>(DnsSection.QUESTION, i), buffer);
}
}
/// <summary>
/// The EncodeRecords
/// </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>
private void EncodeRecords(IDnsQuery query, DnsSection section, IByteBuffer buffer)
{
int count = query.Count(section);
for (int i = 0; i < count; i++)
{
recordEncoder.EncodeRecord(query.GetRecord<IDnsRecord>(section, i), buffer);
}
}
#endregion 方法
}
}