私はDNSクライアントを使用しています。 これをテストするために、私は期待しているDnsRecordsを返すNettyを持つ単純なDNSサーバーを書きました。Netty DNS Answer Sectionが正しくデコードされていません
final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
final EventLoop next = nioEventLoopGroup.next();
final DnsNameResolverBuilder dnsNameResolverBuilder = new
DnsNameResolverBuilder(next).channelFactory(new ChannelFactory<DatagramChannel>() {
@Override
public DatagramChannel newChannel() {
return new NioDatagramChannel();
}
}).queryTimeoutMillis(100000).nameServerAddresses(new
DnsServerAddresses() {
@Override
public DnsServerAddressStream stream() {
return new DnsServerAddressStream() {
@Override
public InetSocketAddress next() {
return new InetSocketAddress("127.0.0.1",
TEST_DNS_SD_SERVER_PORT);
}
};
}
});
final DnsNameResolver build = dnsNameResolverBuilder.build();
final DefaultDnsQuestion defaultDnsQuestion = new
DefaultDnsQuestion(TEST_BASE_RECORD_NAME, DnsRecordType.PTR);
build.query(defaultDnsQuestion).addListener(new GenericFutureListener<Future<? super AddressedEnvelope<DnsResponse, InetSocketAddress>>>() {
@Override
public void operationComplete(final Future<? super AddressedEnvelope<DnsResponse, InetSocketAddress>> future) throws Exception {
final AddressedEnvelope<DnsResponse, InetSocketAddress> answer = (AddressedEnvelope<DnsResponse, InetSocketAddress>) future.get();
final DnsResponse content = answer.content();
final int count = content.count(DnsSection.ANSWER);
for (int i = 0; i < count; i++) {
final DnsRecord recordAt = content.recordAt(DnsSection.ANSWER, i);
System.out.println(recordAt);
}
}
}).await();
Thread.sleep(Long.MAX_VALUE);
TEST_BASE_RECORD_NAME
が応答セクションで3 DnsPtrRecordsを含むレコードです:
は、ここに私のクライアントコードです。 LocalDNSSDHandlerの (パート:)
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
final DatagramDnsQuery query = (DatagramDnsQuery) msg;
DatagramDnsResponse defaultDnsResponse = null;
try {
final DnsRecord recordAt = query.recordAt(DnsSection.QUESTION);
final Name name = Name.fromString(recordAt.name(), Name.root);
final DnsEntryKey dnsEntryKey =
new DnsEntryKey(name, recordAt.type().intValue());
final List<Record> list =
LocalTestServer.this.getDnsEntries().get(dnsEntryKey);
defaultDnsResponse =
new DatagramDnsResponse(query.recipient(),
query.sender(), query.id());
defaultDnsResponse.addRecord(DnsSection.QUESTION, recordAt);
for (final Record record : list) {
final ByteBuf buffer = ctx.alloc().buffer();
buffer.writeBytes(record.toWireCanonical());
defaultDnsResponse.addRecord(DnsSection.ANSWER, new
DefaultDnsRawRecord(record.getName().toString(),
this.fromRecord(record), Long.MAX_VALUE, buffer));
}
} catch (final Exception e) {
}
ctx.writeAndFlush(defaultDnsResponse);
}
サーバーdefiniesはChannelHandler
を次TEST_DNS_SD_SERVER_PORT
の後ろ
は、私は次のように要求を処理する別々のスレッドでDNS-Serverを実行しています
public void initChannel(final DatagramChannel ch) throws Exception {
ch.pipeline().addLast(new DatagramDnsResponseEncoder());
ch.pipeline().addLast(new DatagramDnsQueryDecoder());
ch.pipeline().addLast(new LocalDNSSDHandler());
}
クライアントで期待していることは、私が期待している3つのDnsPtrRecordsについて3 System.out.println
を見ることです。しかし、私が得るのは1だけです。
私はそれをデバッグすると、私は見ることができます、エンコード/デコードのサーバー側でうまく動作します。 しかし、クライアントが(私は期待していたデータが含まれています)correspondending ByteBuf
をデコードするとき、それは単に1つだけのレコードを返し、コード内で、この時点で2他をスキップ:
(DatagramDnsResponseDecoder)
@Override
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet,
List<Object> out) throws Exception {
final ByteBuf buf = packet.content();
final DnsResponse response = newResponse(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(response, buf, questionCount);
decodeRecords(response, DnsSection.ANSWER, buf, answerCount);
decodeRecords(response, DnsSection.AUTHORITY, buf,
authorityRecordCount);
decodeRecords(response, DnsSection.ADDITIONAL, buf,
additionalRecordCount);
...//source code of netty 4.1, trimmed
answerCount
は私が期待しているとおり3です。
decodeRecords(response, DnsSection.ANSWER, buf, answerCount);
が呼び出されたときしかし、それは私が
in.setIndex(offset, offset + length);
(DefaultDnsRecordDecoder)
protected DnsRecord decodeRecord(
String name, DnsRecordType type, int dnsClass, long timeToLive,
ByteBuf in, int offset, int length) throws Exception {
if (type == DnsRecordType.PTR) {
in.setIndex(offset, offset + length);
return
new DefaultDnsPtrRecord(name, dnsClass, timeToLive, decodeName0(in));
}
return new DefaultDnsRawRecord(
name, type, dnsClass, timeToLive,
in.retainedDuplicate().setIndex(offset, offset + length));
}
を呼び出します
ByteBuf(in)の読み取りと書き込みのインデックスが設定されているため、回答セクションの他のDnsRecordsはスキップされ、1つのDnsRecordだけがreturingされます。
私はノーマンマウラーはバグとしてこれを確認し、リリースでそれを固定ネッティー4.1.4.Final
バグがあると思われる場合は、netty発行トリガーにバグレポートを開いてください。 –
問題を追加しました: https://github.com/netty/netty/issues/5760 –