1 /*
2  * Copyright (c) 2017 Linaro Limited
3  * Copyright (c) 2018-2019 Foundries.io
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef LWM2M_ENGINE_H
9 #define LWM2M_ENGINE_H
10 
11 #include "lwm2m_message_handling.h"
12 #include "lwm2m_object.h"
13 #include "lwm2m_observation.h"
14 #include "lwm2m_registry.h"
15 
16 #define LWM2M_PROTOCOL_VERSION_MAJOR 1
17 #if defined(CONFIG_LWM2M_VERSION_1_1)
18 #define LWM2M_PROTOCOL_VERSION_MINOR 1
19 #else
20 #define LWM2M_PROTOCOL_VERSION_MINOR 0
21 #endif
22 
23 #define LWM2M_PROTOCOL_VERSION_STRING                                                              \
24 	STRINGIFY(LWM2M_PROTOCOL_VERSION_MAJOR)                                                    \
25 	"." STRINGIFY(LWM2M_PROTOCOL_VERSION_MINOR)
26 
27 /* Use this value to generate new token */
28 #define LWM2M_MSG_TOKEN_GENERATE_NEW 0xFFU
29 
30 /* length of time in milliseconds to wait for buffer allocations */
31 #define BUF_ALLOC_TIMEOUT K_SECONDS(1)
32 
33 /**
34  * @brief Validates that writing is a legal operation on the field given by the object in
35  * @p obj_inst and the resource id in @p msg. Returns the field to obj_field (if it exists).
36  *
37  * @param[in] msg lwm2m message to signal for which resource the write access should checked
38  * @param[in] obj_inst Engine object instance to signal which object the resource belongs to
39  * @param[out] obj_field Engine obejct field buffer pointer to store the field being checked
40  * @return 0 for successful validation and negative in all other cases
41  */
42 int lwm2m_engine_validate_write_access(struct lwm2m_message *msg,
43 				       struct lwm2m_engine_obj_inst *obj_inst,
44 				       struct lwm2m_engine_obj_field **obj_field);
45 
46 /* LwM2M context functions */
47 /**
48  * @brief Removes all observes, clears all pending coap messages and resets all messages
49  * associated with this context.
50  *
51  * @param[in] client_ctx Context to close
52  */
53 void lwm2m_engine_context_close(struct lwm2m_ctx *client_ctx);
54 
55 /**
56  * @brief Initializes a lwm2m_ctx before a socket can be associated with it.
57  *
58  * @param[in] client_ctx Context to initialize
59  */
60 void lwm2m_engine_context_init(struct lwm2m_ctx *client_ctx);
61 
62 /* Message buffer functions */
63 uint8_t *lwm2m_get_message_buf(void);
64 int lwm2m_put_message_buf(uint8_t *buf);
65 int lwm2m_perform_composite_observation_op(struct lwm2m_message *msg, uint8_t *token,
66 					   uint8_t token_length, sys_slist_t *lwm2m_path_list);
67 
68 /**
69  * @brief Checks if context has access to the object specified by @p path
70  *
71  * @param[in] client_ctx lwm2m ctx of the connection
72  * @param[in] path Path of the object
73  * @return Returns false if the bootstrap flag of @p client_ctx is not set
74  */
75 bool lwm2m_engine_bootstrap_override(struct lwm2m_ctx *client_ctx, struct lwm2m_obj_path *path);
76 
77 /**
78  * @brief Deletes the object instance specified by msg->path. If the object instance id of the
79  * path is null (i.e path.level == 1), all object instances of that object will be deleted.
80  * Should only be called if delete request comes from a bootstrap server.
81  *
82  * @param[in] msg lwm2m message with operation delete
83  * @return 0 for success or negative in case of error
84  */
85 int bootstrap_delete(struct lwm2m_message *msg);
86 
87 /**
88  * @brief Adds the periodic @p service to the work queue. The period of the service becomes
89  * @p period_ms.
90  *
91  * @param[in] service Periodic service to be added
92  * @param[in] period_ms Period of the periodic service
93  * @return 0 for success or negative in case of error
94  */
95 int lwm2m_engine_add_service(k_work_handler_t service, uint32_t period_ms);
96 
97 /**
98  * @brief Update the period of a given service or remove it.
99  *
100  * Allow the period modification on an existing service created with
101  * lwm2m_engine_add_service(). When period is zero, service is removed.
102  *
103  * @param[in] service Handler of the periodic_service
104  * @param[in] period_ms New period for the periodic_service (in milliseconds) or zero.
105  *
106  * @return 0 for success, 1 when service was removed or negative in case of error.
107  */
108 int lwm2m_engine_update_service_period(k_work_handler_t service, uint32_t period_ms);
109 
110 /**
111  * @brief Call specific service handler only once at given timestamp.
112  *
113  * @param[in] service service to be called
114  * @param[in] timestamp Time when to call
115  * @return 0 for success or negative in case of error
116  */
117 int lwm2m_engine_call_at(k_work_handler_t service, int64_t timestamp);
118 
119 /**
120  * @brief Call given handler from engine context.
121  *
122  * @param[in] service Service callback to be called.
123  * @return 0 for success or negative in case of error
124  */
125 int lwm2m_engine_call_now(k_work_handler_t service);
126 
127 /**
128  * @brief Returns the index in the security objects list corresponding to the object instance
129  * id given by @p obj_inst_id
130  *
131  * @param[in] obj_inst_id object instance id of the security instance
132  * @return index in the list or negative in case of error
133  */
134 int lwm2m_security_inst_id_to_index(uint16_t obj_inst_id);
135 
136 /**
137  * @brief Returns the object instance id of the security object instance at @p index
138  * in the security object list.
139  *
140  * @param[in] index Index in the security object list
141  * @return Object instance id of the security instance or negative in case of error
142  */
143 int lwm2m_security_index_to_inst_id(int index);
144 
145 /**
146  * @brief Returns the default minimum period for an observation set for the server
147  * with object instance id given by @p obj_inst_id.
148  *
149  * @param[in] obj_inst_id Object instance id of the server object instance
150  * @return int32_t pmin value
151  */
152 int32_t lwm2m_server_get_pmin(uint16_t obj_inst_id);
153 
154 /**
155  * @brief Returns the default maximum period for an observation set for the server
156  * with object instance id given by @p obj_inst_id.
157  *
158  * @param[in] obj_inst_id Object instance id of the server object instance
159  * @return int32_t pmax value
160  */
161 int32_t lwm2m_server_get_pmax(uint16_t obj_inst_id);
162 
163 /**
164  * @brief Returns the Short Server ID of the server object instance with
165  * object instance id given by @p obj_inst_id.
166  *
167  * @param[in] obj_inst_id Object instance id of the server object
168  * @return SSID or negative in case not found
169  */
170 int lwm2m_server_get_ssid(uint16_t obj_inst_id);
171 
172 /**
173  * @brief Returns the object instance id of the server having ssid given by @p short_id.
174  *
175  * @param[in] short_id ssid of the server object
176  * @return Object instance id or negative in case not found
177  */
178 int lwm2m_server_short_id_to_inst(uint16_t short_id);
179 
180 #if defined(CONFIG_LWM2M_SERVER_OBJECT_VERSION_1_1)
181 bool lwm2m_server_get_mute_send(uint16_t obj_inst_id);
182 #endif
183 
184 #if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT)
185 /**
186  * @brief Sets the update state (as specified in  LWM2M SPEC E.6 regarding the firmware update)
187  * of the Firmware object instance given by @p obj_inst_id to @p state.
188  * (i.e Sets the value of resource 5/ @p obj_inst_id /3)
189  *
190  * @param[in] obj_inst_id Object instance id of the firmware object instance
191  * @param[in] state (STATE_IDLE through STATE_UPDATING)
192  */
193 void lwm2m_firmware_set_update_state_inst(uint16_t obj_inst_id, uint8_t state);
194 
195 /**
196  * @brief Sets the result state (as specified in  LWM2M SPEC E.6 regarding the firmware update)
197  * of the Firmware object instance given by @p obj_inst_id to @p result.
198  * (i.e Sets the value of resource 5/ @p obj_inst_id /5)
199  *
200  * @param[in] obj_inst_id Object instance id of the firmware object instance
201  * @param[in] result (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
202  */
203 void lwm2m_firmware_set_update_result_inst(uint16_t obj_inst_id, uint8_t result);
204 
205 /**
206  * @brief Equivalent to lwm2m_firmware_set_update_state_inst(0, state).
207  *
208  * @param[in] state (STATE_IDLE through STATE_UPDATING)
209  */
210 void lwm2m_firmware_set_update_state(uint8_t state);
211 
212 /**
213  * @brief Equivalent to lwm2m_firmware_set_update_result_inst(0, result).
214  *
215  * @param[in] result (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
216  */
217 void lwm2m_firmware_set_update_result(uint8_t result);
218 
219 /**
220  * @brief Returns the update state (as specified in  LWM2M SPEC E.6 regarding the firmware update)
221  * of the Firmware object instance given by @p obj_inst_id.
222  * (i.e Gets the value of resource 5/ @p obj_inst_id /3)
223  * @param[in] obj_inst_id Object instance id of the firmware object
224  * @return (STATE_IDLE through STATE_UPDATING)
225  */
226 uint8_t lwm2m_firmware_get_update_state_inst(uint16_t obj_inst_id);
227 
228 /**
229  * @brief Equivalent to lwm2m_firmware_get_update_state_inst(0).
230  *
231  * @return (STATE_IDLE through STATE_UPDATING)
232  */
233 uint8_t lwm2m_firmware_get_update_state(void);
234 
235 /**
236  * @brief Returns the result state (as specified in  LWM2M SPEC E.6 regarding the firmware update)
237  * of the Firmware object instance given by @p obj_inst_id.
238  * (i.e Gets the value of resource 5/ @p obj_inst_id /5)
239  * @param[in] obj_inst_id Object instance id of the firmware object
240  * @return (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
241  */
242 uint8_t lwm2m_firmware_get_update_result_inst(uint16_t obj_inst_id);
243 
244 /**
245  * @brief Equivalent to lwm2m_firmware_get_update_result_inst(0).
246  *
247  * @return (RESULT_DEFAULT through RESULT_UNSUP_PROTO)
248  */
249 uint8_t lwm2m_firmware_get_update_result(void);
250 #endif
251 
252 /* Network Layer */
253 /**
254  * @brief Opens a socket for the client_ctx if it does not exist. Saves the
255  * socket file descriptor to client_ctx->sock_fd.
256  *
257  * @param[in] client_ctx lwm2m context to open a socket for
258  * @return 0 for success or negative in case of error
259  */
260 int lwm2m_open_socket(struct lwm2m_ctx *client_ctx);
261 
262 /**
263  * @brief Closes the socket with the file descriptor given by client_ctx->sock_fd.
264  * Does nothing if the context's socket is already closed.
265  *
266  * @param[in, out] client_ctx lwm2m context whose socket is to be closed
267  * @return 0 for success or negative in case of error
268  */
269 int lwm2m_close_socket(struct lwm2m_ctx *client_ctx);
270 
271 /**
272  * @brief Removes the socket with the file descriptor given by client_ctx->sock_fd from the
273  * lwm2m work loop. Keeps the socket open.
274  *
275  * @param[in, out] client_ctx lwm2m context whose socket is being suspended
276  * @return 0 for success or negative in case of error
277  */
278 int lwm2m_socket_suspend(struct lwm2m_ctx *client_ctx);
279 /**
280  * @brief Adds an existing socket to the lwm2m work loop. (The socket specified by the file
281  * descriptor in ctx->sock_fd)
282  *
283  * @param[in] ctx lwm2m context being added to the lwm2m work loop
284  * @return 0 for success or negative in case of error
285  */
286 int lwm2m_socket_add(struct lwm2m_ctx *ctx);
287 
288 /**
289  * @brief Removes a socket from the lwm2m work loop.
290  *
291  * @param[in] ctx lwm2m context to be removed from the lwm2m work loop
292  */
293 void lwm2m_socket_del(struct lwm2m_ctx *ctx);
294 
295 /**
296  * @brief Creates a socket for the @p client_ctx (if it does not exist) and adds it to
297  * the lwm2m work loop.
298  *
299  * @param client_ctx lwm2m context that the socket is being added for
300  * @return 0 for success or negative in case of error
301  */
302 int lwm2m_socket_start(struct lwm2m_ctx *client_ctx);
303 
304 /**
305  * @brief Closes the socket with file descriptor given by client_ctx->sock_fd.
306  *
307  * @param client_ctx Context whose socket is being closed
308  * @return 0 for success or negative in case of error
309  */
310 int lwm2m_socket_close(struct lwm2m_ctx *client_ctx);
311 
312 /**
313  * @brief Closes the socket connection when queue mode is enabled.
314  *
315  * @param[in, out] client_ctx lwm2m context to be closed
316  * @return 0 for success or negative in case of error
317  */
318 int lwm2m_engine_close_socket_connection(struct lwm2m_ctx *client_ctx);
319 
320 /**
321  * @brief Starts the socket of @p client_ctx. Requires CONFIG_LWM2M_DTLS_SUPPORT=y.
322  *
323  * @param[in] client_ctx lwm2m context to be re-added to the lwm2m work loop
324  * @return 0 for success or negative in case of error
325  */
326 int lwm2m_engine_connection_resume(struct lwm2m_ctx *client_ctx);
327 
328 /**
329  * @brief Moves all queued messages to pending.
330  *
331  * @param[in, out] client_ctx
332  * @return 0 for success or negative in case of error
333  */
334 int lwm2m_push_queued_buffers(struct lwm2m_ctx *client_ctx);
335 
336 /* Resources */
337 struct lwm2m_ctx **lwm2m_sock_ctx(void);
338 int lwm2m_sock_nfds(void);
339 
340 /**
341  * @brief Trigger the LwM2M engine to run.
342  *
343  * This function wakes up ongoing poll() from the socket-loop.
344  * It should be called when new transmissions are scheduled or service schedules are modified.
345  */
346 void lwm2m_engine_wake_up(void);
347 
348 #endif /* LWM2M_ENGINE_H */
349