Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
538 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsQueryDecoder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright 2015 The Netty Project | ||
* | ||
* The Netty Project licenses this file to you under the Apache License, | ||
* version 2.0 (the "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at: | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
package io.netty.handler.codec.dns; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
import io.netty.channel.ChannelHandler; | ||
import io.netty.channel.ChannelHandlerContext; | ||
import io.netty.channel.socket.DatagramPacket; | ||
import io.netty.handler.codec.CorruptedFrameException; | ||
import io.netty.handler.codec.MessageToMessageDecoder; | ||
|
||
import java.net.InetSocketAddress; | ||
import java.util.List; | ||
|
||
import static io.netty.util.internal.ObjectUtil.checkNotNull; | ||
|
||
/** | ||
* Decodes a {@link DatagramPacket} into a {@link DatagramDnsQuery}. | ||
*/ | ||
@ChannelHandler.Sharable | ||
public class DatagramDnsQueryDecoder extends MessageToMessageDecoder<DatagramPacket> { | ||
|
||
private final DnsRecordDecoder recordDecoder; | ||
|
||
/** | ||
* Creates a new decoder with {@linkplain DnsRecordDecoder#DEFAULT the default record decoder}. | ||
*/ | ||
public DatagramDnsQueryDecoder() { | ||
this(DnsRecordDecoder.DEFAULT); | ||
} | ||
|
||
/** | ||
* Creates a new decoder with the specified {@code recordDecoder}. | ||
*/ | ||
public DatagramDnsQueryDecoder(DnsRecordDecoder recordDecoder) { | ||
this.recordDecoder = checkNotNull(recordDecoder, "recordDecoder"); | ||
} | ||
|
||
@Override | ||
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List<Object> out) throws Exception { | ||
final ByteBuf buf = packet.content(); | ||
|
||
final DnsQuery query = newQuery(packet, buf); | ||
boolean success = false; | ||
try { | ||
final int questionCount = buf.readUnsignedShort(); | ||
final int answerCount = buf.readUnsignedShort(); | ||
final int authorityRecordCount = buf.readUnsignedShort(); | ||
final int additionalRecordCount = buf.readUnsignedShort(); | ||
|
||
decodeQuestions(query, buf, questionCount); | ||
decodeRecords(query, DnsSection.ANSWER, buf, answerCount); | ||
decodeRecords(query, DnsSection.AUTHORITY, buf, authorityRecordCount); | ||
decodeRecords(query, DnsSection.ADDITIONAL, buf, additionalRecordCount); | ||
|
||
out.add(query); | ||
success = true; | ||
} finally { | ||
if (!success) { | ||
query.release(); | ||
} | ||
} | ||
} | ||
|
||
private static DnsQuery newQuery(DatagramPacket packet, ByteBuf buf) { | ||
final int id = buf.readUnsignedShort(); | ||
|
||
final int flags = buf.readUnsignedShort(); | ||
if (flags >> 15 == 1) { | ||
throw new CorruptedFrameException("not a query"); | ||
} | ||
final DnsQuery query = | ||
new DatagramDnsQuery( | ||
packet.sender(), | ||
packet.recipient(), | ||
id, | ||
DnsOpCode.valueOf((byte) (flags >> 11 & 0xf))); | ||
query.setRecursionDesired((flags >> 8 & 1) == 1); | ||
query.setZ(flags >> 4 & 0x7); | ||
return query; | ||
} | ||
|
||
private void decodeQuestions(DnsQuery query, ByteBuf buf, int questionCount) throws Exception { | ||
for (int i = questionCount; i > 0; i--) { | ||
query.addRecord(DnsSection.QUESTION, recordDecoder.decodeQuestion(buf)); | ||
} | ||
} | ||
|
||
private void decodeRecords( | ||
DnsQuery query, DnsSection section, ByteBuf buf, int count) throws Exception { | ||
for (int i = count; i > 0; i--) { | ||
final DnsRecord r = recordDecoder.decodeRecord(buf); | ||
if (r == null) { | ||
// Truncated response | ||
break; | ||
} | ||
|
||
query.addRecord(section, r); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
netty-bp/codec-dns/src/main/java/io/netty/handler/codec/dns/DatagramDnsResponseEncoder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/* | ||
* Copyright 2015 The Netty Project | ||
* | ||
* The Netty Project licenses this file to you under the Apache License, | ||
* version 2.0 (the "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at: | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
package io.netty.handler.codec.dns; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
import io.netty.channel.AddressedEnvelope; | ||
import io.netty.channel.ChannelHandler; | ||
import io.netty.channel.ChannelHandlerContext; | ||
import io.netty.channel.socket.DatagramPacket; | ||
import io.netty.handler.codec.MessageToMessageEncoder; | ||
|
||
import java.net.InetSocketAddress; | ||
import java.util.List; | ||
|
||
import static io.netty.util.internal.ObjectUtil.checkNotNull; | ||
|
||
/** | ||
* Encodes a {@link DatagramDnsResponse} (or an {@link AddressedEnvelope} of {@link DnsResponse}} into a | ||
* {@link DatagramPacket}. | ||
*/ | ||
@ChannelHandler.Sharable | ||
public class DatagramDnsResponseEncoder | ||
extends MessageToMessageEncoder<AddressedEnvelope<DnsResponse, InetSocketAddress>> { | ||
|
||
private final DnsRecordEncoder recordEncoder; | ||
|
||
/** | ||
* Creates a new encoder with {@linkplain DnsRecordEncoder#DEFAULT the default record encoder}. | ||
*/ | ||
public DatagramDnsResponseEncoder() { | ||
this(DnsRecordEncoder.DEFAULT); | ||
} | ||
|
||
/** | ||
* Creates a new encoder with the specified {@code recordEncoder}. | ||
*/ | ||
public DatagramDnsResponseEncoder(DnsRecordEncoder recordEncoder) { | ||
this.recordEncoder = checkNotNull(recordEncoder, "recordEncoder"); | ||
} | ||
|
||
@Override | ||
protected void encode(ChannelHandlerContext ctx, | ||
AddressedEnvelope<DnsResponse, InetSocketAddress> in, List<Object> out) throws Exception { | ||
|
||
final InetSocketAddress recipient = in.recipient(); | ||
final DnsResponse response = in.content(); | ||
final ByteBuf buf = allocateBuffer(ctx, in); | ||
|
||
boolean success = false; | ||
try { | ||
encodeHeader(response, buf); | ||
encodeQuestions(response, buf); | ||
encodeRecords(response, DnsSection.ANSWER, buf); | ||
encodeRecords(response, DnsSection.AUTHORITY, buf); | ||
encodeRecords(response, DnsSection.ADDITIONAL, buf); | ||
success = true; | ||
} finally { | ||
if (!success) { | ||
buf.release(); | ||
} | ||
} | ||
|
||
out.add(new DatagramPacket(buf, recipient, null)); | ||
} | ||
|
||
/** | ||
* Allocate a {@link ByteBuf} which will be used for constructing a datagram packet. | ||
* Sub-classes may override this method to return a {@link ByteBuf} with a perfect matching initial capacity. | ||
*/ | ||
protected ByteBuf allocateBuffer( | ||
ChannelHandlerContext ctx, | ||
@SuppressWarnings("unused") AddressedEnvelope<DnsResponse, InetSocketAddress> msg) throws Exception { | ||
return ctx.alloc().ioBuffer(1024); | ||
} | ||
|
||
/** | ||
* Encodes the header that is always 12 bytes long. | ||
* | ||
* @param response the response header being encoded | ||
* @param buf the buffer the encoded data should be written to | ||
*/ | ||
private static void encodeHeader(DnsResponse response, ByteBuf buf) { | ||
buf.writeShort(response.id()); | ||
int flags = 32768; | ||
flags |= (response.opCode().byteValue() & 0xFF) << 11; | ||
if (response.isAuthoritativeAnswer()) { | ||
flags |= 1 << 10; | ||
} | ||
if (response.isTruncated()) { | ||
flags |= 1 << 9; | ||
} | ||
if (response.isRecursionDesired()) { | ||
flags |= 1 << 8; | ||
} | ||
if (response.isRecursionAvailable()) { | ||
flags |= 1 << 7; | ||
} | ||
flags |= response.z() << 4; | ||
flags |= response.code().intValue(); | ||
buf.writeShort(flags); | ||
buf.writeShort(response.count(DnsSection.QUESTION)); | ||
buf.writeShort(response.count(DnsSection.ANSWER)); | ||
buf.writeShort(response.count(DnsSection.AUTHORITY)); | ||
buf.writeShort(response.count(DnsSection.ADDITIONAL)); | ||
} | ||
|
||
private void encodeQuestions(DnsResponse response, ByteBuf buf) throws Exception { | ||
final int count = response.count(DnsSection.QUESTION); | ||
for (int i = 0; i < count; i++) { | ||
recordEncoder.encodeQuestion((DnsQuestion) response.recordAt(DnsSection.QUESTION, i), buf); | ||
} | ||
} | ||
|
||
private void encodeRecords(DnsResponse response, DnsSection section, ByteBuf buf) throws Exception { | ||
final int count = response.count(section); | ||
for (int i = 0; i < count; i++) { | ||
recordEncoder.encodeRecord(response.recordAt(section, i), buf); | ||
} | ||
} | ||
} |
Oops, something went wrong.