Я работаю с DNS-клиентом с нетти. Чтобы проверить это, я написал простой DNS-сервер с netty, который возвращает DnsRecords, которого я ожидаю.Раздел ответа Netty DNS не правильно декодирован
Вот мой код клиента:
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 в разделе ответов.
За TEST_DNS_SD_SERVER_PORT
Я бегу DNS-сервера в отдельном потоке, который обрабатывает запросы следующим образом: (часть 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);
}
В définies сервера следующие ChannelHandler
public void initChannel(final DatagramChannel ch) throws Exception {
ch.pipeline().addLast(new DatagramDnsResponseEncoder());
ch.pipeline().addLast(new DatagramDnsQueryDecoder());
ch.pipeline().addLast(new LocalDNSSDHandler());
}
То, что я ожидаю в клиенте, - это увидеть 3 System.out.println
для 3 DnsPtrRecords, которых я ожидаю. Но я получаю только 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);
называется, он будет вызывать
(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));
}
Я не понимаю
in.setIndex(offset, offset + length);
Поскольку это устанавливает индекс чтения и записи ByteBuf (in), и это пропустит другие DnsRecords в разделе «Ответ» и заставит его сохранить только один DnsRecord.
Я использую Netty 4.1.4.Final
Если вы считаете, что есть ошибка, пожалуйста, откройте отчет об ошибке в триггере проблемы. –
Номер ошибки: https://github.com/netty/netty/issues/5760 –