Contiki-NG
lwm2m-object.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2018, Yanzi Networks AB.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /**
32  * \addtogroup apps
33  * @{
34  */
35 
36 /**
37  * \defgroup lwm2m An implementation of LWM2M
38  * @{
39  *
40  * This is an implementation of OMA Lightweight M2M (LWM2M).
41  */
42 
43 /**
44  * \file
45  * Header file for the LWM2M object API
46  * \author
47  * Joakim Eriksson <joakime@sics.se>
48  * Niclas Finne <nfi@sics.se>
49  */
50 
51 #ifndef LWM2M_OBJECT_H_
52 #define LWM2M_OBJECT_H_
53 
54 #include "coap.h"
55 #include "coap-observe.h"
56 
57 /* Operation permissions on the resources - read/write/execute */
58 #define LWM2M_RESOURCE_READ 0x10000
59 #define LWM2M_RESOURCE_WRITE 0x20000
60 #define LWM2M_RESOURCE_EXECUTE 0x40000
61 #define LWM2M_RESOURCE_OP_MASK 0x70000
62 
63 /* The resource id type of lwm2m objects - 16 bits for the ID - the rest
64  is flags */
65 typedef uint32_t lwm2m_resource_id_t;
66 
67 /* Defines for the resource definition array */
68 #define RO(x) (x | LWM2M_RESOURCE_READ)
69 #define WO(x) (x | LWM2M_RESOURCE_WRITE)
70 #define RW(x) (x | LWM2M_RESOURCE_READ | LWM2M_RESOURCE_WRITE)
71 #define EX(x) (x | LWM2M_RESOURCE_EXECUTE)
72 
73 #define LWM2M_OBJECT_SECURITY_ID 0
74 #define LWM2M_OBJECT_SERVER_ID 1
75 #define LWM2M_OBJECT_ACCESS_CONTROL_ID 2
76 #define LWM2M_OBJECT_DEVICE_ID 3
77 #define LWM2M_OBJECT_CONNECTIVITY_MONITORING_ID 4
78 #define LWM2M_OBJECT_FIRMWARE_ID 5
79 #define LWM2M_OBJECT_LOCATION_ID 6
80 #define LWM2M_OBJECT_CONNECTIVITY_STATISTICS_ID 7
81 
82 typedef enum {
83  LWM2M_OP_NONE,
84  LWM2M_OP_READ,
85  LWM2M_OP_DISCOVER,
86  LWM2M_OP_WRITE,
87  LWM2M_OP_WRITE_ATTR,
88  LWM2M_OP_EXECUTE,
89  LWM2M_OP_CREATE,
90  LWM2M_OP_DELETE
91 } lwm2m_operation_t;
92 
93 typedef enum {
94  LWM2M_STATUS_OK,
95 
96  /* Internal server error */
97  LWM2M_STATUS_ERROR,
98  /* Error from writer */
99  LWM2M_STATUS_WRITE_ERROR,
100  /* Error from reader */
101  LWM2M_STATUS_READ_ERROR,
102 
103  LWM2M_STATUS_BAD_REQUEST,
104  LWM2M_STATUS_UNAUTHORIZED,
105  LWM2M_STATUS_FORBIDDEN,
106  LWM2M_STATUS_NOT_FOUND,
107  LWM2M_STATUS_OPERATION_NOT_ALLOWED,
108  LWM2M_STATUS_NOT_ACCEPTABLE,
109  LWM2M_STATUS_UNSUPPORTED_CONTENT_FORMAT,
110 
111  LWM2M_STATUS_NOT_IMPLEMENTED,
112  LWM2M_STATUS_SERVICE_UNAVAILABLE,
113 } lwm2m_status_t;
114 
115 /* remember that we have already output a value - can be between two block's */
116 #define WRITER_OUTPUT_VALUE 1
117 #define WRITER_RESOURCE_INSTANCE 2
118 #define WRITER_HAS_MORE 4
119 
120 typedef struct lwm2m_reader lwm2m_reader_t;
121 typedef struct lwm2m_writer lwm2m_writer_t;
122 
123 typedef struct lwm2m_object_instance lwm2m_object_instance_t;
124 
125 typedef struct {
126  uint16_t len; /* used for current length of the data in the buffer */
127  uint16_t pos; /* position in the buffer - typically write position or similar */
128  uint16_t size;
129  uint8_t *buffer;
130 } lwm2m_buffer_t;
131 
132 /* Data model for OMA LWM2M objects */
133 typedef struct lwm2m_context {
134  uint16_t object_id;
135  uint16_t object_instance_id;
136  uint16_t resource_id;
137  uint16_t resource_instance_id;
138 
139  uint8_t resource_index;
140  uint8_t resource_instance_index; /* for use when stepping to next sub-resource if having multiple */
141  uint8_t level; /* 0/1/2/3 = 3 = resource */
142  lwm2m_operation_t operation;
143 
144  coap_message_t *request;
145  coap_message_t *response;
146 
147  unsigned int content_type;
148  lwm2m_buffer_t *outbuf;
149  lwm2m_buffer_t *inbuf;
150 
151  uint8_t out_mark_pos_oi; /* mark pos for last object instance */
152  uint8_t out_mark_pos_ri; /* mark pos for last resource instance */
153 
154  uint32_t offset; /* If we do blockwise - this needs to change */
155 
156  /* Info on last_instance read/write */
157  uint16_t last_instance;
158  uint16_t last_value_len;
159 
160  uint8_t writer_flags; /* flags for reader/writer */
161  const lwm2m_reader_t *reader;
162  const lwm2m_writer_t *writer;
163 } lwm2m_context_t;
164 
165 /* LWM2M format writer for the various formats supported */
166 struct lwm2m_writer {
167  size_t (* init_write)(lwm2m_context_t *ctx);
168  size_t (* end_write)(lwm2m_context_t *ctx);
169  /* For sub-resources */
170  size_t (* enter_resource_instance)(lwm2m_context_t *ctx);
171  size_t (* exit_resource_instance)(lwm2m_context_t *ctx);
172  size_t (* write_int)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value);
173  size_t (* write_string)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, const char *value, size_t strlen);
174  size_t (* write_float32fix)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int32_t value, int bits);
175  size_t (* write_boolean)(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, int value);
176  size_t (* write_opaque_header)(lwm2m_context_t *ctx, size_t total_size);
177 };
178 
179 struct lwm2m_reader {
180  size_t (* read_int)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value);
181  size_t (* read_string)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen);
182  size_t (* read_float32fix)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits);
183  size_t (* read_boolean)(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value);
184 };
185 
186 typedef lwm2m_status_t
187 (* lwm2m_write_opaque_callback)(lwm2m_object_instance_t *object,
188  lwm2m_context_t *ctx, int num_to_write);
189 
190 void lwm2m_engine_set_opaque_callback(lwm2m_context_t *ctx, lwm2m_write_opaque_callback cb);
191 
192 static inline void
193 lwm2m_notify_observers(char *path)
194 {
195  coap_notify_observers_sub(NULL, path);
196 }
197 
198 static inline size_t
199 lwm2m_object_read_int(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value)
200 {
201  return ctx->reader->read_int(ctx, inbuf, len, value);
202 }
203 
204 static inline size_t
205 lwm2m_object_read_string(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, uint8_t *value, size_t strlen)
206 {
207  return ctx->reader->read_string(ctx, inbuf, len, value, strlen);
208 }
209 
210 static inline size_t
211 lwm2m_object_read_float32fix(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int32_t *value, int bits)
212 {
213  return ctx->reader->read_float32fix(ctx, inbuf, len, value, bits);
214 }
215 
216 static inline size_t
217 lwm2m_object_read_boolean(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t len, int *value)
218 {
219  return ctx->reader->read_boolean(ctx, inbuf, len, value);
220 }
221 
222 static inline size_t
223 lwm2m_object_write_int(lwm2m_context_t *ctx, int32_t value)
224 {
225  size_t s;
226  s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
227  ctx->outbuf->size - ctx->outbuf->len, value);
228  ctx->outbuf->len += s;
229  return s;
230 }
231 
232 static inline size_t
233 lwm2m_object_write_string(lwm2m_context_t *ctx, const char *value, size_t strlen)
234 {
235  size_t s;
236  s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
237  ctx->outbuf->size - ctx->outbuf->len, value, strlen);
238  ctx->outbuf->len += s;
239  return s;
240 }
241 
242 static inline size_t
243 lwm2m_object_write_float32fix(lwm2m_context_t *ctx, int32_t value, int bits)
244 {
245  size_t s;
246  s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
247  ctx->outbuf->size - ctx->outbuf->len, value, bits);
248  ctx->outbuf->len += s;
249  return s;
250 }
251 
252 static inline size_t
253 lwm2m_object_write_boolean(lwm2m_context_t *ctx, int value)
254 {
255  size_t s;
256  s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
257  ctx->outbuf->size - ctx->outbuf->len, value);
258  ctx->outbuf->len += s;
259  return s;
260 }
261 
262 static inline int
263 lwm2m_object_write_opaque_stream(lwm2m_context_t *ctx, int size, lwm2m_write_opaque_callback cb)
264 {
265  /* 1. - create a header of either OPAQUE (nothing) or TLV if the format is TLV */
266  size_t s;
267  if(ctx->writer->write_opaque_header != NULL) {
268  s = ctx->writer->write_opaque_header(ctx, size);
269  ctx->outbuf->len += s;
270  } else {
271  return 0;
272  }
273  /* 2. - set the callback so that future data will be grabbed from the callback */
274  lwm2m_engine_set_opaque_callback(ctx, cb);
275  return 1;
276 }
277 
278 /* Resource instance functions (_ri)*/
279 
280 static inline size_t
281 lwm2m_object_write_enter_ri(lwm2m_context_t *ctx)
282 {
283  if(ctx->writer->enter_resource_instance != NULL) {
284  size_t s;
285  s = ctx->writer->enter_resource_instance(ctx);
286  ctx->outbuf->len += s;
287  return s;
288  }
289  return 0;
290 }
291 
292 static inline size_t
293 lwm2m_object_write_exit_ri(lwm2m_context_t *ctx)
294 {
295  if(ctx->writer->exit_resource_instance != NULL) {
296  size_t s;
297  s = ctx->writer->exit_resource_instance(ctx);
298  ctx->outbuf->len += s;
299  return s;
300  }
301  return 0;
302 }
303 
304 static inline size_t
305 lwm2m_object_write_int_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value)
306 {
307  size_t s;
308  ctx->resource_instance_id = id;
309  s = ctx->writer->write_int(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
310  ctx->outbuf->size - ctx->outbuf->len, value);
311  ctx->outbuf->len += s;
312  return s;
313 }
314 
315 static inline size_t
316 lwm2m_object_write_string_ri(lwm2m_context_t *ctx, uint16_t id, const char *value, size_t strlen)
317 {
318  size_t s;
319  ctx->resource_instance_id = id;
320  s = ctx->writer->write_string(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
321  ctx->outbuf->size - ctx->outbuf->len, value, strlen);
322  ctx->outbuf->len += s;
323  return s;
324 }
325 
326 static inline size_t
327 lwm2m_object_write_float32fix_ri(lwm2m_context_t *ctx, uint16_t id, int32_t value, int bits)
328 {
329  size_t s;
330  ctx->resource_instance_id = id;
331  s = ctx->writer->write_float32fix(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
332  ctx->outbuf->size - ctx->outbuf->len, value, bits);
333  ctx->outbuf->len += s;
334  return s;
335 }
336 
337 static inline size_t
338 lwm2m_object_write_boolean_ri(lwm2m_context_t *ctx, uint16_t id, int value)
339 {
340  size_t s;
341  ctx->resource_instance_id = id;
342  s = ctx->writer->write_boolean(ctx, &ctx->outbuf->buffer[ctx->outbuf->len],
343  ctx->outbuf->size - ctx->outbuf->len, value);
344  ctx->outbuf->len += s;
345  return s;
346 }
347 
348 static inline int
349 lwm2m_object_is_final_incoming(lwm2m_context_t *ctx)
350 {
351  uint8_t more;
352  if(coap_get_header_block1(ctx->request, NULL, &more, NULL, NULL)) {
353  return !more;
354  }
355  /* If we do not know this is final... it might not be... */
356  return 0;
357 }
358 
359 #include "lwm2m-engine.h"
360 
361 #endif /* LWM2M_OBJECT_H_ */
362 /**
363  * @}
364  * @}
365  */
CoAP module for observing resources (draft-ietf-core-observe-11).
Header file for the Contiki OMA LWM2M engine
An implementation of the Constrained Application Protocol (RFC 7252).