1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.connectivity.mdns;
18 
19 import android.annotation.Nullable;
20 
21 import androidx.annotation.VisibleForTesting;
22 
23 import com.android.server.connectivity.mdns.util.MdnsUtils;
24 
25 import java.io.IOException;
26 import java.util.Arrays;
27 
28 /** An mDNS "PTR" record, which holds a name (the "pointer"). */
29 @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
30 public class MdnsPointerRecord extends MdnsRecord {
31     private String[] pointer;
32 
MdnsPointerRecord(String[] name, MdnsPacketReader reader)33     public MdnsPointerRecord(String[] name, MdnsPacketReader reader) throws IOException {
34         this(name, reader, false);
35     }
36 
MdnsPointerRecord(String[] name, MdnsPacketReader reader, boolean isQuestion)37     public MdnsPointerRecord(String[] name, MdnsPacketReader reader, boolean isQuestion)
38             throws IOException {
39         super(name, TYPE_PTR, reader, isQuestion);
40     }
41 
MdnsPointerRecord(String[] name, boolean isUnicast)42     public MdnsPointerRecord(String[] name, boolean isUnicast) {
43         super(name, TYPE_PTR,
44                 MdnsConstants.QCLASS_INTERNET | (isUnicast ? MdnsConstants.QCLASS_UNICAST : 0),
45                 0L /* receiptTimeMillis */, false /* cacheFlush */, 0L /* ttlMillis */);
46     }
47 
MdnsPointerRecord(String[] name, long receiptTimeMillis, boolean cacheFlush, long ttlMillis, String[] pointer)48     public MdnsPointerRecord(String[] name, long receiptTimeMillis, boolean cacheFlush,
49                     long ttlMillis, String[] pointer) {
50         super(name, TYPE_PTR, MdnsConstants.QCLASS_INTERNET, receiptTimeMillis, cacheFlush,
51                 ttlMillis);
52         this.pointer = pointer;
53     }
54 
55     /** Returns the pointer as an array of labels. */
getPointer()56     public String[] getPointer() {
57         return pointer;
58     }
59 
60     @Override
readData(MdnsPacketReader reader)61     protected void readData(MdnsPacketReader reader) throws IOException {
62         pointer = reader.readLabels();
63     }
64 
65     @Override
writeData(MdnsPacketWriter writer)66     protected void writeData(MdnsPacketWriter writer) throws IOException {
67         writer.writeLabels(pointer);
68     }
69 
hasSubtype()70     public boolean hasSubtype() {
71         return (name != null) && (name.length > 2) && MdnsUtils.equalsIgnoreDnsCase(name[1],
72                 MdnsConstants.SUBTYPE_LABEL);
73     }
74 
getSubtype()75     public String getSubtype() {
76         return hasSubtype() ? name[0] : null;
77     }
78 
79     @Override
toString()80     public String toString() {
81         return "PTR: " + labelsToString(name) + " -> " + labelsToString(pointer);
82     }
83 
84     @Override
hashCode()85     public int hashCode() {
86         return (super.hashCode() * 31) + Arrays.hashCode(MdnsUtils.toDnsLabelsLowerCase(pointer));
87     }
88 
89     @Override
equals(@ullable Object other)90     public boolean equals(@Nullable Object other) {
91         if (this == other) {
92             return true;
93         }
94         if (!(other instanceof MdnsPointerRecord)) {
95             return false;
96         }
97 
98         return super.equals(other) && MdnsUtils.equalsDnsLabelIgnoreDnsCase(pointer,
99                 ((MdnsPointerRecord) other).pointer);
100     }
101 }