Implements OIC/OCF resource models for cloud.
[platform/upstream/iotivity.git] / cloud / stack / src / main / java / org / iotivity / cloud / base / protocols / coap / CoapMessage.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2016 Samsung Electronics All Rights Reserved.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.cloud.base.protocols.coap;
23
24 import java.nio.charset.Charset;
25 import java.nio.charset.StandardCharsets;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29
30 import org.iotivity.cloud.base.protocols.Message;
31 import org.iotivity.cloud.base.protocols.enums.ContentFormat;
32 import org.iotivity.cloud.base.protocols.enums.Observe;
33 import org.iotivity.cloud.util.Bytes;
34
35 public abstract class CoapMessage extends Message {
36
37     protected byte[]       mToken         = null;
38     protected int          mObserve       = -1;
39
40     // Option fields
41     protected List<byte[]> if_match       = null;
42     protected byte[]       uri_host       = null;
43     protected List<byte[]> etag           = null;
44     protected boolean      if_none_match  = false;
45     protected byte[]       uri_port       = null;
46     protected List<byte[]> location_path  = null;
47
48     protected byte[]       max_age        = null;
49     protected byte[]       accept         = null;
50     protected List<byte[]> location_query = null;
51     protected byte[]       proxy_uri      = null;
52     protected byte[]       proxy_scheme   = null;
53     protected byte[]       size1          = null;
54     protected byte[]       content_format = null;
55
56     public CoapMessage() {
57     }
58
59     public abstract int getCode();
60
61     public void addOption(int optnum, byte[] value) {
62         switch (optnum) {
63             // IF_MATCH
64             case 1:
65                 if (if_match == null) {
66                     if_match = new ArrayList<>();
67                 }
68                 if_match.add(value);
69                 break;
70
71             // URI_HOST
72             case 3:
73                 uri_host = value;
74                 break;
75
76             // ETAG
77             case 4:
78                 if (etag == null) {
79                     etag = new ArrayList<>();
80                 }
81                 etag.add(value);
82                 break;
83
84             // IF_NONE_MATCH
85             case 5:
86                 if_none_match = true;
87                 break;
88
89             // URI_PORT
90             case 7:
91                 uri_port = value;
92                 break;
93
94             // LOCATION_PATH
95             case 8:
96                 if (location_path == null) {
97                     location_path = new ArrayList<>();
98                 }
99                 location_path.add(value);
100                 break;
101
102             // URI_PATH
103             case 11:
104                 if (uri_path == null) {
105                     uri_path = new ArrayList<>();
106                 }
107                 uri_path.add(value);
108                 break;
109
110             // CONTENT_FORMAT
111             case 12:
112                 content_format = value;
113                 break;
114
115             // MAX_AGE
116             case 14:
117                 max_age = value;
118                 break;
119
120             // URI_QUERY
121             case 15:
122                 if (uri_query == null) {
123                     uri_query = new ArrayList<>();
124                 }
125                 uri_query.add(value);
126                 break;
127
128             // ACCEPT
129             case 17:
130                 accept = value;
131                 break;
132
133             // LOCATION_QUERY
134             case 20:
135                 if (location_query == null) {
136                     location_query = new ArrayList<>();
137                 }
138                 location_query.add(value);
139                 break;
140
141             // PROXY_URI
142             case 35:
143                 proxy_uri = value;
144                 break;
145
146             // PROXY_SCHEME
147             case 39:
148                 proxy_scheme = value;
149                 break;
150
151             // SIZE1
152             case 60:
153                 size1 = value;
154                 break;
155
156             // OBSERVE
157             case 6:
158                 mObserve = Bytes.bytesToInt(value);
159                 break;
160         }
161     }
162
163     public List<byte[]> getOption(int optnum) {
164         switch (optnum) {
165             // IF_MATCH
166             case 1:
167                 return if_match;
168
169             // URI_HOST
170             case 3:
171                 return uri_host != null ? Arrays.asList(uri_host) : null;
172
173             // ETAG
174             case 4:
175                 return etag;
176
177             // IF_NONE_MATCH
178             case 5:
179                 return if_none_match == true ? new ArrayList<byte[]>() : null;
180
181             // URI_PORT
182             case 7:
183                 return uri_port != null ? Arrays.asList(uri_port) : null;
184
185             // LOCATION_PATH
186             case 8:
187                 return location_path;
188
189             // URI_PATH
190             case 11:
191                 return uri_path;
192
193             // CONTENT_FORMAT
194             case 12:
195                 return content_format != null ? Arrays.asList(content_format)
196                         : null;
197
198             // MAX_AGE
199             case 14:
200                 return max_age != null ? Arrays.asList(max_age) : null;
201
202             // URI_QUERY
203             case 15:
204                 return uri_query;
205
206             // ACCEPT
207             case 17:
208                 return accept != null ? Arrays.asList(accept) : null;
209
210             // LOCATION_QUERY
211             case 20:
212                 return location_query;
213
214             // PROXY_URI
215             case 35:
216                 return proxy_uri != null ? Arrays.asList(proxy_uri) : null;
217
218             // PROXY_SCHEME
219             case 39:
220                 return proxy_scheme != null ? Arrays.asList(proxy_scheme)
221                         : null;
222
223             // SIZE1
224             case 60:
225                 return size1 != null ? Arrays.asList(size1) : null;
226
227             // OBSERVE
228             case 6:
229                 return mObserve != -1
230                         ? Arrays.asList(Bytes.intToMax4Bytes(mObserve)) : null;
231         }
232
233         return null;
234     }
235
236     public void setPayload(byte[] payload) {
237         this.payload = payload;
238     }
239
240     public void setUriPath(String path) {
241         if (uri_path == null) {
242             uri_path = new ArrayList<>();
243         } else {
244             uri_path.clear();
245         }
246
247         if (path == null || path.length() == 0) {
248             uri_path.clear();
249             uri_path = null;
250             return;
251         }
252
253         String[] pathSegments = path.split("/");
254         for (String pathSegment : pathSegments) {
255             if (pathSegment.length() == 0)
256                 continue;
257             uri_path.add(pathSegment.getBytes(StandardCharsets.UTF_8));
258         }
259     }
260
261     public void setUriQuery(String query) {
262         if (uri_query == null) {
263             uri_query = new ArrayList<>();
264         } else {
265             uri_query.clear();
266         }
267
268         if (query == null || query.length() == 0) {
269             uri_query.clear();
270             uri_query = null;
271             return;
272         }
273
274         String[] querySegments = query.split("&");
275         for (String querySegment : querySegments) {
276             uri_query.add(querySegment.getBytes(StandardCharsets.UTF_8));
277         }
278     }
279
280     public String getPayloadString() {
281         if (payload == null)
282             return "";
283         return new String(payload, Charset.forName("UTF-8"));
284     }
285
286     public void setToken(byte[] token) {
287         mToken = token;
288     }
289
290     public byte[] getToken() {
291         return mToken;
292     }
293
294     public int getTokenLength() {
295         return mToken == null ? 0 : mToken.length;
296     }
297
298     public String getTokenString() {
299         StringBuffer strBuffer = new StringBuffer(mToken == null ? "null" : "");
300         if (mToken != null)
301             for (byte b : mToken)
302                 strBuffer.append(String.format("%02x", b & 0xff)); // hexadecimal(16)
303         return strBuffer.toString();
304     }
305
306     public String getRequestId() {
307         return getTokenString();
308     }
309
310     public void setSequenceNumber(int seqNumber) {
311         mObserve = seqNumber;
312     }
313
314     public int getSequenceNumber() {
315         return mObserve;
316     }
317
318     public int getNextSequenceNumber() {
319         int ret = mObserve++;
320
321         if (mObserve == 1 || mObserve == 16777216) {
322             mObserve = 2;
323         }
324
325         return ret;
326     }
327
328     public void setObserve(Observe observe) {
329         switch (observe) {
330             case SUBSCRIBE:
331                 mObserve = 0;
332                 break;
333
334             case UNSUBSCRIBE:
335                 mObserve = 1;
336                 break;
337
338             case NOTHING:
339                 mObserve = -1;
340                 break;
341
342             default:
343         }
344     }
345
346     @Override
347     public Observe getObserve() {
348         switch (mObserve) {
349             case -1:
350                 return Observe.NOTHING;
351
352             case 0:
353                 return Observe.SUBSCRIBE;
354
355             case 1:
356                 return Observe.UNSUBSCRIBE;
357         }
358
359         return Observe.SEQUENCE_NUMBER;
360     }
361
362     public void setContentFormat(ContentFormat format) {
363         byte value = 0;
364         switch (format) {
365             case NO_CONTENT:
366                 break;
367             case APPLICATION_LINK_FORMAT:
368                 value = 40;
369                 break;
370             case APPLICATION_XML:
371                 value = 41;
372                 break;
373             case APPLICATION_OCTET_STREAM:
374                 value = 42;
375                 break;
376             case APPLICATION_EXI:
377                 value = 47;
378                 break;
379             case APPLICATION_JSON:
380                 value = 50;
381                 break;
382             case APPLICATION_CBOR:
383                 value = 60;
384                 break;
385         }
386         content_format = new byte[] { value };
387     }
388
389     public ContentFormat getContentFormat() {
390
391         if (content_format == null) {
392             return ContentFormat.NO_CONTENT;
393         }
394
395         switch (content_format[0]) {
396             case 40:
397                 return ContentFormat.APPLICATION_LINK_FORMAT;
398
399             case 41:
400                 return ContentFormat.APPLICATION_XML;
401
402             case 42:
403                 return ContentFormat.APPLICATION_OCTET_STREAM;
404
405             case 47:
406                 return ContentFormat.APPLICATION_EXI;
407
408             case 50:
409                 return ContentFormat.APPLICATION_JSON;
410
411             case 60:
412                 return ContentFormat.APPLICATION_CBOR;
413         }
414
415         return ContentFormat.NO_CONTENT;
416     }
417 }