• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.net.lowpan;
18 
19 import android.annotation.NonNull;
20 import android.icu.text.StringPrep;
21 import android.icu.text.StringPrepParseException;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.util.Log;
25 import com.android.internal.util.HexDump;
26 import java.nio.charset.StandardCharsets;
27 import java.util.Arrays;
28 import java.util.Objects;
29 
30 /**
31  * Describes an instance of a LoWPAN network.
32  *
33  * @hide
34  */
35 // @SystemApi
36 public class LowpanIdentity implements Parcelable {
37     private static final String TAG = LowpanIdentity.class.getSimpleName();
38 
39     // Constants
40     public static final int UNSPECIFIED_CHANNEL = -1;
41     public static final int UNSPECIFIED_PANID = 0xFFFFFFFF;
42     // Builder
43 
44     /** @hide */
45     // @SystemApi
46     public static class Builder {
47         private static final StringPrep stringPrep =
48                 StringPrep.getInstance(StringPrep.RFC3920_RESOURCEPREP);
49 
50         final LowpanIdentity mIdentity = new LowpanIdentity();
51 
escape(@onNull byte[] bytes)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 
setLowpanIdentity(@onNull LowpanIdentity x)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 
setName(@onNull String name)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 
setRawName(@onNull byte[] name)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 
105             return this;
106         }
107 
setXpanid(byte x[])108         public Builder setXpanid(byte x[]) {
109             mIdentity.mXpanid = (x != null ? x.clone() : null);
110             return this;
111         }
112 
setPanid(int x)113         public Builder setPanid(int x) {
114             mIdentity.mPanid = x;
115             return this;
116         }
117 
setType(@onNull String x)118         public Builder setType(@NonNull String x) {
119             mIdentity.mType = x;
120             return this;
121         }
122 
setChannel(int x)123         public Builder setChannel(int x) {
124             mIdentity.mChannel = x;
125             return this;
126         }
127 
build()128         public LowpanIdentity build() {
129             return mIdentity;
130         }
131     }
132 
LowpanIdentity()133     LowpanIdentity() {}
134 
135     // Instance Variables
136 
137     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;
144 
145     // Public Getters
146 
getName()147     public String getName() {
148         return mName;
149     }
150 
isNameValid()151     public boolean isNameValid() {
152         return mIsNameValid;
153     }
154 
getRawName()155     public byte[] getRawName() {
156         return mRawName.clone();
157     }
158 
getXpanid()159     public byte[] getXpanid() {
160         return mXpanid.clone();
161     }
162 
getPanid()163     public int getPanid() {
164         return mPanid;
165     }
166 
getType()167     public String getType() {
168         return mType;
169     }
170 
getChannel()171     public int getChannel() {
172         return mChannel;
173     }
174 
175     @Override
toString()176     public String toString() {
177         StringBuffer sb = new StringBuffer();
178 
179         sb.append("Name:").append(getName());
180 
181         if (mType.length() > 0) {
182             sb.append(", Type:").append(mType);
183         }
184 
185         if (mXpanid.length > 0) {
186             sb.append(", XPANID:").append(HexDump.toHexString(mXpanid));
187         }
188 
189         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);
195         }
196 
197         return sb.toString();
198     }
199 
200     @Override
equals(Object obj)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
hashCode()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
describeContents()221     public int describeContents() {
222         return 0;
223     }
224 
225     /** Implement the Parcelable interface. */
226     @Override
writeToParcel(Parcel dest, int flags)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. */
236     public static final Creator<LowpanIdentity> CREATOR =
237             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             };
255 }
256