2016-08-23 9 views
0

私は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);

01を理解していない

(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

+0

バグがあると思われる場合は、netty発行トリガーにバグレポートを開いてください。 –

+0

問題を追加しました: https://github.com/netty/netty/issues/5760 –

答えて

0

を使用しています: 4.1.6.Final

はあなたのノーマンをありがとう!

関連する問題