private Message makeQuery(DNSRequest request, int id) throws TextParseException {
    Name name = Name.fromString(request.getHostname(), Name.root);

    int type;
    switch (request.getRecordType()) {
      case DNSRequest.A:
        type = Type.A;
        break;
      case DNSRequest.AAAA:
        type = Type.AAAA;
        break;
      case DNSRequest.MX:
        type = Type.MX;
        break;
      case DNSRequest.PTR:
        type = Type.PTR;
        break;
      case DNSRequest.SPF:
        type = Type.SPF;
        break;
      case DNSRequest.TXT:
        type = Type.TXT;
        break;
      default:
        throw new UnsupportedOperationException("Unknown query type: " + request.getRecordType());
    }

    Record question = Record.newRecord(name, type, DClass.ANY);
    Message query = Message.newQuery(question);
    query.getHeader().setID(id);
    return query;
  }
  @Test
  public void itLogsServerErrors() throws Exception {
    header.setRcode(Rcode.REFUSED);

    Name name = Name.fromString("John Wayne.");
    Record question = Record.newRecord(name, 65530, 43210);

    Message query = Message.newQuery(question);

    Message response = mock(Message.class);
    when(response.getHeader()).thenReturn(header);
    when(response.getSectionArray(Section.ANSWER)).thenReturn(null);
    when(response.getQuestion()).thenReturn(question);

    when(nameServer.query(
            any(Message.class), any(InetAddress.class), any(DNSAccessRecord.Builder.class)))
        .thenThrow(new RuntimeException("Aw snap!"));

    FakeAbstractProtocol abstractProtocol = new FakeAbstractProtocol(client, query.toWire());
    abstractProtocol.setNameServer(nameServer);
    abstractProtocol.run();

    verify(accessLogger)
        .info(
            "144140678.000 qtype=DNS chi=192.168.23.45 ttms=345.123 xn=65535 fqdn=John\\032Wayne. type=TYPE65530 class=CLASS43210 rcode=SERVFAIL rtype=- rloc=\"-\" rdtl=- rerr=\"Server Error:RuntimeException:Aw snap!\" ttl=\"-\" ans=\"-\"");
  }
  /*
   * Look for SOA records corresponding to the request
   * TODO: Add cache coherency to SOA records?
   */
  protected synchronized Record checkForSoaRecord(String questionName) {
    if (!questionName.endsWith(".")) questionName += ".";

    if (soaRecords == null) {
      DnsRecord[] getRecs = null;
      // load all SOA records...
      try {
        getRecs = proxy.getDNSByType(Type.SOA);

        if (getRecs == null || getRecs.length == 0) soaRecords = Collections.emptyMap();
        else {
          soaRecords = new HashMap<String, Record>();

          for (DnsRecord rec : getRecs) {
            Record newRec =
                Record.newRecord(
                    Name.fromString(rec.getName()),
                    Type.SOA,
                    rec.getDclass(),
                    rec.getTtl(),
                    rec.getData());

            soaRecords.put(newRec.getName().toString(), newRec);
          }
        }
      } catch (Exception e) {
        LOGGER.error("Failed to load SOA records from config service.");
      }
    }

    Record retVal = null;
    if (soaRecords.size() > 0) {
      // look for the record by question name

      retVal = soaRecords.get(questionName);
      if (retVal == null) {
        // start taking apart the question name . by .
        int index = -1;
        while ((index = questionName.indexOf(".")) > 0 && index < (questionName.length() - 1)) {
          questionName = questionName.substring(index + 1);
          retVal = soaRecords.get(questionName);
          if (retVal != null) break;
        }
      }
    }

    return retVal;
  }
  private void sendQuery() {
    Header queryHeader = new Header();

    // If we set the RA (Recursion Available) flag and our message ID to 0
    // then the packet matches the real mDNS query packet as displayed in Wireshark
    queryHeader.setFlag(org.xbill.DNS.Flags.RA);
    queryHeader.setID(0);

    Record question = null;
    try {
      // We need to create our "Question" DNS query that is a pointer record to
      // the mDNS Query "Name"
      question = Record.newRecord(new Name(NvmDNS.MDNS_QUERY), Type.PTR, DClass.IN);
    } catch (TextParseException e) {
      Log.e("NvmDNS Query", e.getMessage());
      return;
    }

    // We combine our header and our question into a single message
    Message query = new Message();
    query.setHeader(queryHeader);
    query.addRecord(question, Section.QUESTION);

    // Convert the message into Network Byte Order
    byte[] wireQuery = query.toWire();
    Log.i("NvmDNS Query", query.toString());

    // Convert our byte array into a Packet
    DatagramPacket transmitPacket = new DatagramPacket(wireQuery, wireQuery.length);
    transmitPacket.setAddress(NvmDNS.MDNS_MULTICAST_ADDRESS);
    transmitPacket.setPort(NvmDNS.MDNS_PORT);

    // And (attempt) to send the packet
    try {
      Log.d("NvmDNS Query", "Blocking on this.nvstream_socket.send(transmitPacket)");
      this.socket.send(transmitPacket);
      Log.d("NvmDNS Query", "Passed this.nvstream_socket.send(transmitPacket)");
    } catch (IOException e) {
      Log.e("NvmDNS Query", "There was an error sending the DNS query.");
      Log.e("NvmDNS Query", e.getMessage());
    }
  }
  @Test
  public void itLogsARecordQueries() throws Exception {
    header.setRcode(Rcode.NOERROR);

    Name name = Name.fromString("www.example.com.");
    Record question = Record.newRecord(name, Type.A, DClass.IN, 0L);
    Message query = Message.newQuery(question);

    query.getHeader().getRcode();

    byte[] queryBytes = query.toWire();

    whenNew(Message.class).withArguments(queryBytes).thenReturn(query);

    InetAddress resolvedAddress = Inet4Address.getByName("192.168.8.9");

    Record answer = new ARecord(name, DClass.IN, 3600L, resolvedAddress);
    Record[] answers = new Record[] {answer};

    Message response = mock(Message.class);
    when(response.getHeader()).thenReturn(header);
    when(response.getSectionArray(Section.ANSWER)).thenReturn(answers);
    when(response.getQuestion()).thenReturn(question);

    InetAddress client = Inet4Address.getByName("192.168.23.45");
    when(nameServer.query(
            any(Message.class), any(InetAddress.class), any(DNSAccessRecord.Builder.class)))
        .thenReturn(response);

    FakeAbstractProtocol abstractProtocol = new FakeAbstractProtocol(client, queryBytes);
    abstractProtocol.setNameServer(nameServer);

    abstractProtocol.run();

    verify(accessLogger)
        .info(
            "144140678.000 qtype=DNS chi=192.168.23.45 ttms=345.123 xn=65535 fqdn=www.example.com. type=A class=IN rcode=NOERROR rtype=- rloc=\"-\" rdtl=- rerr=\"-\" ttl=\"3600\" ans=\"192.168.8.9\"");
  }
  protected Collection<Record> processGenericANYRecordRequest(String name) throws DNSException {
    DnsRecord records[];

    try {
      records = proxy.getDNSByNameAndType(name, Type.ANY);
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "DNS service proxy call for DNS records failed: " + e.getMessage(),
          e);
    }

    if (records == null || records.length == 0) return null;

    Collection<Record> retVal = new ArrayList<Record>();
    try {
      for (DnsRecord record : records) {
        Record rec =
            Record.newRecord(
                Name.fromString(record.getName()),
                record.getType(),
                record.getDclass(),
                record.getTtl(),
                record.getData());

        retVal.add(rec);
      }
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "Failure while parsing generic record data: " + e.getMessage(),
          e);
    }

    return retVal;
  }
 /*
  * converts a configuration service DnsRecord to a dnsjava Record
  */
 private Record toRecord(DnsRecord rec) {
   return Record.newRecord(
       nameFromString(rec.getName()), rec.getType(), rec.getDclass(), rec.getTtl(), rec.getData());
 }