Skip to content
Snippets Groups Projects
Commit 24db3f1e authored by Paul Hu's avatar Paul Hu
Browse files

Generate a query packet with MdnsPacket

This is a no-op change, only refactoring the query packet
generation code to use MdnsPacket. This refactoring enables the
insertion of additional sections into the query packet and
facilitates the determination of truncation requirements.

Bug: 312657709
Test: atest FrameworksNetTests NsdManagerTest
Change-Id: I3671842b6d433e1856a1efae643f3fe1f6c532d1
parent 976e52a2
No related branches found
No related tags found
No related merge requests found
......@@ -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);
......
......@@ -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,
......
......@@ -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,
......
......@@ -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) {
......
......@@ -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,
......
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment