20#define min(a,b) ((a) < (b) ? (a) : (b))
25#if COAP_SERVER_SUPPORT && COAP_WITH_OBSERVE_PERSIST
32#if COAP_SERVER_SUPPORT
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;
67 subs = coap_persist_observe_add_lkd(context,
88#if COAP_CONSTRAINED_STACK
105 if (e_listen_addr ==
NULL || s_addr_info ==
NULL || raw_packet ==
NULL)
112 ep = context->endpoint;
114 if (ep->proto == e_proto &&
115 memcmp(e_listen_addr, &ep->bind_addr,
sizeof(ep->bind_addr)) == 0)
121#ifndef INET6_ADDRSTRLEN
122#define INET6_ADDRSTRLEN 40
127 coap_log_warn(
"coap_persist_observe_add: Endpoint %s not defined\n",
140 data = raw_packet->
s;
141 data_len = raw_packet->
length;
148 session = coap_endpoint_get_session(ep, packet, now);
179 r = coap_get_resource_from_uri_path_lkd(session->
context,
182 coap_log_warn(
"coap_persist_observe_add: resource '%s' not defined\n",
186 if (!r->observable) {
187 coap_log_warn(
"coap_persist_observe_add: resource '%s' not observable\n",
196 s = coap_add_observer(r, session, &pdu->
actual_token, pdu);
200#if COAP_OSCORE_SUPPORT
217 const uint8_t *info_buf = oscore_info->
s;
218 size_t info_buf_len = oscore_info->
length;
226 int have_partial_iv = 0;
227 int have_id_context = 0;
242 if (oscore_key_id.
length > info_buf_len)
244 oscore_key_id.
s = info_buf;
245 info_buf += oscore_key_id.
length;
252 if (id_context.
length > info_buf_len)
254 id_context.
s = info_buf;
255 info_buf += id_context.
length;
267 if (aad.
length > info_buf_len)
283 if (partial_iv.
length > info_buf_len)
285 partial_iv.
s = info_buf;
286 info_buf += partial_iv.
length;
299 if (nonce.
length > info_buf_len)
311 have_id_context ? &id_context :
NULL,
NULL,
312 &session->recipient_ctx);
314 session->oscore_encryption = 1;
316 session->recipient_ctx,
317 have_aad ? &aad :
NULL,
318 have_nonce ? &nonce :
NULL,
319 have_partial_iv ? &partial_iv :
NULL,
323 have_partial_iv ? &partial_iv :
NULL);
334 coap_log_warn(
"coap_persist_observe_add: discard malformed PDU\n");
341#if COAP_WITH_OBSERVE_PERSIST
355 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
356 raw_packet && oscore_info);
361 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
363 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
365 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
367 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
369 if (fread(&size,
sizeof(size), 1, fp) != 1)
371 if (size < 0 || size > 0x10000)
374 if ((scratch) ==
NULL)
376 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
380 if (fread(&size,
sizeof(size), 1, fp) != 1)
385 else if (size < 0 || size > 0x10000)
391 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
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));
417 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
419 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
421 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
424 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
426 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
428 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
431 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
433 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
436 ssize_t not_defined = -1;
438 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
454 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
471 strcpy(
new, (
const char *)ctx->observe_save_file->s);
473 fp_new = fopen(
new,
"w+");
479 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
480 &s_addr_info, &raw_packet, &oscore_info))
483 observe_key = coap_persist_observe_add_lkd(ctx, e_proto,
489 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
490 s_addr_info, raw_packet, oscore_info))
503 if (fflush(fp_new) == EOF)
508 if (rename(
new, (
const char *)ctx->observe_save_file->s) == -1) {
510 new, (
const char *)ctx->observe_save_file->s,
540 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
554 session->
context->observe_save_file->length + 5);
558 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
560 fp_new = fopen(
new,
"w+");
566 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
567 &s_addr_info, &raw_packet, &oscore_info))
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))
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))
589 if (fflush(fp_new) == EOF)
595 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
620 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
636 session->
context->observe_save_file->length + 5);
640 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
642 fp_new = fopen(
new,
"w+");
648 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
649 &s_addr_info, &raw_packet, &oscore_info))
651 if (observe_key != d_observe_key) {
652 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
667 if (fflush(fp_new) == EOF)
672 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
698 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
704 while (fgets(buf,
sizeof(buf), fp) !=
NULL) {
705 char *cp = strchr(buf,
' ');
707 uint32_t observe_num;
715 observe_num = atoi(cp);
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);
727 coap_log_debug(
"persist: Initial observe number being updated '%s' %u\n",
743 uint32_t n_observe_num,
745 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
756 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
758 fp_new = fopen(
new,
"w+");
763 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) !=
NULL) {
764 char *cp = strchr(buf,
' ');
765 uint32_t observe_num;
773 observe_num = atoi(cp);
774 resource_key.
s = (uint8_t *)buf;
775 resource_key.
length = strlen(buf);
777 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
781 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
783 if (fflush(fp_new) == EOF)
789 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
811 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
822 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
824 fp_new = fopen(
new,
"w+");
829 while (fgets(buf,
sizeof(buf), fp_orig) !=
NULL) {
830 char *cp = strchr(buf,
' ');
831 uint32_t observe_num;
839 observe_num = atoi(cp);
840 resource_key.
s = (uint8_t *)buf;
841 resource_key.
length = strlen(buf);
843 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
847 if (fflush(fp_new) == EOF)
852 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
873coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
881 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
883 if (fread(&size,
sizeof(size), 1, fp) != 1)
885 if (size < 0 || size > 0x10000)
890 if (fread((*name)->s, size, 1, fp) != 1)
892 if (fread(&size,
sizeof(size), 1, fp) != 1)
894 if (size < 0 || size > 0x10000)
899 if (fread((*raw_packet)->s, size, 1, fp) != 1)
911coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
914 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
916 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
918 if (fwrite(name->
s, name->
length, 1, fp) != 1)
920 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
922 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
937 FILE *fp_orig =
NULL;
950 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
962 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
968 coap_log_debug(
"persist: dynamic resource '%s' being re-created\n", name->
s);
977 session->
proto = e_proto;
979 raw_packet->
length, request)) {
982 r = ctx->unknown_resource;
987 ctx->unknown_pdu = request;
988 ctx->unknown_session = session;
990 ctx->unknown_pdu =
NULL;
991 ctx->unknown_session =
NULL;
994 if (!r || !r->handler[request->
code-1])
1010 r->handler[request->
code-1](r,
1047 FILE *fp_new =
NULL;
1056 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
1057 if (fp_orig ==
NULL)
1061 context->dyn_resource_save_file->length + 5);
1065 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1066 strcat(
new,
".tmp");
1067 fp_new = fopen(
new,
"w+");
1073 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1089 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
1090 resource_name, packet))
1093 if (fflush(fp_new) == EOF)
1098 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1121 FILE *fp_orig =
NULL;
1122 FILE *fp_new =
NULL;
1129 coap_op_obs_cnt_deleted(context, resource_name);
1131 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1132 if (fp_orig ==
NULL)
1136 context->dyn_resource_save_file->length + 5);
1140 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1141 strcat(
new,
".tmp");
1142 fp_new = fopen(
new,
"w+");
1148 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1164 if (fflush(fp_new) == EOF)
1169 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
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) {
1194 ret = coap_persist_startup_lkd(context,
1195 dyn_resource_save_file,
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 =
1213 strlen(dyn_resource_save_file));
1214 if (!context->dyn_resource_save_file)
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;
1220 if (obs_cnt_save_file) {
1221 context->obs_cnt_save_file =
1223 strlen(obs_cnt_save_file));
1224 if (!context->obs_cnt_save_file)
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;
1231 if (observe_save_file) {
1232 context->observe_save_file =
1234 strlen(observe_save_file));
1235 if (!context->observe_save_file)
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;
1249 context->dyn_resource_save_file =
NULL;
1250 context->obs_cnt_save_file =
NULL;
1251 context->observe_save_file =
NULL;
1263 coap_persist_stop_lkd(context);
1269 if (context ==
NULL)
1272 context->observe_no_clear = 1;
1273 coap_persist_cleanup(context);
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) {
1283 (void)dyn_resource_save_file;
1284 (void)observe_save_file;
1285 (void)obs_cnt_save_file;
1292 context->observe_no_clear = 1;
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)
Library specific build wrapper for coap_internal.h.
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().
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
#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.
unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
#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(...)
coap_log_t coap_get_log_level(void)
Get the current logging level.
size_t coap_print_addr(const coap_address_t *addr, unsigned char *buf, size_t len)
Print the address into the defined buffer.
#define coap_log_warn(...)
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.
size_t oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_size)
#define CBOR_SIMPLE_VALUE
uint8_t oscore_cbor_get_next_element(const uint8_t **buffer, size_t *buf_size)
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.
coap_proto_t
CoAP protocol types Note: coap_layers_coap[] needs updating if extended.
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.
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.
#define COAP_OPTION_OBSERVE
@ COAP_REQUEST_CODE_FETCH
void coap_delete_bin_const(coap_bin_const_t *s)
Deletes the given const binary data and releases any memory allocated.
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
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...
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
#define coap_binary_equal(binary1, binary2)
Compares the two binary data for equality.
#define coap_string_equal(string1, string2)
Compares the two strings for equality.
coap_string_t * coap_new_string(size_t size)
Returns a new string object with at least size+1 bytes storage allocated.
void coap_delete_string(coap_string_t *s)
Deletes the given string and releases any memory allocated.
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.
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.
Multi-purpose address abstraction.
CoAP binary data definition with const data.
size_t length
length of binary data
const uint8_t * s
read-only binary data
CoAP binary data definition.
size_t length
length of binary data
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
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.
const uint8_t * s
read-only string data
size_t length
length of string
CoAP string data definition.