2016-08-23 6 views
0

Я работаю с 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

+0

Если вы считаете, что есть ошибка, пожалуйста, откройте отчет об ошибке в триггере проблемы. –

+0

Номер ошибки: https://github.com/netty/netty/issues/5760 –

ответ

0

Норман Маурер подтвердил это как Буг и неподвижного его в выпуске: 4.1.6.Final

Спасибо Нормана!