libcoap 4.3.5-develop-3f4d08f
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
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
247 /* id_context */
248 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
249 if (ret == CBOR_BYTE_STRING) {
250 id_context.length = oscore_cbor_get_element_size(&info_buf,
251 &info_buf_len);
252 if (id_context.length > info_buf_len)
253 goto oscore_fail;
254 id_context.s = info_buf;
255 info_buf += id_context.length;
256 have_id_context = 1;
257 } else if (ret == CBOR_SIMPLE_VALUE &&
259 &info_buf_len) == CBOR_NULL) {
260 } else
261 goto oscore_fail;
262
263 /* aad */
264 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
265 if (ret == CBOR_BYTE_STRING) {
266 aad.length = oscore_cbor_get_element_size(&info_buf, &info_buf_len);
267 if (aad.length > info_buf_len)
268 goto oscore_fail;
269 aad.s = info_buf;
270 info_buf += aad.length;
271 have_aad = 1;
272 } else if (ret == CBOR_SIMPLE_VALUE &&
274 &info_buf_len) == CBOR_NULL) {
275 } else
276 goto oscore_fail;
277
278 /* partial_iv */
279 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
280 if (ret == CBOR_BYTE_STRING) {
281 partial_iv.length = oscore_cbor_get_element_size(&info_buf,
282 &info_buf_len);
283 if (partial_iv.length > info_buf_len)
284 goto oscore_fail;
285 partial_iv.s = info_buf;
286 info_buf += partial_iv.length;
287 have_partial_iv = 1;
288 } else if (ret == CBOR_SIMPLE_VALUE &&
290 &info_buf_len) == CBOR_NULL) {
291 } else
292 goto oscore_fail;
293
294 /* nonce */
295 ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len);
296 if (ret == CBOR_BYTE_STRING) {
297 nonce.length = oscore_cbor_get_element_size(&info_buf,
298 &info_buf_len);
299 if (nonce.length > info_buf_len)
300 goto oscore_fail;
301 nonce.s = info_buf;
302 info_buf += nonce.length;
303 have_nonce = 1;
304 } else if (ret == CBOR_SIMPLE_VALUE &&
306 &info_buf_len) == CBOR_NULL) {
307 } else
308 goto oscore_fail;
309
310 osc_ctx = oscore_find_context(session, oscore_key_id,
311 have_id_context ? &id_context : NULL, NULL,
312 &session->recipient_ctx);
313 if (osc_ctx) {
314 session->oscore_encryption = 1;
315 oscore_new_association(session, pdu, &pdu->actual_token,
316 session->recipient_ctx,
317 have_aad ? &aad : NULL,
318 have_nonce ? &nonce : NULL,
319 have_partial_iv ? &partial_iv : NULL,
320 1);
321 coap_log_debug("persist: OSCORE association added\n");
323 have_partial_iv ? &partial_iv : NULL);
324 }
325 }
326oscore_fail:
327#else /* ! COAP_OSCORE_SUPPORT */
328 (void)oscore_info;
329#endif /* ! COAP_OSCORE_SUPPORT */
331 return s;
332
333malformed:
334 coap_log_warn("coap_persist_observe_add: discard malformed PDU\n");
335fail:
336 coap_delete_string(uri_path);
338 return NULL;
339}
340
341#if COAP_WITH_OBSERVE_PERSIST
342#include <stdio.h>
343
344/*
345 * read in active observe entry.
346 */
347static int
348coap_op_observe_read(FILE *fp, coap_subscription_t **observe_key,
349 coap_proto_t *e_proto, coap_address_t *e_listen_addr,
350 coap_addr_tuple_t *s_addr_info,
351 coap_bin_const_t **raw_packet, coap_bin_const_t **oscore_info) {
352 ssize_t size;
353 coap_binary_t *scratch = NULL;
354
355 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
356 raw_packet && oscore_info);
357
358 *raw_packet = NULL;
359 *oscore_info = NULL;
360
361 if (fread(observe_key, sizeof(*observe_key), 1, fp) == 1) {
362 /* New record 'key proto listen addr_info len raw_packet len oscore' */
363 if (fread(e_proto, sizeof(*e_proto), 1, fp) != 1)
364 goto fail;
365 if (fread(e_listen_addr, sizeof(*e_listen_addr), 1, fp) != 1)
366 goto fail;
367 if (fread(s_addr_info, sizeof(*s_addr_info), 1, fp) != 1)
368 goto fail;
369 if (fread(&size, sizeof(size), 1, fp) != 1)
370 goto fail;
371 if (size < 0 || size > 0x10000)
372 goto fail;
373 scratch = coap_new_binary(size);
374 if ((scratch) == NULL)
375 goto fail;
376 if (fread(scratch->s, scratch->length, 1, fp) != 1)
377 goto fail;
378 *raw_packet = (coap_bin_const_t *)scratch;
379 scratch = NULL;
380 if (fread(&size, sizeof(size), 1, fp) != 1)
381 goto fail;
382 /* If size == -1, then no oscore information */
383 if (size == -1)
384 return 1;
385 else if (size < 0 || size > 0x10000)
386 goto fail;
387 else {
388 scratch = coap_new_binary(size);
389 if (scratch == NULL)
390 goto fail;
391 if (fread(scratch->s, scratch->length, 1, fp) != 1)
392 goto fail;
393 *oscore_info = (coap_bin_const_t *)scratch;
394 }
395 return 1;
396 }
397fail:
398 coap_delete_bin_const(*raw_packet);
399 coap_delete_binary(scratch);
400
401 *observe_key = NULL;
402 memset(e_proto, 0, sizeof(*e_proto));
403 memset(e_listen_addr, 0, sizeof(*e_listen_addr));
404 memset(s_addr_info, 0, sizeof(*s_addr_info));
405 *raw_packet = NULL;
406 return 0;
407}
408
409/*
410 * write out active observe entry.
411 */
412static int
413coap_op_observe_write(FILE *fp, coap_subscription_t *observe_key,
414 coap_proto_t e_proto, coap_address_t e_listen_addr,
415 coap_addr_tuple_t s_addr_info,
416 coap_bin_const_t *raw_packet, coap_bin_const_t *oscore_info) {
417 if (fwrite(&observe_key, sizeof(observe_key), 1, fp) != 1)
418 goto fail;
419 if (fwrite(&e_proto, sizeof(e_proto), 1, fp) != 1)
420 goto fail;
421 if (fwrite(&e_listen_addr, sizeof(e_listen_addr),
422 1, fp) != 1)
423 goto fail;
424 if (fwrite(&s_addr_info, sizeof(s_addr_info), 1, fp) != 1)
425 goto fail;
426 if (fwrite(&raw_packet->length, sizeof(raw_packet->length), 1, fp) != 1)
427 goto fail;
428 if (fwrite(raw_packet->s, raw_packet->length, 1, fp) != 1)
429 goto fail;
430 if (oscore_info) {
431 if (fwrite(&oscore_info->length, sizeof(oscore_info->length), 1, fp) != 1)
432 goto fail;
433 if (fwrite(oscore_info->s, oscore_info->length, 1, fp) != 1)
434 goto fail;
435 } else {
436 ssize_t not_defined = -1;
437
438 if (fwrite(&not_defined, sizeof(not_defined), 1, fp) != 1)
439 goto fail;
440 }
441 return 1;
442fail:
443 return 0;
444}
445
446/*
447 * This should be called before coap_persist_track_funcs() to prevent
448 * coap_op_observe_added() getting unnecessarily called.
449 * It should be called after init_resources() and coap_op_resource_load_disk()
450 * so that all the resources are in place.
451 */
452static void
453coap_op_observe_load_disk(coap_context_t *ctx) {
454 FILE *fp_orig = fopen((const char *)ctx->observe_save_file->s, "r");
455 FILE *fp_new = NULL;
456 coap_subscription_t *observe_key = NULL;
457 coap_proto_t e_proto;
458 coap_address_t e_listen_addr;
459 coap_addr_tuple_t s_addr_info;
460 coap_bin_const_t *raw_packet = NULL;
461 coap_bin_const_t *oscore_info = NULL;
462 char *new = NULL;
463
464 if (fp_orig == NULL)
465 goto fail;
466
467 new = coap_malloc_type(COAP_STRING, ctx->observe_save_file->length + 5);
468 if (!new)
469 goto fail;
470
471 strcpy(new, (const char *)ctx->observe_save_file->s);
472 strcat(new, ".tmp");
473 fp_new = fopen(new, "w+");
474 if (fp_new == NULL)
475 goto fail;
476
477 /* Go through and load oscore entry, updating key on the way */
478 while (1) {
479 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
480 &s_addr_info, &raw_packet, &oscore_info))
481 break;
482 coap_log_debug("persist: New session/observe being created\n");
483 observe_key = coap_persist_observe_add_lkd(ctx, e_proto,
484 &e_listen_addr,
485 &s_addr_info,
486 raw_packet,
487 oscore_info);
488 if (observe_key) {
489 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
490 s_addr_info, raw_packet, oscore_info))
491 goto fail;
492 }
493 coap_delete_bin_const(raw_packet);
494 raw_packet = NULL;
495 coap_delete_bin_const(oscore_info);
496 oscore_info = NULL;
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 if (fflush(fp_new) == EOF)
504 goto fail;
505 fclose(fp_new);
506 fclose(fp_orig);
507 /* Either old or new is in place */
508 if (rename(new, (const char *)ctx->observe_save_file->s) == -1) {
509 coap_log_warn("rename %s -> %s: failed: %s (%d)\n",
510 new, (const char *)ctx->observe_save_file->s,
511 coap_socket_strerror(), errno);
512 }
514 return;
515
516fail:
517 coap_delete_bin_const(raw_packet);
518 coap_delete_bin_const(oscore_info);
519 if (fp_new)
520 fclose(fp_new);
521 if (fp_orig)
522 fclose(fp_orig);
523 if (new) {
524 (void)remove(new);
525 }
527 return;
528}
529
530/*
531 * client has registered a new observe subscription request.
532 */
533static int
534coap_op_observe_added(coap_session_t *session,
535 coap_subscription_t *a_observe_key,
536 coap_proto_t a_e_proto, coap_address_t *a_e_listen_addr,
537 coap_addr_tuple_t *a_s_addr_info,
538 coap_bin_const_t *a_raw_packet,
539 coap_bin_const_t *a_oscore_info, void *user_data) {
540 FILE *fp_orig = fopen((const char *)session->context->observe_save_file->s,
541 "r");
542 FILE *fp_new = NULL;
543 coap_subscription_t *observe_key = NULL;
544 coap_proto_t e_proto;
545 coap_address_t e_listen_addr;
546 coap_addr_tuple_t s_addr_info;
547 coap_bin_const_t *raw_packet = NULL;
548 coap_bin_const_t *oscore_info = NULL;
549 char *new = NULL;
550
551 (void)user_data;
552
554 session->context->observe_save_file->length + 5);
555 if (!new)
556 goto fail;
557
558 strcpy(new, (const char *)session->context->observe_save_file->s);
559 strcat(new, ".tmp");
560 fp_new = fopen(new, "w+");
561 if (fp_new == NULL)
562 goto fail;
563
564 /* Go through and delete observe entry if it exists */
565 while (fp_orig) {
566 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
567 &s_addr_info, &raw_packet, &oscore_info))
568 break;
569 if (observe_key != a_observe_key) {
570 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
571 s_addr_info, raw_packet, oscore_info))
572 goto fail;
573 }
574 coap_delete_bin_const(raw_packet);
575 raw_packet = NULL;
576 coap_delete_bin_const(oscore_info);
577 oscore_info = NULL;
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 /* Add in new entry to the end */
585 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
586 *a_s_addr_info, a_raw_packet, a_oscore_info))
587 goto fail;
588
589 if (fflush(fp_new) == EOF)
590 goto fail;
591 fclose(fp_new);
592 if (fp_orig)
593 fclose(fp_orig);
594 /* Either old or new is in place */
595 (void)rename(new, (const char *)session->context->observe_save_file->s);
597 return 1;
598
599fail:
600 coap_delete_bin_const(raw_packet);
601 coap_delete_bin_const(oscore_info);
602 if (fp_new)
603 fclose(fp_new);
604 if (fp_orig)
605 fclose(fp_orig);
606 if (new) {
607 (void)remove(new);
608 }
610 return 0;
611}
612
613/*
614 * client has de-registered a observe subscription request.
615 */
616static int
617coap_op_observe_deleted(coap_session_t *session,
618 coap_subscription_t *d_observe_key,
619 void *user_data) {
620 FILE *fp_orig = fopen((const char *)session->context->observe_save_file->s,
621 "r");
622 FILE *fp_new = NULL;
623 coap_subscription_t *observe_key = NULL;
624 coap_proto_t e_proto;
625 coap_address_t e_listen_addr;
626 coap_addr_tuple_t s_addr_info;
627 coap_bin_const_t *raw_packet = NULL;
628 coap_bin_const_t *oscore_info = NULL;
629 char *new = NULL;
630
631 (void)user_data;
632
633 if (fp_orig == NULL)
634 goto fail;
636 session->context->observe_save_file->length + 5);
637 if (!new)
638 goto fail;
639
640 strcpy(new, (const char *)session->context->observe_save_file->s);
641 strcat(new, ".tmp");
642 fp_new = fopen(new, "w+");
643 if (fp_new == NULL)
644 goto fail;
645
646 /* Go through and locate observe entry to delete and not copy it across */
647 while (1) {
648 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
649 &s_addr_info, &raw_packet, &oscore_info))
650 break;
651 if (observe_key != d_observe_key) {
652 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
653 s_addr_info, (coap_bin_const_t *)raw_packet,
654 (coap_bin_const_t *)oscore_info))
655 goto fail;
656 }
657 coap_delete_bin_const(raw_packet);
658 raw_packet = NULL;
659 coap_delete_bin_const(oscore_info);
660 oscore_info = NULL;
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 if (fflush(fp_new) == EOF)
668 goto fail;
669 fclose(fp_new);
670 fclose(fp_orig);
671 /* Either old or new is in place */
672 (void)rename(new, (const char *)session->context->observe_save_file->s);
674 return 1;
675
676fail:
677 coap_delete_bin_const(raw_packet);
678 coap_delete_bin_const(oscore_info);
679 if (fp_new)
680 fclose(fp_new);
681 if (fp_orig)
682 fclose(fp_orig);
683 if (new) {
684 (void)remove(new);
685 }
687 return 0;
688}
689
690/*
691 * This should be called before coap_persist_track_funcs() to prevent
692 * coap_op_obs_cnt_track_observe() getting unnecessarily called.
693 * Should be called after coap_op_dyn_resource_load_disk() to make sure that
694 * all the resources are in the right place.
695 */
696static void
697coap_op_obs_cnt_load_disk(coap_context_t *context) {
698 FILE *fp = fopen((const char *)context->obs_cnt_save_file->s, "r");
699 char buf[1500];
700
701 if (fp == NULL)
702 return;
703
704 while (fgets(buf, sizeof(buf), fp) != NULL) {
705 char *cp = strchr(buf, ' ');
706 coap_str_const_t resource_key;
707 uint32_t observe_num;
709
710 if (!cp)
711 break;
712
713 *cp = '\000';
714 cp++;
715 observe_num = atoi(cp);
716 /*
717 * Need to assume 0 .. (context->observe_save_freq-1) have in addition
718 * been sent so need to round up to latest possible send value
719 */
720 observe_num = ((observe_num + context->observe_save_freq) /
721 context->observe_save_freq) *
722 context->observe_save_freq - 1;
723 resource_key.s = (uint8_t *)buf;
724 resource_key.length = strlen(buf);
725 r = coap_get_resource_from_uri_path_lkd(context, &resource_key);
726 if (r) {
727 coap_log_debug("persist: Initial observe number being updated '%s' %u\n",
728 buf, observe_num);
729 coap_persist_set_observe_num(r, observe_num);
730 }
731 }
732 fclose(fp);
733}
734
735/*
736 * Called when the observe value of a resource has been changed, but limited
737 * to be called every context->context->observe_save_freq to reduce update
738 * overheads.
739 */
740static int
741coap_op_obs_cnt_track_observe(coap_context_t *context,
742 coap_str_const_t *resource_name,
743 uint32_t n_observe_num,
744 void *user_data) {
745 FILE *fp_orig = fopen((const char *)context->obs_cnt_save_file->s, "r");
746 FILE *fp_new = NULL;
747 char buf[1500];
748 char *new = NULL;
749
750 (void)user_data;
751
752 new = coap_malloc_type(COAP_STRING, context->obs_cnt_save_file->length + 5);
753 if (!new)
754 goto fail;
755
756 strcpy(new, (const char *)context->obs_cnt_save_file->s);
757 strcat(new, ".tmp");
758 fp_new = fopen(new, "w+");
759 if (fp_new == NULL)
760 goto fail;
761
762 /* Go through and locate resource entry to update */
763 while (fp_orig && fgets(buf, sizeof(buf), fp_orig) != NULL) {
764 char *cp = strchr(buf, ' ');
765 uint32_t observe_num;
766 coap_bin_const_t resource_key;
767
768 if (!cp)
769 break;
770
771 *cp = '\000';
772 cp++;
773 observe_num = atoi(cp);
774 resource_key.s = (uint8_t *)buf;
775 resource_key.length = strlen(buf);
776 if (!coap_binary_equal(resource_name, &resource_key)) {
777 if (fprintf(fp_new, "%s %u\n", resource_key.s, observe_num) < 0)
778 goto fail;
779 }
780 }
781 if (fprintf(fp_new, "%s %u\n", resource_name->s, n_observe_num) < 0)
782 goto fail;
783 if (fflush(fp_new) == EOF)
784 goto fail;
785 fclose(fp_new);
786 if (fp_orig)
787 fclose(fp_orig);
788 /* Either old or new is in place */
789 (void)rename(new, (const char *)context->obs_cnt_save_file->s);
791 return 1;
792
793fail:
794 if (fp_new)
795 fclose(fp_new);
796 if (fp_orig)
797 fclose(fp_orig);
798 if (new) {
799 (void)remove(new);
800 }
802 return 0;
803}
804
805/*
806 * Called when a resource has been deleted.
807 */
808static int
809coap_op_obs_cnt_deleted(coap_context_t *context,
810 coap_str_const_t *resource_name) {
811 FILE *fp_orig = fopen((const char *)context->obs_cnt_save_file->s, "r");
812 FILE *fp_new = NULL;
813 char buf[1500];
814 char *new = NULL;
815
816 if (fp_orig == NULL)
817 goto fail;
818 new = coap_malloc_type(COAP_STRING, context->obs_cnt_save_file->length + 5);
819 if (!new)
820 goto fail;
821
822 strcpy(new, (const char *)context->obs_cnt_save_file->s);
823 strcat(new, ".tmp");
824 fp_new = fopen(new, "w+");
825 if (fp_new == NULL)
826 goto fail;
827
828 /* Go through and locate resource entry to delete */
829 while (fgets(buf, sizeof(buf), fp_orig) != NULL) {
830 char *cp = strchr(buf, ' ');
831 uint32_t observe_num;
832 coap_bin_const_t resource_key;
833
834 if (!cp)
835 break;
836
837 *cp = '\000';
838 cp++;
839 observe_num = atoi(cp);
840 resource_key.s = (uint8_t *)buf;
841 resource_key.length = strlen(buf);
842 if (!coap_binary_equal(resource_name, &resource_key)) {
843 if (fprintf(fp_new, "%s %u\n", resource_key.s, observe_num) < 0)
844 goto fail;
845 }
846 }
847 if (fflush(fp_new) == EOF)
848 goto fail;
849 fclose(fp_new);
850 fclose(fp_orig);
851 /* Either old or new is in place */
852 (void)rename(new, (const char *)context->obs_cnt_save_file->s);
854 return 1;
855
856fail:
857 if (fp_new)
858 fclose(fp_new);
859 if (fp_orig)
860 fclose(fp_orig);
861 if (new) {
862 (void)remove(new);
863 }
865 return 0;
866}
867
868/*
869 * read in dynamic resource entry, allocating name & raw_packet
870 * which need to be freed off by caller.
871 */
872static int
873coap_op_dyn_resource_read(FILE *fp, coap_proto_t *e_proto,
874 coap_string_t **name,
875 coap_binary_t **raw_packet) {
876 ssize_t size;
877
878 *name = NULL;
879 *raw_packet = NULL;
880
881 if (fread(e_proto, sizeof(*e_proto), 1, fp) == 1) {
882 /* New record 'proto len resource_name len raw_packet' */
883 if (fread(&size, sizeof(size), 1, fp) != 1)
884 goto fail;
885 if (size < 0 || size > 0x10000)
886 goto fail;
887 *name = coap_new_string(size);
888 if (!(*name))
889 goto fail;
890 if (fread((*name)->s, size, 1, fp) != 1)
891 goto fail;
892 if (fread(&size, sizeof(size), 1, fp) != 1)
893 goto fail;
894 if (size < 0 || size > 0x10000)
895 goto fail;
896 *raw_packet = coap_new_binary(size);
897 if (!(*raw_packet))
898 goto fail;
899 if (fread((*raw_packet)->s, size, 1, fp) != 1)
900 goto fail;
901 return 1;
902 }
903fail:
904 return 0;
905}
906
907/*
908 * write out dynamic resource entry.
909 */
910static int
911coap_op_dyn_resource_write(FILE *fp, coap_proto_t e_proto,
912 coap_str_const_t *name,
913 coap_bin_const_t *raw_packet) {
914 if (fwrite(&e_proto, sizeof(e_proto), 1, fp) != 1)
915 goto fail;
916 if (fwrite(&name->length, sizeof(name->length), 1, fp) != 1)
917 goto fail;
918 if (fwrite(name->s, name->length, 1, fp) != 1)
919 goto fail;
920 if (fwrite(&raw_packet->length, sizeof(raw_packet->length), 1, fp) != 1)
921 goto fail;
922 if (fwrite(raw_packet->s, raw_packet->length, 1, fp) != 1)
923 goto fail;
924 return 1;
925fail:
926 return 0;
927}
928
929/*
930 * This should be called before coap_persist_track_funcs() to prevent
931 * coap_op_dyn_resource_added() getting unnecessarily called.
932 *
933 * Each record 'proto len resource_name len raw_packet'
934 */
935static void
936coap_op_dyn_resource_load_disk(coap_context_t *ctx) {
937 FILE *fp_orig = NULL;
938 coap_proto_t e_proto;
939 coap_string_t *name = NULL;
940 coap_binary_t *raw_packet = NULL;
942 coap_session_t *session = NULL;
943 coap_pdu_t *request = NULL;
944 coap_pdu_t *response = NULL;
945 coap_string_t *query = NULL;
946
947 if (!ctx->unknown_resource && !ctx->dyn_create_handler)
948 return;
949
950 fp_orig = fopen((const char *)ctx->dyn_resource_save_file->s, "r");
951 if (fp_orig == NULL)
952 return;
954 sizeof(coap_session_t));
955 if (!session)
956 goto fail;
957 memset(session, 0, sizeof(coap_session_t));
958 session->context = ctx;
959
960 /* Go through and create each dynamic resource if it does not exist*/
961 while (1) {
962 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
963 break;
964 r = coap_get_resource_from_uri_path_lkd(ctx, (coap_str_const_t *)name);
965 if (!r) {
966 /* Create the new resource using the application logic */
967
968 coap_log_debug("persist: dynamic resource '%s' being re-created\n", name->s);
969 /*
970 * Need max space incase PDU is updated with updated token,
971 * huge size etc.
972 * */
973 request = coap_pdu_init(0, 0, 0, 0);
974 if (!request)
975 goto fail;
976
977 session->proto = e_proto;
978 if (!coap_pdu_parse(session->proto, raw_packet->s,
979 raw_packet->length, request)) {
980 goto fail;
981 }
982 r = ctx->unknown_resource;
983 if ((ctx->dyn_create_handler != NULL) &&
984 (request->code == COAP_REQUEST_CODE_PUT || request->code == COAP_REQUEST_CODE_POST)) {
985 /* Above test must be the same as in handle_request() */
986 if (ctx->dynamic_cur < ctx->dynamic_max || ctx->dynamic_max == 0) {
987 ctx->unknown_pdu = request;
988 ctx->unknown_session = session;
989 coap_lock_callback_ret(r, ctx->dyn_create_handler(session, request));
990 ctx->unknown_pdu = NULL;
991 ctx->unknown_session = NULL;
992 }
993 }
994 if (!r || !r->handler[request->code-1])
995 goto next;
996
997 response = coap_pdu_init(0, 0, 0, 0);
998 if (!response)
999 goto fail;
1000 query = coap_get_query(request);
1001 /* Call the application handler to set up this dynamic resource */
1002 if (r->flags & COAP_RESOURCE_SAFE_REQUEST_HANDLER) {
1003 coap_lock_callback_release(r->handler[request->code-1](r,
1004 session, request,
1005 query, response),
1006 /* context is being freed off */
1007 goto fail);
1008 } else {
1010 r->handler[request->code-1](r,
1011 session, request,
1012 query, response),
1013 /* context is being freed off */
1014 goto fail);
1015 }
1016 coap_delete_string(query);
1017 query = NULL;
1018 coap_delete_pdu_lkd(response);
1019 response = NULL;
1020next:
1021 coap_delete_pdu_lkd(request);
1022 request = NULL;
1023 }
1024 coap_delete_string(name);
1025 coap_delete_binary(raw_packet);
1026 }
1027fail:
1028 coap_delete_string(name);
1029 coap_delete_binary(raw_packet);
1030 coap_delete_string(query);
1031 coap_delete_pdu_lkd(request);
1032 coap_delete_pdu_lkd(response);
1033 fclose(fp_orig);
1034 coap_free_type(COAP_SESSION, session);
1035}
1036
1037/*
1038 * Server has set up a new dynamic resource against a request for an unknown
1039 * resource.
1040 */
1041static int
1042coap_op_dyn_resource_added(coap_session_t *session,
1043 coap_str_const_t *resource_name,
1044 coap_bin_const_t *packet,
1045 void *user_data) {
1046 FILE *fp_orig;
1047 FILE *fp_new = NULL;
1048 char *new = NULL;
1049 coap_context_t *context = session->context;
1050 coap_string_t *name = NULL;
1051 coap_binary_t *raw_packet = NULL;
1052 coap_proto_t e_proto;
1053
1054 (void)user_data;
1055
1056 fp_orig = fopen((const char *)context->dyn_resource_save_file->s, "a");
1057 if (fp_orig == NULL)
1058 return 0;
1059
1061 context->dyn_resource_save_file->length + 5);
1062 if (!new)
1063 goto fail;
1064
1065 strcpy(new, (const char *)context->dyn_resource_save_file->s);
1066 strcat(new, ".tmp");
1067 fp_new = fopen(new, "w+");
1068 if (fp_new == NULL)
1069 goto fail;
1070
1071 /* Go through and locate duplicate resource to delete */
1072 while (1) {
1073 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1074 break;
1075 if (!coap_string_equal(resource_name, name)) {
1076 /* Copy across non-matching entry */
1077 if (!coap_op_dyn_resource_write(fp_new, e_proto, (coap_str_const_t *)name,
1078 (coap_bin_const_t *)raw_packet))
1079 break;
1080 }
1081 coap_delete_string(name);
1082 name = NULL;
1083 coap_delete_binary(raw_packet);
1084 raw_packet = NULL;
1085 }
1086 coap_delete_string(name);
1087 coap_delete_binary(raw_packet);
1088 /* Add new entry to the end */
1089 if (!coap_op_dyn_resource_write(fp_new, session->proto,
1090 resource_name, packet))
1091 goto fail;
1092
1093 if (fflush(fp_new) == EOF)
1094 goto fail;
1095 fclose(fp_new);
1096 fclose(fp_orig);
1097 /* Either old or new is in place */
1098 (void)rename(new, (const char *)context->dyn_resource_save_file->s);
1100 return 1;
1101
1102fail:
1103 if (fp_new)
1104 fclose(fp_new);
1105 if (fp_orig)
1106 fclose(fp_orig);
1107 if (new) {
1108 (void)remove(new);
1109 }
1111 return 0;
1112}
1113
1114/*
1115 * Server has deleted a resource
1116 */
1117static int
1118coap_op_resource_deleted(coap_context_t *context,
1119 coap_str_const_t *resource_name,
1120 void *user_data) {
1121 FILE *fp_orig = NULL;
1122 FILE *fp_new = NULL;
1123 char *new = NULL;
1124 coap_proto_t e_proto;
1125 coap_string_t *name = NULL;
1126 coap_binary_t *raw_packet = NULL;
1127 (void)user_data;
1128
1129 coap_op_obs_cnt_deleted(context, resource_name);
1130
1131 fp_orig = fopen((const char *)context->dyn_resource_save_file->s, "r");
1132 if (fp_orig == NULL)
1133 return 1;
1134
1136 context->dyn_resource_save_file->length + 5);
1137 if (!new)
1138 goto fail;
1139
1140 strcpy(new, (const char *)context->dyn_resource_save_file->s);
1141 strcat(new, ".tmp");
1142 fp_new = fopen(new, "w+");
1143 if (fp_new == NULL)
1144 goto fail;
1145
1146 /* Go through and locate resource to delete and not copy it across */
1147 while (1) {
1148 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1149 break;
1150 if (!coap_string_equal(resource_name, name)) {
1151 /* Copy across non-matching entry */
1152 if (!coap_op_dyn_resource_write(fp_new, e_proto, (coap_str_const_t *)name,
1153 (coap_bin_const_t *)raw_packet))
1154 break;
1155 }
1156 coap_delete_string(name);
1157 name = NULL;
1158 coap_delete_binary(raw_packet);
1159 raw_packet = NULL;
1160 }
1161 coap_delete_string(name);
1162 coap_delete_binary(raw_packet);
1163
1164 if (fflush(fp_new) == EOF)
1165 goto fail;
1166 fclose(fp_new);
1167 fclose(fp_orig);
1168 /* Either old or new is in place */
1169 (void)rename(new, (const char *)context->dyn_resource_save_file->s);
1171 return 1;
1172
1173fail:
1174 if (fp_new)
1175 fclose(fp_new);
1176 if (fp_orig)
1177 fclose(fp_orig);
1178 if (new) {
1179 (void)remove(new);
1180 }
1182 return 0;
1183}
1184
1185COAP_API int
1187 const char *dyn_resource_save_file,
1188 const char *observe_save_file,
1189 const char *obs_cnt_save_file,
1190 uint32_t save_freq) {
1191 int ret;
1192
1193 coap_lock_lock(return 0);
1194 ret = coap_persist_startup_lkd(context,
1195 dyn_resource_save_file,
1196 observe_save_file,
1197 obs_cnt_save_file,
1198 save_freq);
1200 return ret;
1201}
1202
1203int
1204coap_persist_startup_lkd(coap_context_t *context,
1205 const char *dyn_resource_save_file,
1206 const char *observe_save_file,
1207 const char *obs_cnt_save_file,
1208 uint32_t save_freq) {
1210 if (dyn_resource_save_file) {
1211 context->dyn_resource_save_file =
1212 coap_new_bin_const((const uint8_t *)dyn_resource_save_file,
1213 strlen(dyn_resource_save_file));
1214 if (!context->dyn_resource_save_file)
1215 return 0;
1216 coap_op_dyn_resource_load_disk(context);
1217 context->dyn_resource_added_cb = coap_op_dyn_resource_added;
1218 context->resource_deleted_cb = coap_op_resource_deleted;
1219 }
1220 if (obs_cnt_save_file) {
1221 context->obs_cnt_save_file =
1222 coap_new_bin_const((const uint8_t *)obs_cnt_save_file,
1223 strlen(obs_cnt_save_file));
1224 if (!context->obs_cnt_save_file)
1225 return 0;
1226 context->observe_save_freq = save_freq ? save_freq : 1;
1227 coap_op_obs_cnt_load_disk(context);
1228 context->track_observe_value_cb = coap_op_obs_cnt_track_observe;
1229 context->resource_deleted_cb = coap_op_resource_deleted;
1230 }
1231 if (observe_save_file) {
1232 context->observe_save_file =
1233 coap_new_bin_const((const uint8_t *)observe_save_file,
1234 strlen(observe_save_file));
1235 if (!context->observe_save_file)
1236 return 0;
1237 coap_op_observe_load_disk(context);
1238 context->observe_added_cb = coap_op_observe_added;
1239 context->observe_deleted_cb = coap_op_observe_deleted;
1240 }
1241 return 1;
1242}
1243
1244void
1245coap_persist_cleanup(coap_context_t *context) {
1246 coap_delete_bin_const(context->dyn_resource_save_file);
1247 coap_delete_bin_const(context->obs_cnt_save_file);
1248 coap_delete_bin_const(context->observe_save_file);
1249 context->dyn_resource_save_file = NULL;
1250 context->obs_cnt_save_file = NULL;
1251 context->observe_save_file = NULL;
1252
1253 /* Close down any tracking */
1255 NULL, 0, NULL);
1256}
1257
1258COAP_API void
1260 if (!context)
1261 return;
1262 coap_lock_lock(return);
1263 coap_persist_stop_lkd(context);
1265}
1266
1267void
1268coap_persist_stop_lkd(coap_context_t *context) {
1269 if (context == NULL)
1270 return;
1272 context->observe_no_clear = 1;
1273 coap_persist_cleanup(context);
1274}
1275#else /* ! COAP_WITH_OBSERVE_PERSIST */
1276COAP_API int
1278 const char *dyn_resource_save_file,
1279 const char *observe_save_file,
1280 const char *obs_cnt_save_file,
1281 uint32_t save_freq) {
1282 (void)context;
1283 (void)dyn_resource_save_file;
1284 (void)observe_save_file;
1285 (void)obs_cnt_save_file;
1286 (void)save_freq;
1287 return 0;
1288}
1289
1290COAP_API void
1292 context->observe_no_clear = 1;
1293 /* Close down any tracking */
1295 NULL, 0, NULL);
1296}
1297
1298#endif /* ! COAP_WITH_OBSERVE_PERSIST */
1299
1300#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:940
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...
Definition coap_option.h:43
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_callback_ret(r, func)
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
size_t oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_size)
#define CBOR_NULL
Definition oscore_cbor.h:74
#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)
void oscore_log_hex_value(coap_log_t level, const char *name, coap_bin_const_t *value)
oscore_ctx_t * oscore_find_context(const 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 coap_delete_pdu_lkd(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
Definition coap_pdu.c:194
coap_proto_t
CoAP protocol types Note: coap_layers_coap[] needs updating if extended.
Definition coap_pdu.h:316
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:1508
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:102
#define COAP_OPTION_OBSERVE
Definition coap_pdu.h:125
@ COAP_PROTO_UDP
Definition coap_pdu.h:318
@ COAP_REQUEST_CODE_PUT
Definition coap_pdu.h:335
@ COAP_REQUEST_CODE_POST
Definition coap_pdu.h:334
@ COAP_REQUEST_CODE_GET
Definition coap_pdu.h:333
@ COAP_REQUEST_CODE_FETCH
Definition coap_pdu.h:337
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:1023
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:972
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.
uint32_t dynamic_cur
Current number of dynamic resources.
coap_resource_dynamic_create_t dyn_create_handler
Dynamc resource create handler.
uint32_t dynamic_max
Max number of dynamic resources or 0 is unlimited.
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