2016-08-23 136 views
0

我正在与netty的DNS客户端工作。 为了测试它,我用netty编写了一个简单的DNS服务器,它返回我期待的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); 
    } 

服务器definies以下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)的读取和写入索引,并且这将跳过Answer部分中的其他DnsRecords,并且使其仅响应一个DnsRecord。

我使用了Netty 4.1.4.Final

+0

如果您认为存在错误,请在netty问题触发器中打开错误报告。 –

+0

发行时间: https://github.com/netty/netty/issues/5760 –

回答

0

诺曼·毛雷尔证实这是一个错误,在释放固定它: 4.1.6.Final

谢谢诺曼!