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