libcoap 4.3.5-develop-72978e9
Loading...
Searching...
No Matches
coap_subscribe.c
Go to the documentation of this file.
1/* coap_subscribe.c -- subscription handling for CoAP
2 * see RFC7641
3 *
4 * Copyright (C) 2010-2019,2022-2026 Olaf Bergmann <bergmann@tzi.org>
5 *
6 * SPDX-License-Identifier: BSD-2-Clause
7 *
8 * This file is part of the CoAP library libcoap. Please see
9 * README for terms of use.
10 */
11
16
18
19#ifndef min
20#define min(a,b) ((a) < (b) ? (a) : (b))
21#endif
22
23int
25#if COAP_SERVER_SUPPORT && COAP_WITH_OBSERVE_PERSIST
26 return 1;
27#else /* ! (COAP_SERVER_SUPPORT && COAP_WITH_OBSERVE_PERSIST) */
28 return 0;
29#endif /* ! (COAP_SERVER_SUPPORT && COAP_WITH_OBSERVE_PERSIST) */
30}
31
32#if COAP_SERVER_SUPPORT
33void
34coap_subscription_init(coap_subscription_t *s) {
35 assert(s);
36 memset(s, 0, sizeof(coap_subscription_t));
37}
38
39void
41 coap_observe_added_t observe_added,
42 coap_observe_deleted_t observe_deleted,
43 coap_track_observe_value_t track_observe_value,
44 coap_dyn_resource_added_t dyn_resource_added,
45 coap_resource_deleted_t resource_deleted,
46 uint32_t save_freq,
47 void *user_data) {
48 context->observe_added_cb = observe_added;
49 context->observe_deleted_cb = observe_deleted;
50 context->observe_user_data = user_data;
51 context->observe_save_freq = save_freq ? save_freq : 1;
52 context->track_observe_value_cb = track_observe_value;
53 context->dyn_resource_added_cb = dyn_resource_added;
54 context->resource_deleted_cb = resource_deleted;
55}
56
59 coap_proto_t e_proto,
60 const coap_address_t *e_listen_addr,
61 const coap_addr_tuple_t *s_addr_info,
62 const coap_bin_const_t *raw_packet,
63 const coap_bin_const_t *oscore_info) {
65
66 coap_lock_lock(return NULL);
67 subs = coap_persist_observe_add_lkd(context,
68 e_proto,
69 e_listen_addr,
70 s_addr_info,
71 raw_packet,
72 oscore_info);
74 return subs;
75}
76
78coap_persist_observe_add_lkd(coap_context_t *context,
79 coap_proto_t e_proto,
80 const coap_address_t *e_listen_addr,
81 const coap_addr_tuple_t *s_addr_info,
82 const coap_bin_const_t *raw_packet,
83 const coap_bin_const_t *oscore_info) {
84 coap_session_t *session = NULL;
85 const uint8_t *data;
86 size_t data_len;
87 coap_pdu_t *pdu = NULL;
88#if COAP_CONSTRAINED_STACK
89 /* e_packet can be protected by global_lock if needed */
90 static coap_packet_t e_packet;
91#else /* ! COAP_CONSTRAINED_STACK */
92 coap_packet_t e_packet;
93#endif /* ! COAP_CONSTRAINED_STACK */
94 coap_packet_t *packet = &e_packet;
95 coap_tick_t now;
96 coap_string_t *uri_path = NULL;
97 coap_opt_iterator_t opt_iter;
98 coap_opt_t *observe;
99 int observe_action;
102 coap_endpoint_t *ep;
103
105 if (e_listen_addr == NULL || s_addr_info == NULL || raw_packet == NULL)
106 return NULL;
107
108 /* Will be creating a local 'open' session */
109 if (e_proto != COAP_PROTO_UDP)
110 return NULL;
111
112 ep = context->endpoint;
113 while (ep) {
114 if (ep->proto == e_proto &&
115 memcmp(e_listen_addr, &ep->bind_addr, sizeof(ep->bind_addr)) == 0)
116 break;
117 ep = ep->next;
118 }
119 if (!ep) {
121#ifndef INET6_ADDRSTRLEN
122#define INET6_ADDRSTRLEN 40
123#endif
124 unsigned char addr_str[INET6_ADDRSTRLEN + 8];
125
126 if (coap_print_addr(e_listen_addr, addr_str, INET6_ADDRSTRLEN + 8)) {
127 coap_log_warn("coap_persist_observe_add: Endpoint %s not defined\n",
128 addr_str);
129 }
130 }
131 return NULL;
132 }
133
134 /* Build up packet */
135 memcpy(&packet->addr_info, s_addr_info, sizeof(packet->addr_info));
136 packet->ifindex = 0;
137 memcpy(&packet->payload, &raw_packet->s, sizeof(packet->payload));
138 packet->length = raw_packet->length;
139
140 data = raw_packet->s;
141 data_len = raw_packet->length;
142 if (data_len < 4)
143 goto malformed;
144
145 /* Get the session */
146
147 coap_ticks(&now);
148 session = coap_endpoint_get_session(ep, packet, now);
149 if (session == NULL)
150 goto fail;
151 /* Need max space incase PDU is updated with updated token, huge size etc. */
152 pdu = coap_pdu_init(0, 0, 0, 0);
153 if (!pdu)
154 goto fail;
155
156 if (!coap_pdu_parse(session->proto, data, data_len, pdu)) {
157 goto malformed;
158 }
159 pdu->max_size = pdu->used_size;
160
161 if (pdu->code != COAP_REQUEST_CODE_GET &&
163 goto malformed;
164
165 observe = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter);
166 if (observe == NULL)
167 goto malformed;
168 observe_action = coap_decode_var_bytes(coap_opt_value(observe),
169 coap_opt_length(observe));
170 if (observe_action != COAP_OBSERVE_ESTABLISH)
171 goto malformed;
172
173 /* Get the resource */
174
175 uri_path = coap_get_uri_path(pdu);
176 if (!uri_path)
177 goto malformed;
178
179 r = coap_get_resource_from_uri_path_lkd(session->context,
180 (coap_str_const_t *)uri_path);
181 if (r == NULL) {
182 coap_log_warn("coap_persist_observe_add: resource '%s' not defined\n",
183 uri_path->s);
184 goto fail;
185 }
186 if (!r->observable) {
187 coap_log_warn("coap_persist_observe_add: resource '%s' not observable\n",
188 uri_path->s);
189 goto fail;
190 }
191 coap_delete_string(uri_path);
192 uri_path = NULL;
193
194 /* Create / update subscription for observing */
195 /* Now set up the subscription */
196 s = coap_add_observer(r, session, &pdu->actual_token, pdu);
197 if (s == NULL)
198 goto fail;
199
200#if COAP_OSCORE_SUPPORT
201 if (oscore_info) {
202 coap_log_debug("persist: OSCORE association being updated\n");
203 /*
204 * Need to track the association used for tracking this observe, done as
205 * a CBOR array. Written in coap_add_observer().
206 *
207 * If an entry is null, then use nil, else a set of bytes
208 *
209 * Currently tracking 5 items
210 * recipient_id
211 * id_context
212 * aad (from oscore_association_t)
213 * partial_iv (from oscore_association_t)
214 * nonce (from oscore_association_t)
215 */
216 oscore_ctx_t *osc_ctx;
217 const uint8_t *info_buf = oscore_info->s;
218 size_t info_buf_len = oscore_info->length;
219 size_t ret = 0;
220 coap_bin_const_t oscore_key_id;
221 coap_bin_const_t partial_iv;
223 coap_bin_const_t id_context;
224 coap_bin_const_t nonce;
225 int have_aad = 0;
226 int have_partial_iv = 0;
227 int have_id_context = 0;
228 int have_nonce = 0;
229
230 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
231 if (ret != CBOR_ARRAY)
232 goto oscore_fail;
233 if (oscore_cbor_get_element_size(&info_buf, &info_buf_len) != 5)
234 goto oscore_fail;
235
236 /* recipient_id */
237 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
238 if (ret != CBOR_BYTE_STRING)
239 goto oscore_fail;
240 oscore_key_id.length = oscore_cbor_get_element_size(&info_buf,
241 &info_buf_len);
242 if (oscore_key_id.length > info_buf_len)
243 goto oscore_fail;
244 oscore_key_id.s = info_buf;
245 info_buf += oscore_key_id.length;
246 info_buf_len -= oscore_key_id.length;
247
248 /* id_context */
249 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
250 if (ret == CBOR_BYTE_STRING) {
251 id_context.length = oscore_cbor_get_element_size(&info_buf,
252 &info_buf_len);
253 if (id_context.length > info_buf_len)
254 goto oscore_fail;
255 id_context.s = info_buf;
256 info_buf += id_context.length;
257 info_buf_len -= id_context.length;
258 have_id_context = 1;
259 } else if (ret == CBOR_SIMPLE_VALUE &&
261 &info_buf_len) == CBOR_NULL) {
262 } else
263 goto oscore_fail;
264
265 /* aad */
266 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
267 if (ret == CBOR_BYTE_STRING) {
268 aad.length = oscore_cbor_get_element_size(&info_buf, &info_buf_len);
269 if (aad.length > info_buf_len)
270 goto oscore_fail;
271 aad.s = info_buf;
272 info_buf += aad.length;
273 info_buf_len -= aad.length;
274 have_aad = 1;
275 } else if (ret == CBOR_SIMPLE_VALUE &&
277 &info_buf_len) == CBOR_NULL) {
278 } else
279 goto oscore_fail;
280
281 /* partial_iv */
282 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
283 if (ret == CBOR_BYTE_STRING) {
284 partial_iv.length = oscore_cbor_get_element_size(&info_buf,
285 &info_buf_len);
286 if (partial_iv.length > info_buf_len)
287 goto oscore_fail;
288 partial_iv.s = info_buf;
289 info_buf += partial_iv.length;
290 info_buf_len -= partial_iv.length;
291 have_partial_iv = 1;
292 } else if (ret == CBOR_SIMPLE_VALUE &&
294 &info_buf_len) == CBOR_NULL) {
295 } else
296 goto oscore_fail;
297
298 /* nonce */
299 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
300 if (ret == CBOR_BYTE_STRING) {
301 nonce.length = oscore_cbor_get_element_size(&info_buf,
302 &info_buf_len);
303 if (nonce.length > info_buf_len)
304 goto oscore_fail;
305 nonce.s = info_buf;
306 info_buf += nonce.length;
307 info_buf_len -= nonce.length;
308 have_nonce = 1;
309 } else if (ret == CBOR_SIMPLE_VALUE &&
311 &info_buf_len) == CBOR_NULL) {
312 } else
313 goto oscore_fail;
314
315 osc_ctx = oscore_find_context(session, oscore_key_id,
316 have_id_context ? &id_context : NULL, NULL,
317 &session->recipient_ctx);
318 if (osc_ctx) {
319 session->oscore_encryption = 1;
320 oscore_new_association(session, pdu, &pdu->actual_token,
321 session->recipient_ctx,
322 have_aad ? &aad : NULL,
323 have_nonce ? &nonce : NULL,
324 have_partial_iv ? &partial_iv : NULL,
325 1);
326 coap_log_debug("persist: OSCORE association added\n");
328 have_partial_iv ? &partial_iv : NULL);
329 }
330 }
331oscore_fail:
332#else /* ! COAP_OSCORE_SUPPORT */
333 (void)oscore_info;
334#endif /* ! COAP_OSCORE_SUPPORT */
336 return s;
337
338malformed:
339 coap_log_warn("coap_persist_observe_add: discard malformed PDU\n");
340fail:
341 coap_delete_string(uri_path);
343 return NULL;
344}
345
346#if COAP_WITH_OBSERVE_PERSIST
347#include <stdio.h>
348
349/*
350 * read in active observe entry.
351 */
352static int
353coap_op_observe_read(FILE *fp, coap_subscription_t **observe_key,
354 coap_proto_t *e_proto, coap_address_t *e_listen_addr,
355 coap_addr_tuple_t *s_addr_info,
356 coap_bin_const_t **raw_packet, coap_bin_const_t **oscore_info) {
357 ssize_t size;
358 coap_binary_t *scratch = NULL;
359
360 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
361 raw_packet && oscore_info);
362
363 *raw_packet = NULL;
364 *oscore_info = NULL;
365
366 if (fread(observe_key, sizeof(*observe_key), 1, fp) == 1) {
367 /* New record 'key proto listen addr_info len raw_packet len oscore' */
368 if (fread(e_proto, sizeof(*e_proto), 1, fp) != 1)
369 goto fail;
370 if (fread(e_listen_addr, sizeof(*e_listen_addr), 1, fp) != 1)
371 goto fail;
372 if (fread(s_addr_info, sizeof(*s_addr_info), 1, fp) != 1)
373 goto fail;
374 if (fread(&size, sizeof(size), 1, fp) != 1)
375 goto fail;
376 if (size < 0 || size > 0x10000)
377 goto fail;
378 scratch = coap_new_binary(size);
379 if ((scratch) == NULL)
380 goto fail;
381 if (fread(scratch->s, scratch->length, 1, fp) != 1)
382 goto fail;
383 *raw_packet = (coap_bin_const_t *)scratch;
384 scratch = NULL;
385 if (fread(&size, sizeof(size), 1, fp) != 1)
386 goto fail;
387 /* If size == -1, then no oscore information */
388 if (size == -1)
389 return 1;
390 else if (size < 0 || size > 0x10000)
391 goto fail;
392 else {
393 scratch = coap_new_binary(size);
394 if (scratch == NULL)
395 goto fail;
396 if (fread(scratch->s, scratch->length, 1, fp) != 1)
397 goto fail;
398 *oscore_info = (coap_bin_const_t *)scratch;
399 }
400 return 1;
401 }
402fail:
403 coap_delete_bin_const(*raw_packet);
404 coap_delete_binary(scratch);
405
406 *observe_key = NULL;
407 memset(e_proto, 0, sizeof(*e_proto));
408 memset(e_listen_addr, 0, sizeof(*e_listen_addr));
409 memset(s_addr_info, 0, sizeof(*s_addr_info));
410 *raw_packet = NULL;
411 return 0;
412}
413
414/*
415 * write out active observe entry.
416 */
417static int
418coap_op_observe_write(FILE *fp, coap_subscription_t *observe_key,
419 coap_proto_t e_proto, coap_address_t e_listen_addr,
420 coap_addr_tuple_t s_addr_info,
421 coap_bin_const_t *raw_packet, coap_bin_const_t *oscore_info) {
422 if (fwrite(&observe_key, sizeof(observe_key), 1, fp) != 1)
423 goto fail;
424 if (fwrite(&e_proto, sizeof(e_proto), 1, fp) != 1)
425 goto fail;
426 if (fwrite(&e_listen_addr, sizeof(e_listen_addr),
427 1, fp) != 1)
428 goto fail;
429 if (fwrite(&s_addr_info, sizeof(s_addr_info), 1, fp) != 1)
430 goto fail;
431 if (fwrite(&raw_packet->length, sizeof(raw_packet->length), 1, fp) != 1)
432 goto fail;
433 if (fwrite(raw_packet->s, raw_packet->length, 1, fp) != 1)
434 goto fail;
435 if (oscore_info) {
436 if (fwrite(&oscore_info->length, sizeof(oscore_info->length), 1, fp) != 1)
437 goto fail;
438 if (fwrite(oscore_info->s, oscore_info->length, 1, fp) != 1)
439 goto fail;
440 } else {
441 ssize_t not_defined = -1;
442
443 if (fwrite(&not_defined, sizeof(not_defined), 1, fp) != 1)
444 goto fail;
445 }
446 return 1;
447fail:
448 return 0;
449}
450
451/*
452 * This should be called before coap_persist_track_funcs() to prevent
453 * coap_op_observe_added() getting unnecessarily called.
454 * It should be called after init_resources() and coap_op_resource_load_disk()
455 * so that all the resources are in place.
456 */
457static void
458coap_op_observe_load_disk(coap_context_t *ctx) {
459 FILE *fp_orig = fopen((const char *)ctx->observe_save_file->s, "r");
460 FILE *fp_new = NULL;
461 coap_subscription_t *observe_key = NULL;
462 coap_proto_t e_proto;
463 coap_address_t e_listen_addr;
464 coap_addr_tuple_t s_addr_info;
465 coap_bin_const_t *raw_packet = NULL;
466 coap_bin_const_t *oscore_info = NULL;
467 char *new = NULL;
468
469 if (fp_orig == NULL)
470 goto fail;
471
472 new = coap_malloc_type(COAP_STRING, ctx->observe_save_file->length + 5);
473 if (!new)
474 goto fail;
475
476 strcpy(new, (const char *)ctx->observe_save_file->s);
477 strcat(new, ".tmp");
478 fp_new = fopen(new, "w+");
479 if (fp_new == NULL)
480 goto fail;
481
482 /* Go through and load oscore entry, updating key on the way */
483 while (1) {
484 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
485 &s_addr_info, &raw_packet, &oscore_info))
486 break;
487 coap_log_debug("persist: New session/observe being created\n");
488 observe_key = coap_persist_observe_add_lkd(ctx, e_proto,
489 &e_listen_addr,
490 &s_addr_info,
491 raw_packet,
492 oscore_info);
493 if (observe_key) {
494 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
495 s_addr_info, raw_packet, oscore_info))
496 goto fail;
497 }
498 coap_delete_bin_const(raw_packet);
499 raw_packet = NULL;
500 coap_delete_bin_const(oscore_info);
501 oscore_info = NULL;
502 }
503 coap_delete_bin_const(raw_packet);
504 raw_packet = NULL;
505 coap_delete_bin_const(oscore_info);
506 oscore_info = NULL;
507
508 if (fflush(fp_new) == EOF)
509 goto fail;
510 fclose(fp_new);
511 fclose(fp_orig);
512 /* Either old or new is in place */
513 if (rename(new, (const char *)ctx->observe_save_file->s) == -1) {
514 coap_log_warn("rename %s -> %s: failed: %s (%d)\n",
515 new, (const char *)ctx->observe_save_file->s,
516 coap_socket_strerror(), errno);
517 }
519 return;
520
521fail:
522 coap_delete_bin_const(raw_packet);
523 coap_delete_bin_const(oscore_info);
524 if (fp_new)
525 fclose(fp_new);
526 if (fp_orig)
527 fclose(fp_orig);
528 if (new) {
529 (void)remove(new);
530 }
532 return;
533}
534
535/*
536 * client has registered a new observe subscription request.
537 */
538static int
539coap_op_observe_added(coap_session_t *session,
540 coap_subscription_t *a_observe_key,
541 coap_proto_t a_e_proto, coap_address_t *a_e_listen_addr,
542 coap_addr_tuple_t *a_s_addr_info,
543 coap_bin_const_t *a_raw_packet,
544 coap_bin_const_t *a_oscore_info, void *user_data) {
545 FILE *fp_orig = fopen((const char *)session->context->observe_save_file->s,
546 "r");
547 FILE *fp_new = NULL;
548 coap_subscription_t *observe_key = NULL;
549 coap_proto_t e_proto;
550 coap_address_t e_listen_addr;
551 coap_addr_tuple_t s_addr_info;
552 coap_bin_const_t *raw_packet = NULL;
553 coap_bin_const_t *oscore_info = NULL;
554 char *new = NULL;
555
556 (void)user_data;
557
559 session->context->observe_save_file->length + 5);
560 if (!new)
561 goto fail;
562
563 strcpy(new, (const char *)session->context->observe_save_file->s);
564 strcat(new, ".tmp");
565 fp_new = fopen(new, "w+");
566 if (fp_new == NULL)
567 goto fail;
568
569 /* Go through and delete observe entry if it exists */
570 while (fp_orig) {
571 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
572 &s_addr_info, &raw_packet, &oscore_info))
573 break;
574 if (observe_key != a_observe_key) {
575 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
576 s_addr_info, raw_packet, oscore_info))
577 goto fail;
578 }
579 coap_delete_bin_const(raw_packet);
580 raw_packet = NULL;
581 coap_delete_bin_const(oscore_info);
582 oscore_info = NULL;
583 }
584 coap_delete_bin_const(raw_packet);
585 raw_packet = NULL;
586 coap_delete_bin_const(oscore_info);
587 oscore_info = NULL;
588
589 /* Add in new entry to the end */
590 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
591 *a_s_addr_info, a_raw_packet, a_oscore_info))
592 goto fail;
593
594 if (fflush(fp_new) == EOF)
595 goto fail;
596 fclose(fp_new);
597 if (fp_orig)
598 fclose(fp_orig);
599 /* Either old or new is in place */
600 (void)rename(new, (const char *)session->context->observe_save_file->s);
602 return 1;
603
604fail:
605 coap_delete_bin_const(raw_packet);
606 coap_delete_bin_const(oscore_info);
607 if (fp_new)
608 fclose(fp_new);
609 if (fp_orig)
610 fclose(fp_orig);
611 if (new) {
612 (void)remove(new);
613 }
615 return 0;
616}
617
618/*
619 * client has de-registered a observe subscription request.
620 */
621static int
622coap_op_observe_deleted(coap_session_t *session,
623 coap_subscription_t *d_observe_key,
624 void *user_data) {
625 FILE *fp_orig = fopen((const char *)session->context->observe_save_file->s,
626 "r");
627 FILE *fp_new = NULL;
628 coap_subscription_t *observe_key = NULL;
629 coap_proto_t e_proto;
630 coap_address_t e_listen_addr;
631 coap_addr_tuple_t s_addr_info;
632 coap_bin_const_t *raw_packet = NULL;
633 coap_bin_const_t *oscore_info = NULL;
634 char *new = NULL;
635
636 (void)user_data;
637
638 if (fp_orig == NULL)
639 goto fail;
641 session->context->observe_save_file->length + 5);
642 if (!new)
643 goto fail;
644
645 strcpy(new, (const char *)session->context->observe_save_file->s);
646 strcat(new, ".tmp");
647 fp_new = fopen(new, "w+");
648 if (fp_new == NULL)
649 goto fail;
650
651 /* Go through and locate observe entry to delete and not copy it across */
652 while (1) {
653 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
654 &s_addr_info, &raw_packet, &oscore_info))
655 break;
656 if (observe_key != d_observe_key) {
657 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
658 s_addr_info, (coap_bin_const_t *)raw_packet,
659 (coap_bin_const_t *)oscore_info))
660 goto fail;
661 }
662 coap_delete_bin_const(raw_packet);
663 raw_packet = NULL;
664 coap_delete_bin_const(oscore_info);
665 oscore_info = NULL;
666 }
667 coap_delete_bin_const(raw_packet);
668 raw_packet = NULL;
669 coap_delete_bin_const(oscore_info);
670 oscore_info = NULL;
671
672 if (fflush(fp_new) == EOF)
673 goto fail;
674 fclose(fp_new);
675 fclose(fp_orig);
676 /* Either old or new is in place */
677 (void)rename(new, (const char *)session->context->observe_save_file->s);
679 return 1;
680
681fail:
682 coap_delete_bin_const(raw_packet);
683 coap_delete_bin_const(oscore_info);
684 if (fp_new)
685 fclose(fp_new);
686 if (fp_orig)
687 fclose(fp_orig);
688 if (new) {
689 (void)remove(new);
690 }
692 return 0;
693}
694
695/*
696 * This should be called before coap_persist_track_funcs() to prevent
697 * coap_op_obs_cnt_track_observe() getting unnecessarily called.
698 * Should be called after coap_op_dyn_resource_load_disk() to make sure that
699 * all the resources are in the right place.
700 */
701static void
702coap_op_obs_cnt_load_disk(coap_context_t *context) {
703 FILE *fp = fopen((const char *)context->obs_cnt_save_file->s, "r");
704 char buf[1500];
705
706 if (fp == NULL)
707 return;
708
709 while (fgets(buf, sizeof(buf), fp) != NULL) {
710 char *cp = strchr(buf, ' ');
711 coap_str_const_t resource_key;
712 uint32_t observe_num;
714
715 if (!cp)
716 break;
717
718 *cp = '\000';
719 cp++;
720 observe_num = atoi(cp);
721 /*
722 * Need to assume 0 .. (context->observe_save_freq-1) have in addition
723 * been sent so need to round up to latest possible send value
724 */
725 observe_num = ((observe_num + context->observe_save_freq) /
726 context->observe_save_freq) *
727 context->observe_save_freq - 1;
728 resource_key.s = (uint8_t *)buf;
729 resource_key.length = strlen(buf);
730 r = coap_get_resource_from_uri_path_lkd(context, &resource_key);
731 if (r) {
732 coap_log_debug("persist: Initial observe number being updated '%s' %u\n",
733 buf, observe_num);
734 coap_persist_set_observe_num(r, observe_num);
735 }
736 }
737 fclose(fp);
738}
739
740/*
741 * Called when the observe value of a resource has been changed, but limited
742 * to be called every context->context->observe_save_freq to reduce update
743 * overheads.
744 */
745static int
746coap_op_obs_cnt_track_observe(coap_context_t *context,
747 coap_str_const_t *resource_name,
748 uint32_t n_observe_num,
749 void *user_data) {
750 FILE *fp_orig = fopen((const char *)context->obs_cnt_save_file->s, "r");
751 FILE *fp_new = NULL;
752 char buf[1500];
753 char *new = NULL;
754
755 (void)user_data;
756
757 new = coap_malloc_type(COAP_STRING, context->obs_cnt_save_file->length + 5);
758 if (!new)
759 goto fail;
760
761 strcpy(new, (const char *)context->obs_cnt_save_file->s);
762 strcat(new, ".tmp");
763 fp_new = fopen(new, "w+");
764 if (fp_new == NULL)
765 goto fail;
766
767 /* Go through and locate resource entry to update */
768 while (fp_orig && fgets(buf, sizeof(buf), fp_orig) != NULL) {
769 char *cp = strchr(buf, ' ');
770 uint32_t observe_num;
771 coap_bin_const_t resource_key;
772
773 if (!cp)
774 break;
775
776 *cp = '\000';
777 cp++;
778 observe_num = atoi(cp);
779 resource_key.s = (uint8_t *)buf;
780 resource_key.length = strlen(buf);
781 if (!coap_binary_equal(resource_name, &resource_key)) {
782 if (fprintf(fp_new, "%s %u\n", resource_key.s, observe_num) < 0)
783 goto fail;
784 }
785 }
786 if (fprintf(fp_new, "%s %u\n", resource_name->s, n_observe_num) < 0)
787 goto fail;
788 if (fflush(fp_new) == EOF)
789 goto fail;
790 fclose(fp_new);
791 if (fp_orig)
792 fclose(fp_orig);
793 /* Either old or new is in place */
794 (void)rename(new, (const char *)context->obs_cnt_save_file->s);
796 return 1;
797
798fail:
799 if (fp_new)
800 fclose(fp_new);
801 if (fp_orig)
802 fclose(fp_orig);
803 if (new) {
804 (void)remove(new);
805 }
807 return 0;
808}
809
810/*
811 * Called when a resource has been deleted.
812 */
813static int
814coap_op_obs_cnt_deleted(coap_context_t *context,
815 coap_str_const_t *resource_name) {
816 FILE *fp_orig = fopen((const char *)context->obs_cnt_save_file->s, "r");
817 FILE *fp_new = NULL;
818 char buf[1500];
819 char *new = NULL;
820
821 if (fp_orig == NULL)
822 goto fail;
823 new = coap_malloc_type(COAP_STRING, context->obs_cnt_save_file->length + 5);
824 if (!new)
825 goto fail;
826
827 strcpy(new, (const char *)context->obs_cnt_save_file->s);
828 strcat(new, ".tmp");
829 fp_new = fopen(new, "w+");
830 if (fp_new == NULL)
831 goto fail;
832
833 /* Go through and locate resource entry to delete */
834 while (fgets(buf, sizeof(buf), fp_orig) != NULL) {
835 char *cp = strchr(buf, ' ');
836 uint32_t observe_num;
837 coap_bin_const_t resource_key;
838
839 if (!cp)
840 break;
841
842 *cp = '\000';
843 cp++;
844 observe_num = atoi(cp);
845 resource_key.s = (uint8_t *)buf;
846 resource_key.length = strlen(buf);
847 if (!coap_binary_equal(resource_name, &resource_key)) {
848 if (fprintf(fp_new, "%s %u\n", resource_key.s, observe_num) < 0)
849 goto fail;
850 }
851 }
852 if (fflush(fp_new) == EOF)
853 goto fail;
854 fclose(fp_new);
855 fclose(fp_orig);
856 /* Either old or new is in place */
857 (void)rename(new, (const char *)context->obs_cnt_save_file->s);
859 return 1;
860
861fail:
862 if (fp_new)
863 fclose(fp_new);
864 if (fp_orig)
865 fclose(fp_orig);
866 if (new) {
867 (void)remove(new);
868 }
870 return 0;
871}
872
873/*
874 * read in dynamic resource entry, allocating name & raw_packet
875 * which need to be freed off by caller.
876 */
877static int
878coap_op_dyn_resource_read(FILE *fp, coap_proto_t *e_proto,
879 coap_string_t **name,
880 coap_binary_t **raw_packet) {
881 ssize_t size;
882
883 *name = NULL;
884 *raw_packet = NULL;
885
886 if (fread(e_proto, sizeof(*e_proto), 1, fp) == 1) {
887 /* New record 'proto len resource_name len raw_packet' */
888 if (fread(&size, sizeof(size), 1, fp) != 1)
889 goto fail;
890 if (size < 0 || size > 0x10000)
891 goto fail;
892 *name = coap_new_string(size);
893 if (!(*name))
894 goto fail;
895 if (fread((*name)->s, size, 1, fp) != 1)
896 goto fail;
897 if (fread(&size, sizeof(size), 1, fp) != 1)
898 goto fail;
899 if (size < 0 || size > 0x10000)
900 goto fail;
901 *raw_packet = coap_new_binary(size);
902 if (!(*raw_packet))
903 goto fail;
904 if (fread((*raw_packet)->s, size, 1, fp) != 1)
905 goto fail;
906 return 1;
907 }
908fail:
909 return 0;
910}
911
912/*
913 * write out dynamic resource entry.
914 */
915static int
916coap_op_dyn_resource_write(FILE *fp, coap_proto_t e_proto,
917 coap_str_const_t *name,
918 coap_bin_const_t *raw_packet) {
919 if (fwrite(&e_proto, sizeof(e_proto), 1, fp) != 1)
920 goto fail;
921 if (fwrite(&name->length, sizeof(name->length), 1, fp) != 1)
922 goto fail;
923 if (fwrite(name->s, name->length, 1, fp) != 1)
924 goto fail;
925 if (fwrite(&raw_packet->length, sizeof(raw_packet->length), 1, fp) != 1)
926 goto fail;
927 if (fwrite(raw_packet->s, raw_packet->length, 1, fp) != 1)
928 goto fail;
929 return 1;
930fail:
931 return 0;
932}
933
934/*
935 * This should be called before coap_persist_track_funcs() to prevent
936 * coap_op_dyn_resource_added() getting unnecessarily called.
937 *
938 * Each record 'proto len resource_name len raw_packet'
939 */
940static void
941coap_op_dyn_resource_load_disk(coap_context_t *ctx) {
942 FILE *fp_orig = NULL;
943 coap_proto_t e_proto;
944 coap_string_t *name = NULL;
945 coap_binary_t *raw_packet = NULL;
947 coap_session_t *session = NULL;
948 coap_pdu_t *request = NULL;
949 coap_pdu_t *response = NULL;
950 coap_string_t *query = NULL;
951
952 if (!ctx->unknown_resource && !ctx->dyn_create_handler)
953 return;
954
955 fp_orig = fopen((const char *)ctx->dyn_resource_save_file->s, "r");
956 if (fp_orig == NULL)
957 return;
959 sizeof(coap_session_t));
960 if (!session)
961 goto fail;
962 memset(session, 0, sizeof(coap_session_t));
963 session->context = ctx;
964
965 /* Go through and create each dynamic resource if it does not exist*/
966 while (1) {
967 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
968 break;
969 r = coap_get_resource_from_uri_path_lkd(ctx, (coap_str_const_t *)name);
970 if (!r) {
971 /* Create the new resource using the application logic */
972
973 coap_log_debug("persist: dynamic resource '%s' being re-created\n", name->s);
974 /*
975 * Need max space incase PDU is updated with updated token,
976 * huge size etc.
977 * */
978 request = coap_pdu_init(0, 0, 0, 0);
979 if (!request)
980 goto fail;
981
982 session->proto = e_proto;
983 if (!coap_pdu_parse(session->proto, raw_packet->s,
984 raw_packet->length, request)) {
985 goto fail;
986 }
987 if (request->code == 0 || request->code > 7) {
988 /* Need to protect r->handler[request->code-1] */
989 goto next;
990 }
991 r = coap_add_dynamic_resource(session, request);
992 if (!r) {
993 r = ctx->unknown_resource;
994 }
995 if (!r || !r->handler[request->code-1])
996 goto next;
997
998 response = coap_pdu_init(0, 0, 0, 0);
999 if (!response)
1000 goto fail;
1001 query = coap_get_query(request);
1002 /* Call the application handler to set up this dynamic resource */
1003 if (r->flags & COAP_RESOURCE_SAFE_REQUEST_HANDLER) {
1004 coap_lock_callback_release(r->handler[request->code-1](r,
1005 session, request,
1006 query, response),
1007 /* context is being freed off */
1008 goto fail);
1009 } else {
1011 r->handler[request->code-1](r,
1012 session, request,
1013 query, response),
1014 /* context is being freed off */
1015 goto fail);
1016 }
1017 coap_delete_string(query);
1018 query = NULL;
1019 coap_delete_pdu_lkd(response);
1020 response = NULL;
1021next:
1022 coap_delete_pdu_lkd(request);
1023 request = NULL;
1024 }
1025 coap_delete_string(name);
1026 coap_delete_binary(raw_packet);
1027 }
1028fail:
1029 coap_delete_string(name);
1030 coap_delete_binary(raw_packet);
1031 coap_delete_string(query);
1032 coap_delete_pdu_lkd(request);
1033 coap_delete_pdu_lkd(response);
1034 fclose(fp_orig);
1035 coap_free_type(COAP_SESSION, session);
1036}
1037
1038/*
1039 * Server has set up a new dynamic resource against a request for an unknown
1040 * resource.
1041 */
1042static int
1043coap_op_dyn_resource_added(coap_session_t *session,
1044 coap_str_const_t *resource_name,
1045 coap_bin_const_t *packet,
1046 void *user_data) {
1047 FILE *fp_orig;
1048 FILE *fp_new = NULL;
1049 char *new = NULL;
1050 coap_context_t *context = session->context;
1051 coap_string_t *name = NULL;
1052 coap_binary_t *raw_packet = NULL;
1053 coap_proto_t e_proto;
1054
1055 (void)user_data;
1056
1057 fp_orig = fopen((const char *)context->dyn_resource_save_file->s, "a");
1058 if (fp_orig == NULL)
1059 return 0;
1060
1062 context->dyn_resource_save_file->length + 5);
1063 if (!new)
1064 goto fail;
1065
1066 strcpy(new, (const char *)context->dyn_resource_save_file->s);
1067 strcat(new, ".tmp");
1068 fp_new = fopen(new, "w+");
1069 if (fp_new == NULL)
1070 goto fail;
1071
1072 /* Go through and locate duplicate resource to delete */
1073 while (1) {
1074 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1075 break;
1076 if (!coap_string_equal(resource_name, name)) {
1077 /* Copy across non-matching entry */
1078 if (!coap_op_dyn_resource_write(fp_new, e_proto, (coap_str_const_t *)name,
1079 (coap_bin_const_t *)raw_packet))
1080 break;
1081 }
1082 coap_delete_string(name);
1083 name = NULL;
1084 coap_delete_binary(raw_packet);
1085 raw_packet = NULL;
1086 }
1087 coap_delete_string(name);
1088 coap_delete_binary(raw_packet);
1089 /* Add new entry to the end */
1090 if (!coap_op_dyn_resource_write(fp_new, session->proto,
1091 resource_name, packet))
1092 goto fail;
1093
1094 if (fflush(fp_new) == EOF)
1095 goto fail;
1096 fclose(fp_new);
1097 fclose(fp_orig);
1098 /* Either old or new is in place */
1099 (void)rename(new, (const char *)context->dyn_resource_save_file->s);
1101 return 1;
1102
1103fail:
1104 if (fp_new)
1105 fclose(fp_new);
1106 if (fp_orig)
1107 fclose(fp_orig);
1108 if (new) {
1109 (void)remove(new);
1110 }
1112 return 0;
1113}
1114
1115/*
1116 * Server has deleted a resource
1117 */
1118static int
1119coap_op_resource_deleted(coap_context_t *context,
1120 coap_str_const_t *resource_name,
1121 void *user_data) {
1122 FILE *fp_orig = NULL;
1123 FILE *fp_new = NULL;
1124 char *new = NULL;
1125 coap_proto_t e_proto;
1126 coap_string_t *name = NULL;
1127 coap_binary_t *raw_packet = NULL;
1128 (void)user_data;
1129
1130 coap_op_obs_cnt_deleted(context, resource_name);
1131
1132 fp_orig = fopen((const char *)context->dyn_resource_save_file->s, "r");
1133 if (fp_orig == NULL)
1134 return 1;
1135
1137 context->dyn_resource_save_file->length + 5);
1138 if (!new)
1139 goto fail;
1140
1141 strcpy(new, (const char *)context->dyn_resource_save_file->s);
1142 strcat(new, ".tmp");
1143 fp_new = fopen(new, "w+");
1144 if (fp_new == NULL)
1145 goto fail;
1146
1147 /* Go through and locate resource to delete and not copy it across */
1148 while (1) {
1149 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1150 break;
1151 if (!coap_string_equal(resource_name, name)) {
1152 /* Copy across non-matching entry */
1153 if (!coap_op_dyn_resource_write(fp_new, e_proto, (coap_str_const_t *)name,
1154 (coap_bin_const_t *)raw_packet))
1155 break;
1156 }
1157 coap_delete_string(name);
1158 name = NULL;
1159 coap_delete_binary(raw_packet);
1160 raw_packet = NULL;
1161 }
1162 coap_delete_string(name);
1163 coap_delete_binary(raw_packet);
1164
1165 if (fflush(fp_new) == EOF)
1166 goto fail;
1167 fclose(fp_new);
1168 fclose(fp_orig);
1169 /* Either old or new is in place */
1170 (void)rename(new, (const char *)context->dyn_resource_save_file->s);
1172 return 1;
1173
1174fail:
1175 if (fp_new)
1176 fclose(fp_new);
1177 if (fp_orig)
1178 fclose(fp_orig);
1179 if (new) {
1180 (void)remove(new);
1181 }
1183 return 0;
1184}
1185
1186COAP_API int
1188 const char *dyn_resource_save_file,
1189 const char *observe_save_file,
1190 const char *obs_cnt_save_file,
1191 uint32_t save_freq) {
1192 int ret;
1193
1194 coap_lock_lock(return 0);
1195 ret = coap_persist_startup_lkd(context,
1196 dyn_resource_save_file,
1197 observe_save_file,
1198 obs_cnt_save_file,
1199 save_freq);
1201 return ret;
1202}
1203
1204int
1205coap_persist_startup_lkd(coap_context_t *context,
1206 const char *dyn_resource_save_file,
1207 const char *observe_save_file,
1208 const char *obs_cnt_save_file,
1209 uint32_t save_freq) {
1211 if (dyn_resource_save_file) {
1212 context->dyn_resource_save_file =
1213 coap_new_bin_const((const uint8_t *)dyn_resource_save_file,
1214 strlen(dyn_resource_save_file));
1215 if (!context->dyn_resource_save_file)
1216 return 0;
1217 coap_op_dyn_resource_load_disk(context);
1218 context->dyn_resource_added_cb = coap_op_dyn_resource_added;
1219 context->resource_deleted_cb = coap_op_resource_deleted;
1220 }
1221 if (obs_cnt_save_file) {
1222 context->obs_cnt_save_file =
1223 coap_new_bin_const((const uint8_t *)obs_cnt_save_file,
1224 strlen(obs_cnt_save_file));
1225 if (!context->obs_cnt_save_file)
1226 return 0;
1227 context->observe_save_freq = save_freq ? save_freq : 1;
1228 coap_op_obs_cnt_load_disk(context);
1229 context->track_observe_value_cb = coap_op_obs_cnt_track_observe;
1230 context->resource_deleted_cb = coap_op_resource_deleted;
1231 }
1232 if (observe_save_file) {
1233 context->observe_save_file =
1234 coap_new_bin_const((const uint8_t *)observe_save_file,
1235 strlen(observe_save_file));
1236 if (!context->observe_save_file)
1237 return 0;
1238 coap_op_observe_load_disk(context);
1239 context->observe_added_cb = coap_op_observe_added;
1240 context->observe_deleted_cb = coap_op_observe_deleted;
1241 }
1242 return 1;
1243}
1244
1245void
1246coap_persist_cleanup(coap_context_t *context) {
1247 coap_delete_bin_const(context->dyn_resource_save_file);
1248 coap_delete_bin_const(context->obs_cnt_save_file);
1249 coap_delete_bin_const(context->observe_save_file);
1250 context->dyn_resource_save_file = NULL;
1251 context->obs_cnt_save_file = NULL;
1252 context->observe_save_file = NULL;
1253
1254 /* Close down any tracking */
1256 NULL, 0, NULL);
1257}
1258
1259COAP_API void
1261 if (!context)
1262 return;
1263 coap_lock_lock(return);
1264 coap_persist_stop_lkd(context);
1266}
1267
1268void
1269coap_persist_stop_lkd(coap_context_t *context) {
1270 if (context == NULL)
1271 return;
1273 context->observe_no_clear = 1;
1274 coap_persist_cleanup(context);
1275}
1276#else /* ! COAP_WITH_OBSERVE_PERSIST */
1277COAP_API int
1279 const char *dyn_resource_save_file,
1280 const char *observe_save_file,
1281 const char *obs_cnt_save_file,
1282 uint32_t save_freq) {
1283 (void)context;
1284 (void)dyn_resource_save_file;
1285 (void)observe_save_file;
1286 (void)obs_cnt_save_file;
1287 (void)save_freq;
1288 return 0;
1289}
1290
1291COAP_API void
1293 context->observe_no_clear = 1;
1294 /* Close down any tracking */
1296 NULL, 0, NULL);
1297}
1298
1299#endif /* ! COAP_WITH_OBSERVE_PERSIST */
1300
1301#endif /* COAP_SERVER_SUPPORT */
#define INET6_ADDRSTRLEN
Definition coap_debug.c:234
struct coap_endpoint_t coap_endpoint_t
struct coap_subscription_t coap_subscription_t
struct coap_resource_t coap_resource_t
const char * coap_socket_strerror(void)
Definition coap_io.c:963
Library specific build wrapper for coap_internal.h.
#define COAP_API
@ COAP_SESSION
Definition coap_mem.h:45
@ COAP_STRING
Definition coap_mem.h:33
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
#define NULL
Definition coap_option.h:30
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
@ COAP_OPTION_OBSERVE
Definition coap_option.h:75
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:149
#define COAP_RESOURCE_SAFE_REQUEST_HANDLER
Don't lock this resource when calling app call-back handler for requests as handler will not be manip...
void coap_ticks(coap_tick_t *t)
Returns the current value of an internal tick counter.
Definition coap_time.c:90
unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition coap_encode.c:38
#define coap_lock_specific_callback_release(lock, func, failed)
Dummy for no thread-safe code.
#define coap_lock_unlock()
Dummy for no thread-safe code.
#define coap_lock_check_locked()
Dummy for no thread-safe code.
#define coap_lock_callback_release(func, failed)
Dummy for no thread-safe code.
#define coap_lock_lock(failed)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:126
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition coap_debug.c:103
size_t coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len)
Print the address into the defined buffer.
Definition coap_debug.c:241
#define coap_log_warn(...)
Definition coap_debug.h:108
@ COAP_LOG_OSCORE
Definition coap_debug.h:65
@ COAP_LOG_WARN
Definition coap_debug.h:61
COAP_API coap_subscription_t * coap_persist_observe_add(coap_context_t *context, coap_proto_t e_proto, const coap_address_t *e_listen_addr, const coap_addr_tuple_t *s_addr_info, const coap_bin_const_t *raw_packet, const coap_bin_const_t *oscore_info)
Set up an active subscription for an observe that was previously active over a coap-server inadvertan...
int(* coap_dyn_resource_added_t)(coap_session_t *session, coap_str_const_t *resource_name, coap_bin_const_t *raw_packet, void *user_data)
Callback handler definition called when a dynamic resource is getting created, as defined in coap_per...
void coap_persist_set_observe_num(coap_resource_t *resource, uint32_t observe_num)
Sets the current observe number value.
int(* coap_resource_deleted_t)(coap_context_t *context, coap_str_const_t *resource_name, void *user_data)
Callback handler definition called when resource is removed, as defined in coap_persist_track_funcs()...
int(* coap_observe_added_t)(coap_session_t *session, coap_subscription_t *observe_key, coap_proto_t e_proto, coap_address_t *e_listen_addr, coap_addr_tuple_t *s_addr_info, coap_bin_const_t *raw_packet, coap_bin_const_t *oscore_info, void *user_data)
Callback handler definition called when a new observe has been set up, as defined in coap_persist_tra...
#define COAP_OBSERVE_ESTABLISH
The value COAP_OBSERVE_ESTABLISH in a GET/FETCH request option COAP_OPTION_OBSERVE indicates a new ob...
COAP_API void coap_persist_stop(coap_context_t *context)
Stop tracking persist information, leaving the current persist information in the files defined in co...
void coap_persist_track_funcs(coap_context_t *context, coap_observe_added_t observe_added, coap_observe_deleted_t observe_deleted, coap_track_observe_value_t track_observe_value, coap_dyn_resource_added_t dyn_resource_added, coap_resource_deleted_t resource_deleted, uint32_t save_freq, void *user_data)
Set up callbacks to handle persist tracking so on a coap-server inadvertent restart,...
int(* coap_track_observe_value_t)(coap_context_t *context, coap_str_const_t *resource_name, uint32_t observe_num, void *user_data)
Callback handler definition called when an observe unsolicited response is being sent,...
int(* coap_observe_deleted_t)(coap_session_t *session, coap_subscription_t *observe_key, void *user_data)
Callback handler definition called when an observe is being removed, as defined in coap_persist_track...
COAP_API int coap_persist_startup(coap_context_t *context, const char *dyn_resource_save_file, const char *observe_save_file, const char *obs_cnt_save_file, uint32_t save_freq)
Start up persist tracking using the libcoap module.
uint32_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
coap_opt_t * coap_check_option(const coap_pdu_t *pdu, coap_option_num_t number, coap_opt_iterator_t *oi)
Retrieves the first option of number number from pdu.
const uint8_t * coap_opt_value(const coap_opt_t *opt)
Returns a pointer to the value of the given option.
#define CBOR_BYTE_STRING
Definition oscore_cbor.h:64
#define CBOR_NULL
Definition oscore_cbor.h:74
uint64_t oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_size)
#define CBOR_SIMPLE_VALUE
Definition oscore_cbor.h:69
uint8_t oscore_cbor_get_next_element(const uint8_t **buffer, size_t *buf_size)
#define CBOR_ARRAY
Definition oscore_cbor.h:66
int oscore_new_association(coap_session_t *session, coap_pdu_t *sent_pdu, coap_bin_const_t *token, oscore_recipient_ctx_t *recipient_ctx, coap_bin_const_t *aad, coap_bin_const_t *nonce, coap_bin_const_t *partial_iv, int is_observe)
oscore_ctx_t * oscore_find_context(coap_session_t *session, const coap_bin_const_t rcpkey_id, const coap_bin_const_t *ctxkey_id, uint8_t *oscore_r2, oscore_recipient_ctx_t **recipient_ctx)
oscore_find_context - Locate recipient context (and hence OSCORE context)
void oscore_log_hex_value(coap_log_t level, const char *name, coap_bin_const_t *value)
void coap_delete_pdu_lkd(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
Definition coap_pdu.c:197
coap_proto_t
CoAP protocol types Note: coap_layers_coap[] needs updating if extended.
Definition coap_pdu.h:234
int coap_pdu_parse(coap_proto_t proto, const uint8_t *data, size_t length, coap_pdu_t *pdu)
Parses data into the CoAP PDU structure given in result.
Definition coap_pdu.c:1569
coap_pdu_t * coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code, coap_mid_t mid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size.
Definition coap_pdu.c:104
@ COAP_PROTO_UDP
Definition coap_pdu.h:236
@ COAP_REQUEST_CODE_GET
Definition coap_pdu.h:251
@ COAP_REQUEST_CODE_FETCH
Definition coap_pdu.h:255
void coap_delete_bin_const(coap_bin_const_t *s)
Deletes the given const binary data and releases any memory allocated.
Definition coap_str.c:130
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:81
coap_bin_const_t * coap_new_bin_const(const uint8_t *data, size_t size)
Take the specified byte array (text) and create a coap_bin_const_t * Returns a new const binary objec...
Definition coap_str.c:119
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:114
#define coap_binary_equal(binary1, binary2)
Compares the two binary data for equality.
Definition coap_str.h:222
#define coap_string_equal(string1, string2)
Compares the two strings for equality.
Definition coap_str.h:208
coap_string_t * coap_new_string(size_t size)
Returns a new string object with at least size+1 bytes storage allocated.
Definition coap_str.c:21
void coap_delete_string(coap_string_t *s)
Deletes the given string and releases any memory allocated.
Definition coap_str.c:50
int coap_observe_persist_is_supported(void)
Check whether Observe Persist is available.
coap_string_t * coap_get_uri_path(const coap_pdu_t *request)
Extract uri_path string from request PDU.
Definition coap_uri.c:1182
coap_string_t * coap_get_query(const coap_pdu_t *request)
Extract query string from request PDU according to escape rules in 6.5.8.
Definition coap_uri.c:1103
Multi-purpose address abstraction.
CoAP binary data definition with const data.
Definition coap_str.h:65
size_t length
length of binary data
Definition coap_str.h:66
const uint8_t * s
read-only binary data
Definition coap_str.h:67
CoAP binary data definition.
Definition coap_str.h:57
size_t length
length of binary data
Definition coap_str.h:58
uint8_t * s
binary data
Definition coap_str.h:59
The CoAP stack's global state is stored in a coap_context_t object.
coap_resource_dynamic_create_t dyn_create_handler
Dynamc resource create handler.
Iterator to run through PDU options.
size_t length
length of payload
coap_addr_tuple_t addr_info
local and remote addresses
unsigned char * payload
payload
int ifindex
the interface index
structure for CoAP PDUs
size_t max_size
maximum size for token, options and payload, or zero for variable size pdu
coap_pdu_code_t code
request method (value 1–31) or response code (value 64-255)
coap_bin_const_t actual_token
Actual token in pdu.
size_t used_size
used bytes of storage for token, options and payload
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_proto_t proto
protocol used
coap_context_t * context
session's context
CoAP string data definition with const data.
Definition coap_str.h:47
const uint8_t * s
read-only string data
Definition coap_str.h:49
size_t length
length of string
Definition coap_str.h:48
CoAP string data definition.
Definition coap_str.h:39
uint8_t * s
string data
Definition coap_str.h:41