1ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpackage com.android.anqp;
2ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
3ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.net.ProtocolException;
4ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.nio.ByteBuffer;
5ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.nio.ByteOrder;
6ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.nio.charset.Charset;
7ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Collection;
8ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.EnumMap;
9ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.HashMap;
10ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.List;
11ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Map;
12ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
13ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist/**
14ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist * ANQP related constants (802.11-2012)
15ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist */
16ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistpublic class Constants {
17ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
18ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int NIBBLE_MASK = 0x0f;
19ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int BYTE_MASK = 0xff;
20ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int SHORT_MASK = 0xffff;
21ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final long INT_MASK = 0xffffffffL;
22ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int BYTES_IN_SHORT = 2;
23ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int BYTES_IN_INT = 4;
24ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int BYTES_IN_EUI48 = 6;
25ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final long MILLIS_IN_A_SEC = 1000L;
26ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
27ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS20_PREFIX = 0x119a6f50;   // Note that this is represented as a LE int
28ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS20_FRAME_PREFIX = 0x109a6f50;
29ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int UTF8_INDICATOR = 1;
30ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
31ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int LANG_CODE_LENGTH = 3;
32ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
33ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_QUERY_LIST = 256;
34ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_CAPABILITY_LIST = 257;
35ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_VENUE_NAME = 258;
36ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_EMERGENCY_NUMBER = 259;
37ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_NWK_AUTH_TYPE = 260;
38ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_ROAMING_CONSORTIUM = 261;
39ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_IP_ADDR_AVAILABILITY = 262;
40ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_NAI_REALM = 263;
41ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_3GPP_NETWORK = 264;
42ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_GEO_LOC = 265;
43ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_CIVIC_LOC = 266;
44ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_LOC_URI = 267;
45ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_DOM_NAME = 268;
46ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_EMERGENCY_ALERT = 269;
47ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_TDLS_CAP = 270;
48ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_EMERGENCY_NAI = 271;
49ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_NEIGHBOR_REPORT = 272;
50ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int ANQP_VENDOR_SPEC = 56797;
51ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
52ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_QUERY_LIST = 1;
53ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_CAPABILITY_LIST = 2;
54ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_FRIENDLY_NAME = 3;
55ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_WAN_METRICS = 4;
56ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_CONN_CAPABILITY = 5;
57ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_NAI_HOME_REALM_QUERY = 6;
58ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_OPERATING_CLASS = 7;
59ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_OSU_PROVIDERS = 8;
60ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_ICON_REQUEST = 10;
61ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final int HS_ICON_FILE = 11;
62ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
63ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public enum ANQPElementType {
64ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPQueryList,
65ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPCapabilityList,
66ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPVenueName,
67ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPEmergencyNumber,
68ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPNwkAuthType,
69ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPRoamingConsortium,
70ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPIPAddrAvailability,
71ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPNAIRealm,
72ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQP3GPPNetwork,
73ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPGeoLoc,
74ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPCivicLoc,
75ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPLocURI,
76ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPDomName,
77ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPEmergencyAlert,
78ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPTDLSCap,
79ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPEmergencyNAI,
80ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPNeighborReport,
81ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        ANQPVendorSpec,
82ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSQueryList,
83ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSCapabilityList,
84ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSFriendlyName,
85ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSWANMetrics,
86ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSConnCapability,
87ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSNAIHomeRealmQuery,
88ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSOperatingclass,
89ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSOSUProviders,
90ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSIconRequest,
91ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        HSIconFile
92ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
93ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
94ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static final Map<Integer, ANQPElementType> sAnqpMap = new HashMap<>();
95ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static final Map<Integer, ANQPElementType> sHs20Map = new HashMap<>();
96ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static final Map<ANQPElementType, Integer> sRevAnqpmap =
97ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            new EnumMap<>(ANQPElementType.class);
98ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static final Map<ANQPElementType, Integer> sRevHs20map =
99ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            new EnumMap<>(ANQPElementType.class);
100ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
101ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    static {
102ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_QUERY_LIST, ANQPElementType.ANQPQueryList);
103ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_CAPABILITY_LIST, ANQPElementType.ANQPCapabilityList);
104ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_VENUE_NAME, ANQPElementType.ANQPVenueName);
105ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_EMERGENCY_NUMBER, ANQPElementType.ANQPEmergencyNumber);
106ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_NWK_AUTH_TYPE, ANQPElementType.ANQPNwkAuthType);
107ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_ROAMING_CONSORTIUM, ANQPElementType.ANQPRoamingConsortium);
108ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_IP_ADDR_AVAILABILITY, ANQPElementType.ANQPIPAddrAvailability);
109ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_NAI_REALM, ANQPElementType.ANQPNAIRealm);
110ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_3GPP_NETWORK, ANQPElementType.ANQP3GPPNetwork);
111ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_GEO_LOC, ANQPElementType.ANQPGeoLoc);
112ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_CIVIC_LOC, ANQPElementType.ANQPCivicLoc);
113ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_LOC_URI, ANQPElementType.ANQPLocURI);
114ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_DOM_NAME, ANQPElementType.ANQPDomName);
115ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_EMERGENCY_ALERT, ANQPElementType.ANQPEmergencyAlert);
116ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_TDLS_CAP, ANQPElementType.ANQPTDLSCap);
117ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_EMERGENCY_NAI, ANQPElementType.ANQPEmergencyNAI);
118ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_NEIGHBOR_REPORT, ANQPElementType.ANQPNeighborReport);
119ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sAnqpMap.put(ANQP_VENDOR_SPEC, ANQPElementType.ANQPVendorSpec);
120ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
121ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_QUERY_LIST, ANQPElementType.HSQueryList);
122ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_CAPABILITY_LIST, ANQPElementType.HSCapabilityList);
123ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_FRIENDLY_NAME, ANQPElementType.HSFriendlyName);
124ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_WAN_METRICS, ANQPElementType.HSWANMetrics);
125ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_CONN_CAPABILITY, ANQPElementType.HSConnCapability);
126ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_NAI_HOME_REALM_QUERY, ANQPElementType.HSNAIHomeRealmQuery);
127ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_OPERATING_CLASS, ANQPElementType.HSOperatingclass);
128ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_OSU_PROVIDERS, ANQPElementType.HSOSUProviders);
129ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_ICON_REQUEST, ANQPElementType.HSIconRequest);
130ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        sHs20Map.put(HS_ICON_FILE, ANQPElementType.HSIconFile);
131ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
132ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (Map.Entry<Integer, ANQPElementType> entry : sAnqpMap.entrySet()) {
133ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sRevAnqpmap.put(entry.getValue(), entry.getKey());
134ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
135ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (Map.Entry<Integer, ANQPElementType> entry : sHs20Map.entrySet()) {
136ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            sRevHs20map.put(entry.getValue(), entry.getKey());
137ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
138ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
139ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
140ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static ANQPElementType mapANQPElement(int id) {
141ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return sAnqpMap.get(id);
142ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
143ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
144ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static ANQPElementType mapHS20Element(int id) {
145ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return sHs20Map.get(id);
146ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
147ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
148ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static Integer getANQPElementID(ANQPElementType elementType) {
149ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return sRevAnqpmap.get(elementType);
150ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
151ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
152ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static Integer getHS20ElementID(ANQPElementType elementType) {
153ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return sRevHs20map.get(elementType);
154ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
155ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
156ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static boolean hasBaseANQPElements(Collection<ANQPElementType> elements) {
157ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (elements == null) {
158ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return false;
159ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
160ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (ANQPElementType element : elements) {
161ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (sRevAnqpmap.containsKey(element)) {
162ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                return true;
163ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
164ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
165ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return false;
166ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
167ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
168ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static boolean hasR2Elements(List<ANQPElementType> elements) {
169ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return elements.contains(ANQPElementType.HSOSUProviders);
170ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
171ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
172ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static long getInteger(ByteBuffer payload, ByteOrder bo, int size) {
173ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        byte[] octets = new byte[size];
174ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        payload.get(octets);
175ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        long value = 0;
176ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (bo == ByteOrder.LITTLE_ENDIAN) {
177ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            for (int n = octets.length - 1; n >= 0; n--) {
178ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                value = (value << Byte.SIZE) | (octets[n] & BYTE_MASK);
179ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
180ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
181ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        else {
182ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            for (byte octet : octets) {
183ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                value = (value << Byte.SIZE) | (octet & BYTE_MASK);
184ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
185ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
186ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return value;
187ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
188ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
189ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset)
190ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throws ProtocolException {
191ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return getPrefixedString(payload, lengthLength, charset, false);
192ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
193ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
194ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset,
195ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                                           boolean useNull) throws ProtocolException {
196ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (payload.remaining() < lengthLength) {
197ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throw new ProtocolException("Runt string: " + payload.remaining());
198ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
199ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return getString(payload, (int) getInteger(payload, ByteOrder.LITTLE_ENDIAN,
200ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                lengthLength), charset, useNull);
201ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
202ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
203ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static String getTrimmedString(ByteBuffer payload, int length, Charset charset)
204ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throws ProtocolException {
205ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        String s = getString(payload, length, charset, false);
206ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        int zero = length - 1;
207ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        while (zero >= 0) {
208ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (s.charAt(zero) != 0) {
209ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                break;
210ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
211ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            zero--;
212ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
213ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return zero < length - 1 ? s.substring(0, zero + 1) : s;
214ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
215ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
216ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static String getString(ByteBuffer payload, int length, Charset charset)
217ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throws ProtocolException {
218ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return getString(payload, length, charset, false);
219ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
220ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
221ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static String getString(ByteBuffer payload, int length, Charset charset, boolean useNull)
222ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throws ProtocolException {
223ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (length > payload.remaining()) {
224ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            throw new ProtocolException("Bad string length: " + length);
225ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
226ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (useNull && length == 0) {
227ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return null;
228ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
229ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        byte[] octets = new byte[length];
230ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        payload.get(octets);
231ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return new String(octets, charset);
232ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
233ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist}
234