1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define LOG_MODULE_NAME net_lwm2m_senml_json
8 #define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
9 
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
12 
13 #include <stdio.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <inttypes.h>
17 #include <ctype.h>
18 #include <zephyr/sys/base64.h>
19 #include <zephyr/sys/slist.h>
20 #include <zephyr/data/json.h>
21 
22 #include "lwm2m_object.h"
23 #include "lwm2m_rw_senml_json.h"
24 #include "lwm2m_engine.h"
25 #include "lwm2m_util.h"
26 
27 #define BASE64_OUTPUT_MIN_LENGTH 4
28 #define BASE64_MODULO_LENGTH(x) (x % BASE64_OUTPUT_MIN_LENGTH)
29 #define BASE64_BYTES_TO_MODULO(x) (BASE64_OUTPUT_MIN_LENGTH - x)
30 
31 struct senml_string_bn_payload {
32 	const char *base_name;
33 	const char *name;
34 	const char *val_string;
35 };
36 
37 struct senml_string_payload {
38 	const char *name;
39 	const char *val_string;
40 };
41 
42 struct senml_opaque_payload {
43 	const char *name;
44 	struct json_obj_token val_opaque;
45 };
46 
47 struct senml_opaque_bn_payload {
48 	const char *base_name;
49 	const char *name;
50 	struct json_obj_token val_opaque;
51 };
52 
53 struct senml_boolean_payload {
54 	const char *name;
55 	bool val_bool;
56 };
57 
58 struct senml_boolean_t_payload {
59 	const char *name;
60 	bool val_bool;
61 	struct json_obj_token time;
62 };
63 
64 struct senml_boolean_bn_payload {
65 	const char *base_name;
66 	const char *name;
67 	bool val_bool;
68 };
69 
70 struct senml_boolean_bn_t_payload {
71 	const char *base_name;
72 	const char *name;
73 	bool val_bool;
74 	struct json_obj_token base_time;
75 };
76 
77 struct senml_float_payload {
78 	const char *name;
79 	struct json_obj_token val_float;
80 };
81 
82 struct senml_float_t_payload {
83 	const char *name;
84 	struct json_obj_token val_float;
85 	struct json_obj_token time;
86 };
87 
88 struct senml_float_bn_payload {
89 	const char *base_name;
90 	const char *name;
91 	struct json_obj_token val_float;
92 };
93 
94 struct senml_float_bn_t_payload {
95 	const char *base_name;
96 	const char *name;
97 	struct json_obj_token val_float;
98 	struct json_obj_token base_time;
99 };
100 
101 struct senml_json_object {
102 	union {
103 		struct senml_float_payload  float_obj;
104 		struct senml_float_t_payload float_t_obj;
105 		struct senml_float_bn_payload float_bn_obj;
106 		struct senml_float_bn_t_payload float_bn_t_obj;
107 		struct senml_boolean_payload boolean_obj;
108 		struct senml_boolean_t_payload boolean_t_obj;
109 		struct senml_boolean_bn_payload boolean_bn_obj;
110 		struct senml_boolean_bn_t_payload boolean_bn_t_obj;
111 		struct senml_opaque_payload  opaque_obj;
112 		struct senml_opaque_bn_payload  opaque_bn_obj;
113 		struct senml_string_payload string_obj;
114 		struct senml_string_bn_payload string_bn_obj;
115 	} obj;
116 };
117 
118 struct json_out_formatter_data {
119 	uint8_t writer_flags;
120 	struct lwm2m_obj_path base_name;
121 	bool add_base_name_to_start;
122 	bool historical_data;
123 	char bn_string[sizeof("/65535/65535/") + 1];
124 	char name_string[sizeof("/65535/65535/") + 1];
125 	char timestamp_buffer[42];
126 	int timestamp_length;
127 	time_t base_time;
128 	struct senml_json_object json;
129 	struct lwm2m_output_context *out;
130 };
131 
132 /* Decode payload structure */
133 struct senml_context {
134 	const char *base_name;
135 	const char *name;
136 	char *val_object_link;
137 	const char *val_string;
138 	struct json_obj_token val_opaque;
139 	struct json_obj_token val_float;
140 	bool val_bool;
141 };
142 
143 /* Decode description structure for parsing LwM2m SenML-JSON object*/
144 static const struct json_obj_descr senml_descr[] = {
145 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_context, "bn",
146 				  base_name, JSON_TOK_STRING),
147 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_context, "n",
148 				  name, JSON_TOK_STRING),
149 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_context, "v",
150 				  val_float, JSON_TOK_FLOAT),
151 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_context, "vb",
152 				  val_bool, JSON_TOK_TRUE),
153 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_context, "vlo",
154 				  val_object_link, JSON_TOK_STRING),
155 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_context, "vd",
156 				  val_opaque, JSON_TOK_OPAQUE),
157 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_context, "vs",
158 				  val_string, JSON_TOK_STRING),
159 };
160 
161 #define	JSON_BN_TYPE	1
162 #define	JSON_N_TYPE	2
163 #define	JSON_V_TYPE	4
164 #define	JSON_VB_TYPE	8
165 #define	JSON_VLO_TYPE	16
166 #define	JSON_VD_TYPE	32
167 #define	JSON_VS_TYPE	64
168 
169 #define JSON_NAME_MASK (JSON_BN_TYPE + JSON_N_TYPE)
170 #define JSON_VALUE_MASK	(JSON_V_TYPE + JSON_VB_TYPE + JSON_VLO_TYPE + JSON_VD_TYPE + JSON_VS_TYPE)
171 
172 #define JSON_BIT_CHECK(mask, x) (mask & x)
173 
174 static const struct json_obj_descr senml_float_bn_descr[] = {
175 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_bn_payload, "bn",
176 				  base_name, JSON_TOK_STRING),
177 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_bn_payload, "n",
178 				  name, JSON_TOK_STRING),
179 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_bn_payload, "v",
180 				  val_float, JSON_TOK_FLOAT),
181 };
182 
183 static const struct json_obj_descr senml_float_bn_t_descr[] = {
184 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_bn_t_payload, "bn",
185 				  base_name, JSON_TOK_STRING),
186 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_bn_t_payload, "bt",
187 				  base_time, JSON_TOK_FLOAT),
188 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_bn_t_payload, "n",
189 				  name, JSON_TOK_STRING),
190 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_bn_t_payload, "v",
191 				  val_float, JSON_TOK_FLOAT),
192 };
193 
194 static const struct json_obj_descr senml_float_descr[] = {
195 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_payload, "n",
196 				  name, JSON_TOK_STRING),
197 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_payload, "v",
198 				  val_float, JSON_TOK_FLOAT),
199 };
200 
201 static const struct json_obj_descr senml_float_t_descr[] = {
202 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_t_payload, "n",
203 				  name, JSON_TOK_STRING),
204 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_t_payload, "v",
205 				  val_float, JSON_TOK_FLOAT),
206 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_float_t_payload, "t",
207 				  time, JSON_TOK_FLOAT),
208 };
209 
210 static const struct json_obj_descr senml_boolean_bn_descr[] = {
211 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_bn_payload, "bn",
212 				  base_name, JSON_TOK_STRING),
213 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_bn_payload, "n",
214 				  name, JSON_TOK_STRING),
215 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_bn_payload, "vb",
216 				  val_bool, JSON_TOK_TRUE),
217 };
218 
219 static const struct json_obj_descr senml_boolean_bn_t_descr[] = {
220 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_bn_t_payload, "bn",
221 				  base_name, JSON_TOK_STRING),
222 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_bn_t_payload, "bt",
223 				  base_time, JSON_TOK_FLOAT),
224 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_bn_t_payload, "n",
225 				  name, JSON_TOK_STRING),
226 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_bn_t_payload, "vb",
227 				  val_bool, JSON_TOK_TRUE),
228 };
229 
230 static const struct json_obj_descr senml_boolean_descr[] = {
231 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_payload, "n",
232 				  name, JSON_TOK_STRING),
233 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_payload, "vb",
234 				  val_bool, JSON_TOK_TRUE),
235 };
236 
237 static const struct json_obj_descr senml_boolean_t_descr[] = {
238 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_t_payload, "n",
239 				  name, JSON_TOK_STRING),
240 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_t_payload, "vb",
241 				  val_bool, JSON_TOK_TRUE),
242 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_boolean_t_payload, "t",
243 				  time, JSON_TOK_FLOAT),
244 };
245 
246 static const struct json_obj_descr senml_obj_lnk_bn_descr[] = {
247 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_bn_payload, "bn",
248 				  base_name, JSON_TOK_STRING),
249 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_bn_payload, "n",
250 				  name, JSON_TOK_STRING),
251 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_bn_payload, "vlo",
252 				  val_string, JSON_TOK_STRING),
253 };
254 
255 static const struct json_obj_descr senml_obj_lnk_descr[] = {
256 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_payload, "n",
257 				  name, JSON_TOK_STRING),
258 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_payload, "vlo",
259 				  val_string, JSON_TOK_STRING),
260 };
261 
262 static const struct json_obj_descr senml_opaque_bn_descr[] = {
263 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_opaque_bn_payload, "bn",
264 				  base_name, JSON_TOK_STRING),
265 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_opaque_bn_payload, "n",
266 				  name, JSON_TOK_STRING),
267 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_opaque_bn_payload, "vd",
268 				  val_opaque, JSON_TOK_OPAQUE),
269 };
270 
271 static const struct json_obj_descr senml_opaque_descr[] = {
272 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_opaque_payload, "n",
273 				  name, JSON_TOK_STRING),
274 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_opaque_payload, "vd",
275 				  val_opaque, JSON_TOK_OPAQUE),
276 };
277 
278 static const struct json_obj_descr senml_string_bn_descr[] = {
279 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_bn_payload, "bn",
280 				  base_name, JSON_TOK_STRING),
281 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_bn_payload, "n",
282 				  name, JSON_TOK_STRING),
283 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_bn_payload, "vs",
284 				  val_string, JSON_TOK_STRING),
285 };
286 
287 static const struct json_obj_descr senml_string_descr[] = {
288 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_payload, "n",
289 				  name, JSON_TOK_STRING),
290 	JSON_OBJ_DESCR_PRIM_NAMED(struct senml_string_payload, "vs",
291 				  val_string, JSON_TOK_STRING),
292 };
293 
294 struct json_in_formatter_data {
295 	int object_bit_field;
296 	struct senml_context senml_object;
297 };
298 
299 /* some temporary buffer space for format conversions */
300 static char pt_buffer[42];
301 
init_object_name_parameters(struct json_out_formatter_data * fd,struct lwm2m_obj_path * path)302 static int init_object_name_parameters(struct json_out_formatter_data *fd,
303 				       struct lwm2m_obj_path *path)
304 {
305 	int ret;
306 
307 	if (fd->add_base_name_to_start) {
308 		/* Init Base name string */
309 		ret = snprintk(fd->bn_string, sizeof(fd->bn_string), "/%u/%u/", path->obj_id,
310 			       path->obj_inst_id);
311 		if (ret < 0) {
312 			return ret;
313 		}
314 	}
315 
316 	/* Init Name string */
317 	if (fd->writer_flags & WRITER_RESOURCE_INSTANCE) {
318 		ret = snprintk(fd->name_string, sizeof(fd->name_string), "%u/%u", path->res_id,
319 			       path->res_inst_id);
320 	} else {
321 		ret = snprintk(fd->name_string, sizeof(fd->name_string), "%u", path->res_id);
322 	}
323 
324 	if (ret < 0) {
325 		return ret;
326 	}
327 
328 	return 0;
329 }
330 
put_begin(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)331 static int put_begin(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
332 {
333 	int res;
334 	struct json_out_formatter_data *fd;
335 
336 	fd = engine_get_out_user_data(out);
337 	if (!fd) {
338 		return -EINVAL;
339 	}
340 
341 	res = buf_append(CPKT_BUF_WRITE(out->out_cpkt), "[", 1);
342 	if (res < 0) {
343 		return res;
344 	}
345 
346 	/* Init base level state for skip first object instance compare */
347 	fd->base_name.level = LWM2M_PATH_LEVEL_NONE;
348 	return 1;
349 }
350 
put_end(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)351 static int put_end(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
352 {
353 	struct json_out_formatter_data *fd;
354 	int res;
355 
356 	fd = engine_get_out_user_data(out);
357 	if (!fd) {
358 		return -EINVAL;
359 	}
360 
361 	res = buf_append(CPKT_BUF_WRITE(out->out_cpkt), "]", 1);
362 	if (res < 0) {
363 		return res;
364 	}
365 
366 	return 1;
367 }
368 
put_begin_oi(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)369 static int put_begin_oi(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
370 {
371 	struct json_out_formatter_data *fd;
372 	bool update_base_name = false;
373 
374 	fd = engine_get_out_user_data(out);
375 	if (!fd) {
376 		return -EINVAL;
377 	}
378 
379 	if (fd->base_name.level == LWM2M_PATH_LEVEL_NONE) {
380 		update_base_name = true;
381 
382 	} else if (fd->base_name.obj_id != path->obj_id ||
383 		   fd->base_name.obj_inst_id != path->obj_inst_id) {
384 		update_base_name = true;
385 	}
386 
387 	if (update_base_name) {
388 		fd->base_name.level = LWM2M_PATH_LEVEL_OBJECT_INST;
389 		fd->base_name.obj_id = path->obj_id;
390 		fd->base_name.obj_inst_id = path->obj_inst_id;
391 	}
392 
393 	fd->add_base_name_to_start = update_base_name;
394 
395 	return 0;
396 }
397 
put_begin_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)398 static int put_begin_ri(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
399 {
400 	struct json_out_formatter_data *fd;
401 
402 	fd = engine_get_out_user_data(out);
403 	if (!fd) {
404 		return -EINVAL;
405 	}
406 
407 	fd->writer_flags |= WRITER_RESOURCE_INSTANCE;
408 	return 0;
409 }
410 
put_end_ri(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)411 static int put_end_ri(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
412 {
413 	struct json_out_formatter_data *fd;
414 
415 	fd = engine_get_out_user_data(out);
416 	if (!fd) {
417 		return -EINVAL;
418 	}
419 
420 	fd->writer_flags &= ~WRITER_RESOURCE_INSTANCE;
421 	return 0;
422 }
423 
put_end_r(struct lwm2m_output_context * out,struct lwm2m_obj_path * path)424 static int put_end_r(struct lwm2m_output_context *out, struct lwm2m_obj_path *path)
425 {
426 	struct json_out_formatter_data *fd;
427 
428 	fd = engine_get_out_user_data(out);
429 	if (!fd) {
430 		return -EINVAL;
431 	}
432 
433 	/* Clear Historical Data */
434 	fd->historical_data = false;
435 	fd->base_time = 0;
436 	return 0;
437 }
438 
number_to_string(char * buf,size_t buf_len,const char * format,...)439 static int number_to_string(char *buf, size_t buf_len, const char *format, ...)
440 {
441 	va_list vargs;
442 	int n;
443 
444 	va_start(vargs, format);
445 	n = vsnprintk(buf, buf_len, format, vargs);
446 	va_end(vargs);
447 	if (n < 0 || n >= buf_len) {
448 		return -EINVAL;
449 	}
450 
451 	return n;
452 }
453 
454 
float_to_string(double * value)455 static int float_to_string(double *value)
456 {
457 	int len;
458 
459 	len = lwm2m_ftoa(value, pt_buffer, sizeof(pt_buffer), 15);
460 	if (len < 0 || len >= sizeof(pt_buffer)) {
461 		LOG_ERR("Failed to encode float value");
462 		return -EINVAL;
463 	}
464 
465 	return len;
466 }
467 
objlnk_to_string(struct lwm2m_objlnk * value)468 static int objlnk_to_string(struct lwm2m_objlnk *value)
469 {
470 	return snprintk(pt_buffer, sizeof(pt_buffer), "%u:%u", value->obj_id, value->obj_inst);
471 }
472 
json_add_separator(struct lwm2m_output_context * out,struct json_out_formatter_data * fd)473 static int json_add_separator(struct lwm2m_output_context *out, struct json_out_formatter_data *fd)
474 {
475 	int len = 0;
476 
477 	if (fd->writer_flags & WRITER_OUTPUT_VALUE) {
478 		/* Add separator */
479 		char separator = ',';
480 
481 		len = buf_append(CPKT_BUF_WRITE(out->out_cpkt), &separator, sizeof(separator));
482 		if (len < 0) {
483 			return -ENOMEM;
484 		}
485 	}
486 
487 	return len;
488 }
489 
json_postprefix(struct json_out_formatter_data * fd)490 static void json_postprefix(struct json_out_formatter_data *fd)
491 {
492 	fd->writer_flags |= WRITER_OUTPUT_VALUE;
493 	fd->add_base_name_to_start = false;
494 }
495 
json_float_object_write(struct lwm2m_output_context * out,struct json_out_formatter_data * fd,int float_string_length)496 static int json_float_object_write(struct lwm2m_output_context *out,
497 				   struct json_out_formatter_data *fd, int float_string_length)
498 {
499 	int res, len;
500 	ssize_t o_len;
501 	const struct json_obj_descr *descr;
502 	size_t descr_len;
503 	void *obj_payload;
504 
505 	len = json_add_separator(out, fd);
506 	if (len < 0) {
507 		return len;
508 	}
509 
510 	if (fd->add_base_name_to_start) {
511 		if (fd->historical_data) {
512 			descr = senml_float_bn_t_descr;
513 			descr_len = ARRAY_SIZE(senml_float_bn_t_descr);
514 			obj_payload = &fd->json.obj.float_bn_t_obj;
515 			fd->json.obj.float_bn_t_obj.base_name = fd->bn_string;
516 			fd->json.obj.float_bn_t_obj.name = fd->name_string;
517 			fd->json.obj.float_bn_t_obj.val_float.start = pt_buffer;
518 			fd->json.obj.float_bn_t_obj.val_float.length = float_string_length;
519 			fd->json.obj.float_bn_t_obj.base_time.start = fd->timestamp_buffer;
520 			fd->json.obj.float_bn_t_obj.base_time.length = fd->timestamp_length;
521 		} else {
522 			descr = senml_float_bn_descr;
523 			descr_len = ARRAY_SIZE(senml_float_bn_descr);
524 			obj_payload = &fd->json.obj.float_bn_obj;
525 			fd->json.obj.float_bn_obj.base_name = fd->bn_string;
526 			fd->json.obj.float_bn_obj.name = fd->name_string;
527 			fd->json.obj.float_bn_obj.val_float.start = pt_buffer;
528 			fd->json.obj.float_bn_obj.val_float.length = float_string_length;
529 		}
530 
531 	} else {
532 		if (fd->historical_data) {
533 			descr = senml_float_t_descr;
534 			descr_len = ARRAY_SIZE(senml_float_t_descr);
535 			obj_payload = &fd->json.obj.float_t_obj;
536 			fd->json.obj.float_t_obj.name = fd->name_string;
537 			fd->json.obj.float_t_obj.val_float.start = pt_buffer;
538 			fd->json.obj.float_t_obj.val_float.length = float_string_length;
539 			fd->json.obj.float_t_obj.time.start = fd->timestamp_buffer;
540 			fd->json.obj.float_t_obj.time.length = fd->timestamp_length;
541 		} else {
542 			descr = senml_float_descr;
543 			descr_len = ARRAY_SIZE(senml_float_descr);
544 			obj_payload = &fd->json.obj.float_obj;
545 			fd->json.obj.float_obj.name = fd->name_string;
546 			fd->json.obj.float_obj.val_float.start = pt_buffer;
547 			fd->json.obj.float_obj.val_float.length = float_string_length;
548 		}
549 	}
550 
551 	/* Calculate length */
552 	o_len = json_calc_encoded_len(descr, descr_len, obj_payload);
553 	if (o_len < 0) {
554 		return -EINVAL;
555 	}
556 
557 	/* Encode */
558 	res = json_obj_encode_buf(descr, descr_len, obj_payload,
559 				  CPKT_BUF_W_REGION(out->out_cpkt));
560 	if (res < 0) {
561 		return -ENOMEM;
562 	}
563 
564 	len += o_len;
565 	out->out_cpkt->offset += len;
566 	json_postprefix(fd);
567 	return len;
568 }
569 
json_string_object_write(struct lwm2m_output_context * out,struct json_out_formatter_data * fd,char * buf)570 static int json_string_object_write(struct lwm2m_output_context *out,
571 				    struct json_out_formatter_data *fd, char *buf)
572 {
573 	int res, len;
574 	ssize_t o_len;
575 	const struct json_obj_descr *descr;
576 	size_t descr_len;
577 	void *obj_payload;
578 
579 	len = json_add_separator(out, fd);
580 	if (len < 0) {
581 		return len;
582 	}
583 
584 	if (fd->add_base_name_to_start) {
585 		descr = senml_string_bn_descr;
586 		descr_len = ARRAY_SIZE(senml_string_bn_descr);
587 		obj_payload = &fd->json.obj.string_bn_obj;
588 		fd->json.obj.string_bn_obj.base_name = fd->bn_string;
589 		fd->json.obj.string_bn_obj.name = fd->name_string;
590 		fd->json.obj.string_bn_obj.val_string = buf;
591 
592 	} else {
593 		descr = senml_string_descr;
594 		descr_len = ARRAY_SIZE(senml_string_descr);
595 		obj_payload = &fd->json.obj.string_obj;
596 		fd->json.obj.string_obj.name = fd->name_string;
597 		fd->json.obj.string_obj.val_string = buf;
598 	}
599 
600 	/* Calculate length */
601 	o_len = json_calc_encoded_len(descr, descr_len, obj_payload);
602 	if (o_len < 0) {
603 		return -EINVAL;
604 	}
605 
606 	/* Encode */
607 	res = json_obj_encode_buf(descr, descr_len, obj_payload,
608 				  CPKT_BUF_W_REGION(out->out_cpkt));
609 	if (res < 0) {
610 		return -ENOMEM;
611 	}
612 
613 	len += o_len;
614 	out->out_cpkt->offset += len;
615 	json_postprefix(fd);
616 	return len;
617 }
618 
json_boolean_object_write(struct lwm2m_output_context * out,struct json_out_formatter_data * fd,bool value)619 static int json_boolean_object_write(struct lwm2m_output_context *out,
620 				     struct json_out_formatter_data *fd, bool value)
621 {
622 	int res, len;
623 	ssize_t o_len;
624 	const struct json_obj_descr *descr;
625 	size_t descr_len;
626 	void *obj_payload;
627 
628 	len = json_add_separator(out, fd);
629 	if (len < 0) {
630 		return len;
631 	}
632 
633 	if (fd->add_base_name_to_start) {
634 		if (fd->historical_data) {
635 			descr = senml_boolean_bn_t_descr;
636 			descr_len = ARRAY_SIZE(senml_boolean_bn_t_descr);
637 			obj_payload = &fd->json.obj.boolean_bn_t_obj;
638 			fd->json.obj.boolean_bn_t_obj.base_name = fd->bn_string;
639 			fd->json.obj.boolean_bn_t_obj.name = fd->name_string;
640 			fd->json.obj.boolean_bn_t_obj.base_time.start = fd->timestamp_buffer;
641 			fd->json.obj.boolean_bn_t_obj.base_time.length = fd->timestamp_length;
642 			fd->json.obj.boolean_bn_t_obj.val_bool = value;
643 		} else {
644 			descr = senml_boolean_bn_descr;
645 			descr_len = ARRAY_SIZE(senml_boolean_bn_descr);
646 			obj_payload = &fd->json.obj.boolean_bn_obj;
647 			fd->json.obj.boolean_bn_obj.base_name = fd->bn_string;
648 			fd->json.obj.boolean_bn_obj.name = fd->name_string;
649 			fd->json.obj.boolean_bn_obj.val_bool = value;
650 		}
651 
652 	} else {
653 		if (fd->historical_data) {
654 			descr = senml_boolean_t_descr;
655 			descr_len = ARRAY_SIZE(senml_boolean_t_descr);
656 			obj_payload = &fd->json.obj.boolean_t_obj;
657 			fd->json.obj.boolean_t_obj.name = fd->name_string;
658 			fd->json.obj.boolean_t_obj.time.start = fd->timestamp_buffer;
659 			fd->json.obj.boolean_t_obj.time.length = fd->timestamp_length;
660 			fd->json.obj.boolean_t_obj.val_bool = value;
661 		} else {
662 			descr = senml_boolean_descr;
663 			descr_len = ARRAY_SIZE(senml_boolean_descr);
664 			obj_payload = &fd->json.obj.boolean_obj;
665 			fd->json.obj.boolean_obj.name = fd->name_string;
666 			fd->json.obj.boolean_obj.val_bool = value;
667 		}
668 	}
669 
670 	/* Calculate length */
671 	o_len = json_calc_encoded_len(descr, descr_len, obj_payload);
672 	if (o_len < 0) {
673 		return -EINVAL;
674 	}
675 
676 	/* Encode */
677 	res = json_obj_encode_buf(descr, descr_len, obj_payload,
678 				  CPKT_BUF_W_REGION(out->out_cpkt));
679 	if (res < 0) {
680 		return -ENOMEM;
681 	}
682 
683 	len += o_len;
684 	out->out_cpkt->offset += len;
685 	json_postprefix(fd);
686 	return len;
687 }
688 
json_objlnk_object_write(struct lwm2m_output_context * out,struct json_out_formatter_data * fd)689 static int json_objlnk_object_write(struct lwm2m_output_context *out,
690 				    struct json_out_formatter_data *fd)
691 {
692 	int res, len;
693 	ssize_t o_len;
694 	const struct json_obj_descr *descr;
695 	size_t descr_len;
696 	void *obj_payload;
697 
698 	len = json_add_separator(out, fd);
699 	if (len < 0) {
700 		return len;
701 	}
702 
703 	if (fd->add_base_name_to_start) {
704 		descr = senml_obj_lnk_bn_descr;
705 		descr_len = ARRAY_SIZE(senml_obj_lnk_bn_descr);
706 		obj_payload = &fd->json.obj.string_bn_obj;
707 		fd->json.obj.string_bn_obj.base_name = fd->bn_string;
708 		fd->json.obj.string_bn_obj.name = fd->name_string;
709 		fd->json.obj.string_bn_obj.val_string = pt_buffer;
710 
711 	} else {
712 		descr = senml_obj_lnk_descr;
713 		descr_len = ARRAY_SIZE(senml_obj_lnk_descr);
714 		obj_payload = &fd->json.obj.string_obj;
715 		fd->json.obj.string_obj.name = fd->name_string;
716 		fd->json.obj.string_obj.val_string = pt_buffer;
717 	}
718 
719 	/* Calculate length */
720 	o_len = json_calc_encoded_len(descr, descr_len, obj_payload);
721 	if (o_len < 0) {
722 		return -EINVAL;
723 	}
724 
725 	/* Encode */
726 	res = json_obj_encode_buf(descr, descr_len, obj_payload,
727 				  CPKT_BUF_W_REGION(out->out_cpkt));
728 	if (res < 0) {
729 		return -ENOMEM;
730 	}
731 
732 	len += o_len;
733 	out->out_cpkt->offset += len;
734 	json_postprefix(fd);
735 	return len;
736 }
737 
put_s32(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int32_t value)738 static int put_s32(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int32_t value)
739 {
740 	struct json_out_formatter_data *fd;
741 	int len = 0;
742 
743 	fd = engine_get_out_user_data(out);
744 
745 	if (!out->out_cpkt || !fd) {
746 		return -EINVAL;
747 	}
748 
749 	if (init_object_name_parameters(fd, path)) {
750 		return -EINVAL;
751 	}
752 
753 	len = number_to_string(pt_buffer, sizeof(pt_buffer), "%d", value);
754 	if (len < 0) {
755 		return len;
756 	}
757 
758 	return json_float_object_write(out, fd, len);
759 }
760 
put_s16(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int16_t value)761 static int put_s16(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int16_t value)
762 {
763 	return put_s32(out, path, (int32_t)value);
764 }
765 
put_s8(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int8_t value)766 static int put_s8(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int8_t value)
767 {
768 	return put_s32(out, path, (int32_t)value);
769 }
770 
put_s64(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,int64_t value)771 static int put_s64(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int64_t value)
772 {
773 	struct json_out_formatter_data *fd;
774 	int len;
775 
776 	fd = engine_get_out_user_data(out);
777 
778 	if (!out->out_cpkt || !fd) {
779 		return -EINVAL;
780 	}
781 
782 	if (init_object_name_parameters(fd, path)) {
783 		return -EINVAL;
784 	}
785 
786 	len = number_to_string(pt_buffer, sizeof(pt_buffer), "%lld", value);
787 	if (len < 0) {
788 		return len;
789 	}
790 
791 	return json_float_object_write(out, fd, len);
792 }
793 
put_time(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,time_t value)794 static int put_time(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, time_t value)
795 {
796 	return put_s64(out, path, (int64_t)value);
797 }
798 
put_string(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)799 static int put_string(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, char *buf,
800 			 size_t buflen)
801 {
802 	struct json_out_formatter_data *fd;
803 
804 	fd = engine_get_out_user_data(out);
805 
806 	if (!out->out_cpkt || !fd) {
807 		return -EINVAL;
808 	}
809 
810 	if (init_object_name_parameters(fd, path)) {
811 		return -EINVAL;
812 	}
813 
814 	return json_string_object_write(out, fd, buf);
815 
816 }
817 
put_float(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,double * value)818 static int put_float(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
819 			     double  *value)
820 {
821 	struct json_out_formatter_data *fd;
822 	int len;
823 
824 	fd = engine_get_out_user_data(out);
825 
826 	if (!out->out_cpkt || !fd) {
827 		return -EINVAL;
828 	}
829 
830 	if (init_object_name_parameters(fd, path)) {
831 		return -EINVAL;
832 	}
833 
834 	len = float_to_string(value);
835 	if (len < 0) {
836 		return len;
837 	}
838 
839 	return json_float_object_write(out, fd, len);
840 }
841 
put_bool(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,bool value)842 static int put_bool(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, bool value)
843 {
844 	struct json_out_formatter_data *fd;
845 
846 	fd = engine_get_out_user_data(out);
847 
848 	if (!out->out_cpkt || !fd) {
849 		return -EINVAL;
850 	}
851 
852 	if (init_object_name_parameters(fd, path)) {
853 		return -EINVAL;
854 	}
855 
856 	return json_boolean_object_write(out, fd, value);
857 }
858 
859 #define SEN_BASE64_SIZE_T_MAX	((size_t) -1)
860 
861 /*
862  * Encode a buffer into base64 format
863  */
base64_encoded_length(size_t slen)864 static size_t base64_encoded_length(size_t slen)
865 {
866 	size_t n;
867 
868 	if (slen == 0) {
869 		return 0;
870 	}
871 
872 	n = slen / 3 + (slen % 3 != 0);
873 
874 	if (n > (SEN_BASE64_SIZE_T_MAX - 1) / 4) {
875 		return -ENOMEM;
876 	}
877 
878 	n *= 4;
879 	return  n;
880 }
881 
json_base64_encode_data(struct json_out_formatter_data * fd,const char * buf)882 static bool json_base64_encode_data(struct json_out_formatter_data *fd, const char *buf)
883 {
884 	if (fd->add_base_name_to_start) {
885 		if (fd->json.obj.opaque_bn_obj.val_opaque.start == buf) {
886 			return true;
887 		}
888 	} else if (fd->json.obj.opaque_obj.val_opaque.start == buf) {
889 		return true;
890 	}
891 	return false;
892 }
893 
json_append_bytes_base64(const char * bytes,size_t len,void * data)894 static int json_append_bytes_base64(const char *bytes, size_t len, void *data)
895 {
896 	struct json_out_formatter_data *fd = data;
897 	struct lwm2m_output_context *out;
898 	size_t temp_length = 0;
899 
900 	out = fd->out;
901 
902 	if (json_base64_encode_data(fd, bytes)) {
903 		if (base64_encode(CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt),
904 				  &temp_length, bytes, len)) {
905 			/* No space available for base64 data */
906 			return -ENOMEM;
907 		}
908 		/* Update Data offset */
909 		out->out_cpkt->offset += temp_length;
910 	} else {
911 		if (buf_append(CPKT_BUF_WRITE(fd->out->out_cpkt), bytes, len) < 0) {
912 			return -ENOMEM;
913 		}
914 	}
915 
916 	return 0;
917 }
918 
put_opaque(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)919 static int put_opaque(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, char *buf,
920 			 size_t buflen)
921 {
922 	struct json_out_formatter_data *fd;
923 	int res, len;
924 	ssize_t o_len, encoded_length;
925 	const struct json_obj_descr *descr;
926 	size_t descr_len;
927 	void *obj_payload;
928 
929 	fd = engine_get_out_user_data(out);
930 
931 	if (!out->out_cpkt || !fd) {
932 		return -EINVAL;
933 	}
934 
935 	if (init_object_name_parameters(fd, path)) {
936 		return -EINVAL;
937 	}
938 
939 	encoded_length = base64_encoded_length(buflen);
940 	if (encoded_length < 0) {
941 		return -ENOMEM;
942 	}
943 
944 	len = json_add_separator(out, fd);
945 	if (len < 0) {
946 		return len;
947 	}
948 
949 	if (fd->add_base_name_to_start) {
950 		descr = senml_opaque_bn_descr;
951 		descr_len = ARRAY_SIZE(senml_opaque_bn_descr);
952 		obj_payload = &fd->json.obj.opaque_bn_obj;
953 		fd->json.obj.opaque_bn_obj.base_name = fd->bn_string;
954 		fd->json.obj.opaque_bn_obj.name = fd->name_string;
955 		fd->json.obj.opaque_bn_obj.val_opaque.start = buf;
956 		fd->json.obj.opaque_bn_obj.val_opaque.length = encoded_length;
957 	} else {
958 		descr = senml_opaque_descr;
959 		descr_len = ARRAY_SIZE(senml_opaque_descr);
960 		obj_payload = &fd->json.obj.opaque_obj;
961 		fd->json.obj.opaque_obj.name = fd->name_string;
962 		fd->json.obj.opaque_obj.val_opaque.start = buf;
963 		fd->json.obj.opaque_obj.val_opaque.length = encoded_length;
964 	}
965 	/* Store Out context pointer for data write */
966 	fd->out = out;
967 
968 	/* Calculate length */
969 	o_len = json_calc_encoded_len(descr, descr_len, obj_payload);
970 	if (o_len < 0) {
971 		return -EINVAL;
972 	}
973 
974 	/* Put Original payload length back */
975 	if (fd->add_base_name_to_start) {
976 		fd->json.obj.opaque_bn_obj.val_opaque.length = buflen;
977 	} else {
978 		fd->json.obj.opaque_obj.val_opaque.length = buflen;
979 	}
980 
981 	/* Encode */
982 	res = json_obj_encode(descr, descr_len, obj_payload, json_append_bytes_base64, fd);
983 	if (res < 0) {
984 		return -ENOMEM;
985 	}
986 
987 	json_postprefix(fd);
988 	len += o_len;
989 	return len;
990 
991 }
992 
put_objlnk(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,struct lwm2m_objlnk * value)993 static int put_objlnk(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
994 			 struct lwm2m_objlnk *value)
995 {
996 	struct json_out_formatter_data *fd;
997 
998 	fd = engine_get_out_user_data(out);
999 
1000 	if (!out->out_cpkt || !fd) {
1001 		return -EINVAL;
1002 	}
1003 
1004 	if (init_object_name_parameters(fd, path)) {
1005 		return -EINVAL;
1006 	}
1007 
1008 	if (objlnk_to_string(value) < 0) {
1009 		return -EINVAL;
1010 	}
1011 
1012 	return json_objlnk_object_write(out, fd);
1013 }
1014 
read_int(struct lwm2m_input_context * in,int64_t * value,bool accept_sign)1015 static int read_int(struct lwm2m_input_context *in, int64_t *value, bool accept_sign)
1016 {
1017 	struct json_in_formatter_data *fd;
1018 	const uint8_t *buf;
1019 	size_t i = 0;
1020 	bool neg = false;
1021 	char c;
1022 
1023 	/* initialize values to 0 */
1024 	*value = 0;
1025 
1026 	fd = engine_get_in_user_data(in);
1027 	if (!fd || !JSON_BIT_CHECK(fd->object_bit_field, JSON_V_TYPE)) {
1028 		return -EINVAL;
1029 	}
1030 
1031 	size_t value_length = fd->senml_object.val_float.length;
1032 
1033 	if (value_length == 0) {
1034 		return -ENODATA;
1035 	}
1036 
1037 	buf = fd->senml_object.val_float.start;
1038 	while (*(buf + i) && i < value_length) {
1039 		c = *(buf + i);
1040 		if (c == '-' && accept_sign && i == 0) {
1041 			neg = true;
1042 		} else if (isdigit(c) != 0) {
1043 			*value = *value * 10 + (c - '0');
1044 		} else {
1045 			/* anything else stop reading */
1046 			break;
1047 		}
1048 		i++;
1049 	}
1050 
1051 	if (neg) {
1052 		*value = -*value;
1053 	}
1054 
1055 	return i;
1056 }
1057 
get_s64(struct lwm2m_input_context * in,int64_t * value)1058 static int get_s64(struct lwm2m_input_context *in, int64_t *value)
1059 {
1060 	return read_int(in, value, true);
1061 }
1062 
get_time(struct lwm2m_input_context * in,time_t * value)1063 static int get_time(struct lwm2m_input_context *in, time_t *value)
1064 {
1065 	int64_t temp64;
1066 	int ret;
1067 
1068 	ret = read_int(in, &temp64, true);
1069 	*value = (time_t)temp64;
1070 
1071 	return ret;
1072 }
1073 
get_s32(struct lwm2m_input_context * in,int32_t * value)1074 static int get_s32(struct lwm2m_input_context *in, int32_t *value)
1075 {
1076 	int64_t tmp = 0;
1077 	int len = 0;
1078 
1079 	len = read_int(in, &tmp, true);
1080 	if (len > 0) {
1081 		*value = (int32_t)tmp;
1082 	}
1083 
1084 	return len;
1085 }
1086 
get_string(struct lwm2m_input_context * in,uint8_t * buf,size_t buflen)1087 static int get_string(struct lwm2m_input_context *in, uint8_t *buf, size_t buflen)
1088 {
1089 	struct json_in_formatter_data *fd;
1090 	size_t string_length;
1091 
1092 	fd = engine_get_in_user_data(in);
1093 	if (!fd || !JSON_BIT_CHECK(fd->object_bit_field, JSON_VS_TYPE)) {
1094 		return -EINVAL;
1095 	}
1096 
1097 	string_length = strlen(fd->senml_object.val_string);
1098 
1099 	if (string_length > buflen) {
1100 		LOG_WRN("Buffer too small to accommodate string, truncating");
1101 		string_length = buflen - 1;
1102 	}
1103 	memcpy(buf, fd->senml_object.val_string, string_length);
1104 
1105 	/* add NULL */
1106 	buf[string_length] = '\0';
1107 
1108 	return string_length;
1109 }
1110 
get_float(struct lwm2m_input_context * in,double * value)1111 static int get_float(struct lwm2m_input_context *in, double *value)
1112 {
1113 	struct json_in_formatter_data *fd;
1114 
1115 	int i = 0, len = 0;
1116 	bool has_dot = false;
1117 	uint8_t tmp, buf[24];
1118 	const uint8_t *json_buf;
1119 
1120 	fd = engine_get_in_user_data(in);
1121 	if (!fd || !JSON_BIT_CHECK(fd->object_bit_field, JSON_V_TYPE)) {
1122 		return -EINVAL;
1123 	}
1124 
1125 	size_t value_length = fd->senml_object.val_float.length;
1126 
1127 	if (value_length == 0) {
1128 		return -ENODATA;
1129 	}
1130 
1131 	json_buf = fd->senml_object.val_float.start;
1132 	while (*(json_buf + len) && len < value_length) {
1133 		tmp = *(json_buf + len);
1134 
1135 		if ((tmp == '-' && i == 0) || (tmp == '.' && !has_dot) || isdigit(tmp) != 0) {
1136 			len++;
1137 
1138 			/* Copy only if it fits into provided buffer - we won't
1139 			 * get better precision anyway.
1140 			 */
1141 			if (i < sizeof(buf) - 1) {
1142 				buf[i++] = tmp;
1143 			}
1144 
1145 			if (tmp == '.') {
1146 				has_dot = true;
1147 			}
1148 		} else {
1149 			break;
1150 		}
1151 	}
1152 
1153 	buf[i] = '\0';
1154 
1155 	if (lwm2m_atof(buf, value) != 0) {
1156 		LOG_ERR("Failed to parse float value");
1157 	}
1158 
1159 	return len;
1160 }
1161 
get_bool(struct lwm2m_input_context * in,bool * value)1162 static int get_bool(struct lwm2m_input_context *in, bool *value)
1163 {
1164 	struct json_in_formatter_data *fd;
1165 
1166 	fd = engine_get_in_user_data(in);
1167 	if (!fd || !JSON_BIT_CHECK(fd->object_bit_field, JSON_VB_TYPE)) {
1168 		return -EINVAL;
1169 	}
1170 
1171 	*value = fd->senml_object.val_bool;
1172 
1173 	return 1;
1174 }
1175 
base64_url_safe_decode(uint8_t * data_buf,size_t buf_len)1176 static void base64_url_safe_decode(uint8_t *data_buf, size_t buf_len)
1177 {
1178 	uint8_t *ptr = data_buf;
1179 
1180 	for (size_t i = 0; i < buf_len; i++) {
1181 		if (*ptr == '-') {
1182 			/* replace '-' with "+" */
1183 			*ptr = '+';
1184 		} else if (*ptr == '_') {
1185 			/* replace '_' with "/" */
1186 			*ptr = '/';
1187 		}
1188 		ptr++;
1189 	}
1190 }
1191 
store_padded_modulo(uint16_t * padded_length,uint8_t * padded_buf,uint8_t * data_tail,uint16_t data_length)1192 static int store_padded_modulo(uint16_t *padded_length, uint8_t *padded_buf, uint8_t *data_tail,
1193 			       uint16_t data_length)
1194 {
1195 	uint16_t padded_len = BASE64_MODULO_LENGTH(data_length);
1196 
1197 	if (data_length < padded_len) {
1198 		return -ENODATA;
1199 	}
1200 	*padded_length = padded_len;
1201 
1202 	if (padded_len) {
1203 		uint8_t *tail_ptr;
1204 
1205 		tail_ptr = data_tail - padded_len;
1206 		memcpy(padded_buf, tail_ptr, padded_len);
1207 		for (size_t i = padded_len; i < BASE64_OUTPUT_MIN_LENGTH; i++) {
1208 			padded_buf[i] = '=';
1209 		}
1210 	}
1211 	return 0;
1212 }
1213 
get_opaque(struct lwm2m_input_context * in,uint8_t * value,size_t buflen,struct lwm2m_opaque_context * opaque,bool * last_block)1214 static int get_opaque(struct lwm2m_input_context *in, uint8_t *value, size_t buflen,
1215 			 struct lwm2m_opaque_context *opaque, bool *last_block)
1216 {
1217 	struct json_in_formatter_data *fd;
1218 	struct json_obj_token *val_opaque;
1219 	uint8_t *data_ptr;
1220 	int in_len, ret;
1221 	uint16_t padded_length = 0;
1222 	uint8_t padded_buf[BASE64_OUTPUT_MIN_LENGTH];
1223 	size_t buffer_base64_length;
1224 
1225 	fd = engine_get_in_user_data(in);
1226 	if (!fd || !JSON_BIT_CHECK(fd->object_bit_field, JSON_VD_TYPE)) {
1227 		return -EINVAL;
1228 	}
1229 	val_opaque = &fd->senml_object.val_opaque;
1230 
1231 	data_ptr = val_opaque->start;
1232 
1233 	/* Decode from url safe to normal */
1234 	base64_url_safe_decode(data_ptr, val_opaque->length);
1235 
1236 	if (opaque->remaining == 0) {
1237 		size_t original_size = val_opaque->length;
1238 		size_t base64_length;
1239 
1240 		ret = store_padded_modulo(&padded_length, padded_buf, data_ptr + original_size,
1241 					  original_size);
1242 		if (ret) {
1243 			return ret;
1244 		}
1245 
1246 		if (base64_decode(data_ptr, val_opaque->length, &base64_length, data_ptr,
1247 				  val_opaque->length) < 0) {
1248 			return -ENODATA;
1249 		}
1250 
1251 		val_opaque->length = base64_length;
1252 		if (padded_length) {
1253 			if (base64_decode(padded_buf, BASE64_OUTPUT_MIN_LENGTH,
1254 					  &buffer_base64_length, padded_buf,
1255 					  BASE64_OUTPUT_MIN_LENGTH) < 0) {
1256 				return -ENODATA;
1257 			}
1258 			/* Add padded tail */
1259 			memcpy(data_ptr + val_opaque->length, padded_buf, buffer_base64_length);
1260 			val_opaque->length += buffer_base64_length;
1261 		}
1262 		opaque->len = val_opaque->length;
1263 		opaque->remaining = val_opaque->length;
1264 	}
1265 
1266 	in_len = opaque->remaining;
1267 
1268 	if (in_len > buflen) {
1269 		in_len = buflen;
1270 	}
1271 
1272 	if (in_len > val_opaque->length) {
1273 		in_len = val_opaque->length;
1274 	}
1275 
1276 	opaque->remaining -= in_len;
1277 	if (opaque->remaining == 0U) {
1278 		*last_block = true;
1279 	}
1280 	/* Copy data to buffer */
1281 	memcpy(value, data_ptr, in_len);
1282 
1283 	return in_len;
1284 }
1285 
get_objlnk(struct lwm2m_input_context * in,struct lwm2m_objlnk * value)1286 static int get_objlnk(struct lwm2m_input_context *in, struct lwm2m_objlnk *value)
1287 {
1288 	int64_t tmp;
1289 	int len, total_len;
1290 	struct json_in_formatter_data *fd;
1291 	char *demiliter_pos;
1292 
1293 	fd = engine_get_in_user_data(in);
1294 	if (!fd || !JSON_BIT_CHECK(fd->object_bit_field, JSON_VLO_TYPE)) {
1295 		return -EINVAL;
1296 	}
1297 
1298 	demiliter_pos = strchr(fd->senml_object.val_object_link, ':');
1299 	if (!demiliter_pos) {
1300 		return -ENODATA;
1301 	}
1302 
1303 	fd->object_bit_field |= JSON_V_TYPE;
1304 	fd->senml_object.val_float.start = fd->senml_object.val_object_link;
1305 	fd->senml_object.val_float.length = strlen(fd->senml_object.val_object_link);
1306 
1307 	/* Set String end for first item  */
1308 	*demiliter_pos = '\0';
1309 
1310 	len = read_int(in, &tmp, false);
1311 	if (len <= 0) {
1312 		return -ENODATA;
1313 	}
1314 
1315 	total_len = len;
1316 	value->obj_id = (uint16_t)tmp;
1317 
1318 	len++;  /* +1 for ':' delimiter. */
1319 	demiliter_pos++;
1320 	fd->senml_object.val_float.start = demiliter_pos;
1321 	fd->senml_object.val_float.length = strlen(demiliter_pos);
1322 
1323 	len = read_int(in, &tmp, false);
1324 	if (len <= 0) {
1325 		return -ENODATA;
1326 	}
1327 
1328 	total_len += len;
1329 	value->obj_inst = (uint16_t)tmp;
1330 
1331 	return total_len;
1332 }
1333 
put_data_timestamp(struct lwm2m_output_context * out,time_t value)1334 static int put_data_timestamp(struct lwm2m_output_context *out, time_t value)
1335 {
1336 	struct json_out_formatter_data *fd;
1337 	int len;
1338 
1339 	fd = engine_get_out_user_data(out);
1340 
1341 	if (!out->out_cpkt || !fd) {
1342 		LOG_ERR("Timestamp fail");
1343 		return -EINVAL;
1344 	}
1345 
1346 	len = number_to_string(fd->timestamp_buffer, sizeof(fd->timestamp_buffer), "%lld",
1347 			       value - fd->base_time);
1348 
1349 	if (len < 0) {
1350 		return len;
1351 	}
1352 
1353 	if (fd->base_time == 0) {
1354 		/* Store  base time */
1355 		fd->base_time = value;
1356 	}
1357 
1358 	fd->timestamp_length = len;
1359 	fd->historical_data = true;
1360 
1361 	return 0;
1362 }
1363 
1364 const struct lwm2m_writer senml_json_writer = {
1365 	.put_begin = put_begin,
1366 	.put_end = put_end,
1367 	.put_begin_oi = put_begin_oi,
1368 	.put_begin_ri = put_begin_ri,
1369 	.put_end_ri = put_end_ri,
1370 	.put_end_r = put_end_r,
1371 	.put_s8 = put_s8,
1372 	.put_s16 = put_s16,
1373 	.put_s32 = put_s32,
1374 	.put_s64 = put_s64,
1375 	.put_string = put_string,
1376 	.put_time = put_time,
1377 	.put_float = put_float,
1378 	.put_bool = put_bool,
1379 	.put_opaque = put_opaque,
1380 	.put_objlnk = put_objlnk,
1381 	.put_data_timestamp = put_data_timestamp,
1382 };
1383 
1384 const struct lwm2m_reader senml_json_reader = {
1385 	.get_s32 = get_s32,
1386 	.get_s64 = get_s64,
1387 	.get_string = get_string,
1388 	.get_time = get_time,
1389 	.get_float = get_float,
1390 	.get_bool = get_bool,
1391 	.get_opaque = get_opaque,
1392 	.get_objlnk = get_objlnk,
1393 };
1394 
do_read_op_senml_json(struct lwm2m_message * msg)1395 int do_read_op_senml_json(struct lwm2m_message *msg)
1396 {
1397 	struct lwm2m_obj_path_list temp;
1398 	sys_slist_t lwm2m_path_list;
1399 	int ret;
1400 	struct json_out_formatter_data fd;
1401 
1402 	(void)memset(&fd, 0, sizeof(fd));
1403 	engine_set_out_user_data(&msg->out, &fd);
1404 	/* Init list */
1405 	sys_slist_init(&lwm2m_path_list);
1406 	/* Init message here ready for response */
1407 	temp.path = msg->path;
1408 	/* Add one entry to list */
1409 	sys_slist_append(&lwm2m_path_list, &temp.node);
1410 
1411 	ret = lwm2m_perform_read_op(msg, LWM2M_FORMAT_APP_SEML_JSON);
1412 	engine_clear_out_user_data(&msg->out);
1413 
1414 	return ret;
1415 }
1416 
lwm2m_senml_write_operation(struct lwm2m_message * msg,struct json_in_formatter_data * fd)1417 static int lwm2m_senml_write_operation(struct lwm2m_message *msg, struct json_in_formatter_data *fd)
1418 {
1419 	struct lwm2m_engine_obj_field *obj_field = NULL;
1420 	struct lwm2m_engine_obj_inst *obj_inst = NULL;
1421 	struct lwm2m_engine_res *res = NULL;
1422 	struct lwm2m_engine_res_inst *res_inst = NULL;
1423 	uint8_t created;
1424 	int ret = 0;
1425 
1426 	/* handle resource value */
1427 	/* reset values */
1428 	created = 0U;
1429 
1430 	/* if valid, use the return value as level */
1431 	ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
1432 	if (ret < 0) {
1433 		return ret;
1434 	}
1435 
1436 	ret = lwm2m_engine_validate_write_access(msg, obj_inst, &obj_field);
1437 	if (ret < 0) {
1438 		return ret;
1439 	}
1440 
1441 	ret = lwm2m_engine_get_create_res_inst(&msg->path, &res, &res_inst);
1442 	if (ret < 0) {
1443 		/* if OPTIONAL and BOOTSTRAP-WRITE or CREATE use ENOTSUP */
1444 		if ((msg->ctx->bootstrap_mode ||
1445 				msg->operation == LWM2M_OP_CREATE) &&
1446 			LWM2M_HAS_PERM(obj_field, BIT(LWM2M_FLAG_OPTIONAL))) {
1447 			ret = -ENOTSUP;
1448 			return ret;
1449 		}
1450 
1451 		ret = -ENOENT;
1452 		return ret;
1453 	}
1454 
1455 	/* Write the resource value */
1456 	ret = lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
1457 	if (ret == -EACCES || ret == -ENOENT) {
1458 		/* if read-only or non-existent data buffer move on */
1459 		ret = 0;
1460 	}
1461 
1462 	return ret;
1463 }
1464 
do_write_op_senml_json(struct lwm2m_message * msg)1465 int do_write_op_senml_json(struct lwm2m_message *msg)
1466 {
1467 	struct json_in_formatter_data fd;
1468 	struct json_obj json_object;
1469 	struct lwm2m_obj_path resource_path;
1470 	int ret = 0;
1471 	uint8_t full_name[MAX_RESOURCE_LEN + 1] = {0};
1472 	const char *base_name_ptr = NULL;
1473 	char *data_ptr;
1474 	uint16_t in_len;
1475 
1476 	(void)memset(&fd, 0, sizeof(fd));
1477 	engine_set_in_user_data(&msg->in, &fd);
1478 
1479 	if (msg->in.block_ctx) {
1480 		LOG_ERR("Json library not support Coap Block");
1481 		ret = -EOPNOTSUPP;
1482 		goto end_of_operation;
1483 	}
1484 
1485 	data_ptr = (char *)coap_packet_get_payload(msg->in.in_cpkt, &in_len);
1486 
1487 	/* When No blockwise do Normal Init */
1488 	if (json_arr_separate_object_parse_init(&json_object, data_ptr, in_len)) {
1489 		ret = -EINVAL;
1490 		goto end_of_operation;
1491 	}
1492 
1493 	while (1) {
1494 
1495 		(void)memset(&fd.senml_object, 0, sizeof(fd.senml_object));
1496 		fd.object_bit_field = json_arr_separate_parse_object(&json_object, senml_descr,
1497 						  ARRAY_SIZE(senml_descr), &fd.senml_object);
1498 		if (fd.object_bit_field == 0) {
1499 			/* End of  */
1500 			break;
1501 		} else if (fd.object_bit_field < 0 ||
1502 			   ((fd.object_bit_field & JSON_NAME_MASK) == 0 ||
1503 			    (fd.object_bit_field & JSON_VALUE_MASK) == 0)) {
1504 			LOG_ERR("Json Write Parse object fail %d", fd.object_bit_field);
1505 			ret = -EINVAL;
1506 			goto end_of_operation;
1507 		}
1508 
1509 		if (JSON_BIT_CHECK(fd.object_bit_field, JSON_BN_TYPE)) {
1510 			base_name_ptr = fd.senml_object.base_name;
1511 		}
1512 
1513 		/* Create object resource path */
1514 		if (base_name_ptr) {
1515 			if (JSON_BIT_CHECK(fd.object_bit_field, JSON_N_TYPE)) {
1516 				ret = snprintk(full_name, sizeof(full_name), "%s%s", base_name_ptr,
1517 				       fd.senml_object.name);
1518 			} else {
1519 				ret = snprintk(full_name, sizeof(full_name), "%s", base_name_ptr);
1520 			}
1521 		} else {
1522 			ret = snprintk(full_name, sizeof(full_name), "%s", fd.senml_object.name);
1523 		}
1524 
1525 		if (ret >= MAX_RESOURCE_LEN) {
1526 			ret = -EINVAL;
1527 			goto end_of_operation;
1528 		}
1529 
1530 		ret = lwm2m_string_to_path(full_name, &resource_path, '/');
1531 		if (ret < 0) {
1532 			LOG_ERR("Relative name too long");
1533 			ret = -EINVAL;
1534 			goto end_of_operation;
1535 		}
1536 
1537 		msg->path = resource_path;
1538 		ret = lwm2m_senml_write_operation(msg, &fd);
1539 
1540 		/*
1541 		 * for OP_CREATE and BOOTSTRAP WRITE: errors on
1542 		 * optional resources are ignored (ENOTSUP)
1543 		 */
1544 		if (ret < 0 && !((ret == -ENOTSUP) &&
1545 				(msg->ctx->bootstrap_mode || msg->operation == LWM2M_OP_CREATE))) {
1546 			goto end_of_operation;
1547 		}
1548 	}
1549 
1550 	ret = 0;
1551 
1552 end_of_operation:
1553 	engine_clear_in_user_data(&msg->in);
1554 
1555 	return ret;
1556 }
1557 
json_parse_composite_read_paths(struct lwm2m_message * msg,sys_slist_t * lwm2m_path_list,sys_slist_t * lwm2m_path_free_list)1558 static uint8_t json_parse_composite_read_paths(struct lwm2m_message *msg,
1559 					       sys_slist_t *lwm2m_path_list,
1560 					       sys_slist_t *lwm2m_path_free_list)
1561 {
1562 	struct lwm2m_obj_path path;
1563 	struct json_obj json_object;
1564 	struct senml_context ts;
1565 
1566 	uint8_t full_name[MAX_RESOURCE_LEN + 1] = {0};
1567 	uint8_t valid_path_cnt = 0;
1568 	const char *base_name_ptr = NULL;
1569 	char *data_ptr;
1570 	int bit_field;
1571 	uint16_t in_len;
1572 	int ret;
1573 
1574 	data_ptr = (char *)coap_packet_get_payload(msg->in.in_cpkt, &in_len);
1575 
1576 	if (json_arr_separate_object_parse_init(&json_object, data_ptr, in_len)) {
1577 		return 0;
1578 	}
1579 
1580 	while (1) {
1581 		bit_field = json_arr_separate_parse_object(&json_object, senml_descr,
1582 						  ARRAY_SIZE(senml_descr), &ts);
1583 		if (bit_field < 0) {
1584 			LOG_ERR("Json Read Parse object fail %d", bit_field);
1585 			break;
1586 		} else if (JSON_BIT_CHECK(bit_field, JSON_NAME_MASK) == 0) {
1587 			break;
1588 		}
1589 
1590 		if (JSON_BIT_CHECK(bit_field, JSON_BN_TYPE)) {
1591 			base_name_ptr = ts.base_name;
1592 		}
1593 
1594 		/* Create object resource path */
1595 		if (base_name_ptr) {
1596 			if (JSON_BIT_CHECK(bit_field, JSON_N_TYPE)) {
1597 				ret = snprintk(full_name, sizeof(full_name), "%s%s", base_name_ptr,
1598 				       ts.name);
1599 			} else {
1600 				ret = snprintk(full_name, sizeof(full_name), "%s", base_name_ptr);
1601 			}
1602 		} else {
1603 			ret = snprintk(full_name, sizeof(full_name), "%s", ts.name);
1604 		}
1605 
1606 		if (ret < MAX_RESOURCE_LEN) {
1607 			ret = lwm2m_string_to_path(full_name, &path, '/');
1608 			if (ret == 0) {
1609 				if (lwm2m_engine_add_path_to_list(
1610 					    lwm2m_path_list, lwm2m_path_free_list, &path) == 0) {
1611 					valid_path_cnt++;
1612 				}
1613 			}
1614 		}
1615 	}
1616 
1617 	return valid_path_cnt;
1618 }
1619 
do_composite_read_op_for_parsed_list_senml_json(struct lwm2m_message * msg,sys_slist_t * path_list)1620 int do_composite_read_op_for_parsed_list_senml_json(struct lwm2m_message *msg,
1621 						    sys_slist_t *path_list)
1622 {
1623 	int ret;
1624 	struct json_out_formatter_data fd;
1625 
1626 	(void)memset(&fd, 0, sizeof(fd));
1627 	engine_set_out_user_data(&msg->out, &fd);
1628 
1629 	ret = lwm2m_perform_composite_read_op(msg, LWM2M_FORMAT_APP_SEML_JSON, path_list);
1630 	engine_clear_out_user_data(&msg->out);
1631 
1632 	return ret;
1633 }
1634 
do_composite_read_op_senml_json(struct lwm2m_message * msg)1635 int do_composite_read_op_senml_json(struct lwm2m_message *msg)
1636 {
1637 	struct lwm2m_obj_path_list path_list_buf[CONFIG_LWM2M_COMPOSITE_PATH_LIST_SIZE];
1638 	sys_slist_t path_list;
1639 	sys_slist_t free_list;
1640 	uint8_t path_list_size;
1641 
1642 	/* Init list */
1643 	lwm2m_engine_path_list_init(&path_list, &free_list, path_list_buf,
1644 				    CONFIG_LWM2M_COMPOSITE_PATH_LIST_SIZE);
1645 
1646 	/* Parse Path's from SenML JSO payload */
1647 	path_list_size = json_parse_composite_read_paths(msg, &path_list, &free_list);
1648 	if (path_list_size == 0) {
1649 		LOG_ERR("No Valid Url at msg");
1650 		return -ESRCH;
1651 	}
1652 
1653 	/* Clear path which are part are part of recursive path /1 will include /1/0/1 */
1654 	lwm2m_engine_clear_duplicate_path(&path_list, &free_list);
1655 
1656 	return do_composite_read_op_for_parsed_list(msg, LWM2M_FORMAT_APP_SEML_JSON, &path_list);
1657 }
1658 
do_send_op_senml_json(struct lwm2m_message * msg,sys_slist_t * lwm2m_path_list)1659 int do_send_op_senml_json(struct lwm2m_message *msg, sys_slist_t *lwm2m_path_list)
1660 {
1661 	struct json_out_formatter_data fd;
1662 	int ret;
1663 
1664 	(void)memset(&fd, 0, sizeof(fd));
1665 	engine_set_out_user_data(&msg->out, &fd);
1666 
1667 	ret = lwm2m_perform_composite_read_op(msg, LWM2M_FORMAT_APP_SEML_JSON, lwm2m_path_list);
1668 	engine_clear_out_user_data(&msg->out);
1669 
1670 	return ret;
1671 }
1672 
do_composite_observe_parse_path_senml_json(struct lwm2m_message * msg,sys_slist_t * lwm2m_path_list,sys_slist_t * lwm2m_path_free_list)1673 int do_composite_observe_parse_path_senml_json(struct lwm2m_message *msg,
1674 					       sys_slist_t *lwm2m_path_list,
1675 					       sys_slist_t *lwm2m_path_free_list)
1676 {
1677 	uint8_t list_size;
1678 	uint16_t original_offset;
1679 
1680 	original_offset = msg->in.offset;
1681 	/* Parse Path's from SenML JSON payload */
1682 	list_size = json_parse_composite_read_paths(msg, lwm2m_path_list, lwm2m_path_free_list);
1683 	if (list_size == 0) {
1684 		LOG_ERR("No Valid Url at msg");
1685 		return -ESRCH;
1686 	}
1687 
1688 	msg->in.offset = original_offset;
1689 	return 0;
1690 }
1691