diff --git a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java index 1582fb66b42bb8d414c4d34a8fc97ac4be30ac46..c4d3338ed2e58c3035e9d472ec021fe4c0369cc0 100644 --- a/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java +++ b/service-t/src/com/android/server/connectivity/mdns/EnqueueMdnsQueryCallable.java @@ -32,6 +32,7 @@ import java.net.DatagramPacket; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; @@ -122,17 +123,22 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str return Pair.create(INVALID_TRANSACTION_ID, new ArrayList<>()); } - int numQuestions = 0; + final List<MdnsRecord> questions = new ArrayList<>(); if (sendDiscoveryQueries) { - numQuestions++; // Base service type - if (!subtypes.isEmpty()) { - numQuestions += subtypes.size(); + // Base service type + questions.add(new MdnsPointerRecord(serviceTypeLabels, expectUnicastResponse)); + for (String subtype : subtypes) { + final String[] labels = new String[serviceTypeLabels.length + 2]; + labels[0] = MdnsConstants.SUBTYPE_PREFIX + subtype; + labels[1] = MdnsConstants.SUBTYPE_LABEL; + System.arraycopy(serviceTypeLabels, 0, labels, 2, serviceTypeLabels.length); + + questions.add(new MdnsPointerRecord(labels, expectUnicastResponse)); } } // List of (name, type) to query - final ArrayList<Pair<String[], Integer>> missingKnownAnswerRecords = new ArrayList<>(); final long now = clock.elapsedRealtime(); for (MdnsResponse response : servicesToResolve) { final String[] serviceName = response.getServiceName(); @@ -142,13 +148,13 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str boolean renewSrv = !response.hasServiceRecord() || MdnsUtils.isRecordRenewalNeeded( response.getServiceRecord(), now); if (renewSrv && renewTxt) { - missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_ANY)); + questions.add(new MdnsAnyRecord(serviceName, expectUnicastResponse)); } else { if (renewTxt) { - missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_TXT)); + questions.add(new MdnsTextRecord(serviceName, expectUnicastResponse)); } if (renewSrv) { - missingKnownAnswerRecords.add(new Pair<>(serviceName, MdnsRecord.TYPE_SRV)); + questions.add(new MdnsServiceRecord(serviceName, expectUnicastResponse)); // The hostname is not yet known, so queries for address records will be // sent the next time the EnqueueMdnsQueryCallable is enqueued if the reply // does not contain them. In practice, advertisers should include the @@ -157,46 +163,27 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str } else if (!response.hasInet4AddressRecord() && !response.hasInet6AddressRecord()) { final String[] host = response.getServiceRecord().getServiceHost(); - missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_A)); - missingKnownAnswerRecords.add(new Pair<>(host, MdnsRecord.TYPE_AAAA)); + questions.add(new MdnsInetAddressRecord( + host, MdnsRecord.TYPE_A, expectUnicastResponse)); + questions.add(new MdnsInetAddressRecord( + host, MdnsRecord.TYPE_AAAA, expectUnicastResponse)); } } } - numQuestions += missingKnownAnswerRecords.size(); - if (numQuestions == 0) { + if (questions.size() == 0) { // No query to send return Pair.create(INVALID_TRANSACTION_ID, new ArrayList<>()); } - // Header. - packetWriter.writeUInt16(transactionId); // transaction ID - packetWriter.writeUInt16(MdnsConstants.FLAGS_QUERY); // flags - packetWriter.writeUInt16(numQuestions); // number of questions - packetWriter.writeUInt16(0); // number of answers (not yet known; will be written later) - packetWriter.writeUInt16(0); // number of authority entries - packetWriter.writeUInt16(0); // number of additional records - - // Question(s) for missing records on known answers - for (Pair<String[], Integer> question : missingKnownAnswerRecords) { - writeQuestion(question.first, question.second); - } - - // Question(s) for discovering other services with the type. There will be one question - // for each (fqdn+subtype, recordType) combination, as well as one for each (fqdn, - // recordType) combination. - if (sendDiscoveryQueries) { - for (String subtype : subtypes) { - String[] labels = new String[serviceTypeLabels.length + 2]; - labels[0] = MdnsConstants.SUBTYPE_PREFIX + subtype; - labels[1] = MdnsConstants.SUBTYPE_LABEL; - System.arraycopy(serviceTypeLabels, 0, labels, 2, serviceTypeLabels.length); - - writeQuestion(labels, MdnsRecord.TYPE_PTR); - } - writeQuestion(serviceTypeLabels, MdnsRecord.TYPE_PTR); - } - + final MdnsPacket queryPacket = new MdnsPacket( + transactionId, + MdnsConstants.FLAGS_QUERY, + questions, + Collections.emptyList(), /* answers */ + Collections.emptyList(), /* authorityRecords */ + Collections.emptyList() /* additionalRecords */); + MdnsUtils.writeMdnsPacket(packetWriter, queryPacket); sendPacketToIpv4AndIpv6(requestSender, MdnsConstants.MDNS_PORT); for (Integer emulatorPort : castShellEmulatorMdnsPorts) { sendPacketToIpv4AndIpv6(requestSender, emulatorPort); @@ -209,14 +196,6 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str } } - private void writeQuestion(String[] labels, int type) throws IOException { - packetWriter.writeLabels(labels); - packetWriter.writeUInt16(type); - packetWriter.writeUInt16( - MdnsConstants.QCLASS_INTERNET - | (expectUnicastResponse ? MdnsConstants.QCLASS_UNICAST : 0)); - } - private void sendPacket(MdnsSocketClientBase requestSender, InetSocketAddress address) throws IOException { DatagramPacket packet = packetWriter.getPacket(address); diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java index 973fd9602e7874c45dc80db0b2ce8ad730beb70a..4399f2d6dac97f395d8b0703d26f385f270428bf 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsInetAddressRecord.java @@ -60,6 +60,12 @@ public class MdnsInetAddressRecord extends MdnsRecord { super(name, type, reader, isQuestion); } + public MdnsInetAddressRecord(String[] name, int type, boolean isUnicast) { + super(name, type, + MdnsConstants.QCLASS_INTERNET | (isUnicast ? MdnsConstants.QCLASS_UNICAST : 0), + 0L /* receiptTimeMillis */, false /* cacheFlush */, 0L /* ttlMillis */); + } + public MdnsInetAddressRecord(String[] name, long receiptTimeMillis, boolean cacheFlush, long ttlMillis, InetAddress address) { super(name, address instanceof Inet4Address ? TYPE_A : TYPE_AAAA, diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java index 41cc3800299445fe2a620558e83e0dd65772b713..e5c90a46e8f0a24e755c6861861d54a474abfe6f 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsPointerRecord.java @@ -39,6 +39,12 @@ public class MdnsPointerRecord extends MdnsRecord { super(name, TYPE_PTR, reader, isQuestion); } + public MdnsPointerRecord(String[] name, boolean isUnicast) { + super(name, TYPE_PTR, + MdnsConstants.QCLASS_INTERNET | (isUnicast ? MdnsConstants.QCLASS_UNICAST : 0), + 0L /* receiptTimeMillis */, false /* cacheFlush */, 0L /* ttlMillis */); + } + public MdnsPointerRecord(String[] name, long receiptTimeMillis, boolean cacheFlush, long ttlMillis, String[] pointer) { super(name, TYPE_PTR, MdnsConstants.QCLASS_INTERNET, receiptTimeMillis, cacheFlush, diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java index 4d407be63f784e3db7bb9e5314426bbaf7c22d84..0d6a9ec487c54887f9e87cf77d7003f4e912aac0 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceRecord.java @@ -49,6 +49,12 @@ public class MdnsServiceRecord extends MdnsRecord { super(name, TYPE_SRV, reader, isQuestion); } + public MdnsServiceRecord(String[] name, boolean isUnicast) { + super(name, TYPE_SRV, + MdnsConstants.QCLASS_INTERNET | (isUnicast ? MdnsConstants.QCLASS_UNICAST : 0), + 0L /* receiptTimeMillis */, false /* cacheFlush */, 0L /* ttlMillis */); + } + public MdnsServiceRecord(String[] name, long receiptTimeMillis, boolean cacheFlush, long ttlMillis, int servicePriority, int serviceWeight, int servicePort, String[] serviceHost) { diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsTextRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsTextRecord.java index cf6c8acf2f07436bd71ac342348142e8fd0ab01e..92cf3243cc6ee18695cda33678e708c4db60b454 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsTextRecord.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsTextRecord.java @@ -42,6 +42,12 @@ public class MdnsTextRecord extends MdnsRecord { super(name, TYPE_TXT, reader, isQuestion); } + public MdnsTextRecord(String[] name, boolean isUnicast) { + super(name, TYPE_TXT, + MdnsConstants.QCLASS_INTERNET | (isUnicast ? MdnsConstants.QCLASS_UNICAST : 0), + 0L /* receiptTimeMillis */, false /* cacheFlush */, 0L /* ttlMillis */); + } + public MdnsTextRecord(String[] name, long receiptTimeMillis, boolean cacheFlush, long ttlMillis, List<TextEntry> entries) { super(name, TYPE_TXT, MdnsConstants.QCLASS_INTERNET, receiptTimeMillis, cacheFlush, diff --git a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java index 4d79f9d8eae3d9d5a404f1c2a4883e0b941c04bb..1482ebb7a039cb15e06d83ab4df92014fa7bb99b 100644 --- a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java +++ b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java @@ -183,13 +183,10 @@ public class MdnsUtils { } /** - * Create a raw DNS packet. + * Write the mdns packet from given MdnsPacket. */ - public static byte[] createRawDnsPacket(@NonNull byte[] packetCreationBuffer, - @NonNull MdnsPacket packet) throws IOException { - // TODO: support packets over size (send in multiple packets with TC bit set) - final MdnsPacketWriter writer = new MdnsPacketWriter(packetCreationBuffer); - + public static void writeMdnsPacket(@NonNull MdnsPacketWriter writer, @NonNull MdnsPacket packet) + throws IOException { writer.writeUInt16(packet.transactionId); // Transaction ID (advertisement: 0) writer.writeUInt16(packet.flags); // Response, authoritative (rfc6762 18.4) writer.writeUInt16(packet.questions.size()); // questions count @@ -210,6 +207,16 @@ public class MdnsUtils { for (MdnsRecord record : packet.additionalRecords) { record.write(writer, 0L); } + } + + /** + * Create a raw DNS packet. + */ + public static byte[] createRawDnsPacket(@NonNull byte[] packetCreationBuffer, + @NonNull MdnsPacket packet) throws IOException { + // TODO: support packets over size (send in multiple packets with TC bit set) + final MdnsPacketWriter writer = new MdnsPacketWriter(packetCreationBuffer); + writeMdnsPacket(writer, packet); final int len = writer.getWritePosition(); return Arrays.copyOfRange(packetCreationBuffer, 0, len);