blob: 1997bc4a46351f6933eff4231ae18193c53ddfef [file] [log] [blame]
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -08001/*
2 * Copyright (C) 2017 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
17package android.net.lowpan;
18
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -070019import android.annotation.NonNull;
20import android.icu.text.StringPrep;
21import android.icu.text.StringPrepParseException;
22import android.os.Parcel;
23import android.os.Parcelable;
24import android.util.Log;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -080025import com.android.internal.util.HexDump;
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -070026import java.nio.charset.StandardCharsets;
27import java.util.Arrays;
28import java.util.Objects;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -080029
30/**
31 * Describes an instance of a LoWPAN network.
32 *
33 * @hide
34 */
Robert Quattlebaum325b7f52017-06-06 16:51:41 -070035// @SystemApi
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -070036public class LowpanIdentity implements Parcelable {
37 private static final String TAG = LowpanIdentity.class.getSimpleName();
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -080038
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -080039 // Constants
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -070040 public static final int UNSPECIFIED_CHANNEL = -1;
41 public static final int UNSPECIFIED_PANID = 0xFFFFFFFF;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -080042 // Builder
43
44 /** @hide */
Robert Quattlebaum325b7f52017-06-06 16:51:41 -070045 // @SystemApi
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -080046 public static class Builder {
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -070047 private static final StringPrep stringPrep =
48 StringPrep.getInstance(StringPrep.RFC3920_RESOURCEPREP);
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -080049
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -070050 final LowpanIdentity mIdentity = new LowpanIdentity();
51
52 private static String escape(@NonNull byte[] bytes) {
53 StringBuffer sb = new StringBuffer();
54 for (byte b : bytes) {
55 if (b >= 32 && b <= 126) {
56 sb.append((char) b);
57 } else {
58 sb.append(String.format("\\0x%02x", b & 0xFF));
59 }
60 }
61 return sb.toString();
62 }
63
64 public Builder setLowpanIdentity(@NonNull LowpanIdentity x) {
65 Objects.requireNonNull(x);
66 setRawName(x.getRawName());
67 setXpanid(x.getXpanid());
68 setPanid(x.getPanid());
69 setChannel(x.getChannel());
70 setType(x.getType());
71 return this;
72 }
73
74 public Builder setName(@NonNull String name) {
75 Objects.requireNonNull(name);
76 try {
77 mIdentity.mName = stringPrep.prepare(name, StringPrep.DEFAULT);
78 mIdentity.mRawName = mIdentity.mName.getBytes(StandardCharsets.UTF_8);
79 mIdentity.mIsNameValid = true;
80 } catch (StringPrepParseException x) {
81 Log.w(TAG, x.toString());
82 setRawName(name.getBytes(StandardCharsets.UTF_8));
83 }
84 return this;
85 }
86
87 public Builder setRawName(@NonNull byte[] name) {
88 Objects.requireNonNull(name);
89 mIdentity.mRawName = name.clone();
90 mIdentity.mName = new String(name, StandardCharsets.UTF_8);
91 try {
92 String nameCheck = stringPrep.prepare(mIdentity.mName, StringPrep.DEFAULT);
93 mIdentity.mIsNameValid =
94 Arrays.equals(nameCheck.getBytes(StandardCharsets.UTF_8), name);
95 } catch (StringPrepParseException x) {
96 Log.w(TAG, x.toString());
97 mIdentity.mIsNameValid = false;
98 }
99
100 // Non-normal names must be rendered differently to avoid confusion.
101 if (!mIdentity.mIsNameValid) {
102 mIdentity.mName = "«" + escape(name) + "»";
103 }
104
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800105 return this;
106 }
107
108 public Builder setXpanid(byte x[]) {
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700109 mIdentity.mXpanid = (x != null ? x.clone() : null);
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800110 return this;
111 }
112
113 public Builder setPanid(int x) {
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700114 mIdentity.mPanid = x;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800115 return this;
116 }
117
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700118 public Builder setType(@NonNull String x) {
119 mIdentity.mType = x;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800120 return this;
121 }
122
123 public Builder setChannel(int x) {
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700124 mIdentity.mChannel = x;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800125 return this;
126 }
127
128 public LowpanIdentity build() {
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700129 return mIdentity;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800130 }
131 }
132
133 LowpanIdentity() {}
134
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800135 // Instance Variables
136
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700137 private String mName = "";
138 private boolean mIsNameValid = true;
139 private byte[] mRawName = new byte[0];
140 private String mType = "";
141 private byte[] mXpanid = new byte[0];
142 private int mPanid = UNSPECIFIED_PANID;
143 private int mChannel = UNSPECIFIED_CHANNEL;
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800144
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700145 // Public Getters
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800146
147 public String getName() {
148 return mName;
149 }
150
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700151 public boolean isNameValid() {
152 return mIsNameValid;
153 }
154
155 public byte[] getRawName() {
156 return mRawName.clone();
157 }
158
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800159 public byte[] getXpanid() {
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700160 return mXpanid.clone();
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800161 }
162
163 public int getPanid() {
164 return mPanid;
165 }
166
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700167 public String getType() {
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800168 return mType;
169 }
170
171 public int getChannel() {
172 return mChannel;
173 }
174
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800175 @Override
176 public String toString() {
177 StringBuffer sb = new StringBuffer();
178
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700179 sb.append("Name:").append(getName());
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800180
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700181 if (mType.length() > 0) {
182 sb.append(", Type:").append(mType);
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800183 }
184
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700185 if (mXpanid.length > 0) {
186 sb.append(", XPANID:").append(HexDump.toHexString(mXpanid));
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800187 }
188
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700189 if (mPanid != UNSPECIFIED_PANID) {
190 sb.append(", PANID:").append(String.format("0x%04X", mPanid));
191 }
192
193 if (mChannel != UNSPECIFIED_CHANNEL) {
194 sb.append(", Channel:").append(mChannel);
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800195 }
196
197 return sb.toString();
198 }
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700199
200 @Override
201 public boolean equals(Object obj) {
202 if (!(obj instanceof LowpanIdentity)) {
203 return false;
204 }
205 LowpanIdentity rhs = (LowpanIdentity) obj;
206 return Arrays.equals(mRawName, rhs.mRawName)
207 && Arrays.equals(mXpanid, rhs.mXpanid)
208 && mType.equals(rhs.mType)
209 && mPanid == rhs.mPanid
210 && mChannel == rhs.mChannel;
211 }
212
213 @Override
214 public int hashCode() {
215 return Objects.hash(
216 Arrays.hashCode(mRawName), mType, Arrays.hashCode(mXpanid), mPanid, mChannel);
217 }
218
219 /** Implement the Parcelable interface. */
220 @Override
221 public int describeContents() {
222 return 0;
223 }
224
225 /** Implement the Parcelable interface. */
226 @Override
227 public void writeToParcel(Parcel dest, int flags) {
228 dest.writeByteArray(mRawName);
229 dest.writeString(mType);
230 dest.writeByteArray(mXpanid);
231 dest.writeInt(mPanid);
232 dest.writeInt(mChannel);
233 }
234
235 /** Implement the Parcelable interface. */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700236 public static final @android.annotation.NonNull Creator<LowpanIdentity> CREATOR =
Robert Quattlebaum80aca1e2017-07-14 12:02:19 -0700237 new Creator<LowpanIdentity>() {
238
239 public LowpanIdentity createFromParcel(Parcel in) {
240 Builder builder = new Builder();
241
242 builder.setRawName(in.createByteArray());
243 builder.setType(in.readString());
244 builder.setXpanid(in.createByteArray());
245 builder.setPanid(in.readInt());
246 builder.setChannel(in.readInt());
247
248 return builder.build();
249 }
250
251 public LowpanIdentity[] newArray(int size) {
252 return new LowpanIdentity[size];
253 }
254 };
Robert Quattlebaum4e0c2192017-02-08 12:13:19 -0800255}