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;
246 info_buf_len -= oscore_key_id.
length;
253 if (id_context.
length > info_buf_len)
255 id_context.
s = info_buf;
256 info_buf += id_context.
length;
257 info_buf_len -= id_context.
length;
269 if (aad.
length > info_buf_len)
273 info_buf_len -= aad.
length;
286 if (partial_iv.
length > info_buf_len)
288 partial_iv.
s = info_buf;
289 info_buf += partial_iv.
length;
290 info_buf_len -= partial_iv.
length;
303 if (nonce.
length > info_buf_len)
307 info_buf_len -= nonce.
length;
316 have_id_context ? &id_context :
NULL,
NULL,
317 &session->recipient_ctx);
319 session->oscore_encryption = 1;
321 session->recipient_ctx,
322 have_aad ? &aad :
NULL,
323 have_nonce ? &nonce :
NULL,
324 have_partial_iv ? &partial_iv :
NULL,
328 have_partial_iv ? &partial_iv :
NULL);
339 coap_log_warn(
"coap_persist_observe_add: discard malformed PDU\n");
346#if COAP_WITH_OBSERVE_PERSIST
360 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
361 raw_packet && oscore_info);
366 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
368 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
370 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
372 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
374 if (fread(&size,
sizeof(size), 1, fp) != 1)
376 if (size < 0 || size > 0x10000)
379 if ((scratch) ==
NULL)
381 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
385 if (fread(&size,
sizeof(size), 1, fp) != 1)
390 else if (size < 0 || size > 0x10000)
396 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
407 memset(e_proto, 0,
sizeof(*e_proto));
408 memset(e_listen_addr, 0,
sizeof(*e_listen_addr));
409 memset(s_addr_info, 0,
sizeof(*s_addr_info));
422 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
424 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
426 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
429 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
431 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
433 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
436 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
438 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
441 ssize_t not_defined = -1;
443 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
459 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
476 strcpy(
new, (
const char *)ctx->observe_save_file->s);
478 fp_new = fopen(
new,
"w+");
484 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
485 &s_addr_info, &raw_packet, &oscore_info))
488 observe_key = coap_persist_observe_add_lkd(ctx, e_proto,
494 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
495 s_addr_info, raw_packet, oscore_info))
508 if (fflush(fp_new) == EOF)
513 if (rename(
new, (
const char *)ctx->observe_save_file->s) == -1) {
515 new, (
const char *)ctx->observe_save_file->s,
545 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
559 session->
context->observe_save_file->length + 5);
563 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
565 fp_new = fopen(
new,
"w+");
571 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
572 &s_addr_info, &raw_packet, &oscore_info))
574 if (observe_key != a_observe_key) {
575 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
576 s_addr_info, raw_packet, oscore_info))
590 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
591 *a_s_addr_info, a_raw_packet, a_oscore_info))
594 if (fflush(fp_new) == EOF)
600 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
625 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
641 session->
context->observe_save_file->length + 5);
645 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
647 fp_new = fopen(
new,
"w+");
653 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
654 &s_addr_info, &raw_packet, &oscore_info))
656 if (observe_key != d_observe_key) {
657 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
672 if (fflush(fp_new) == EOF)
677 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
703 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
709 while (fgets(buf,
sizeof(buf), fp) !=
NULL) {
710 char *cp = strchr(buf,
' ');
712 uint32_t observe_num;
720 observe_num = atoi(cp);
725 observe_num = ((observe_num + context->observe_save_freq) /
726 context->observe_save_freq) *
727 context->observe_save_freq - 1;
728 resource_key.
s = (uint8_t *)buf;
729 resource_key.
length = strlen(buf);
730 r = coap_get_resource_from_uri_path_lkd(context, &resource_key);
732 coap_log_debug(
"persist: Initial observe number being updated '%s' %u\n",
748 uint32_t n_observe_num,
750 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
761 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
763 fp_new = fopen(
new,
"w+");
768 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) !=
NULL) {
769 char *cp = strchr(buf,
' ');
770 uint32_t observe_num;
778 observe_num = atoi(cp);
779 resource_key.
s = (uint8_t *)buf;
780 resource_key.
length = strlen(buf);
782 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
786 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
788 if (fflush(fp_new) == EOF)
794 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
816 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
827 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
829 fp_new = fopen(
new,
"w+");
834 while (fgets(buf,
sizeof(buf), fp_orig) !=
NULL) {
835 char *cp = strchr(buf,
' ');
836 uint32_t observe_num;
844 observe_num = atoi(cp);
845 resource_key.
s = (uint8_t *)buf;
846 resource_key.
length = strlen(buf);
848 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
852 if (fflush(fp_new) == EOF)
857 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
878coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
886 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
888 if (fread(&size,
sizeof(size), 1, fp) != 1)
890 if (size < 0 || size > 0x10000)
895 if (fread((*name)->s, size, 1, fp) != 1)
897 if (fread(&size,
sizeof(size), 1, fp) != 1)
899 if (size < 0 || size > 0x10000)
904 if (fread((*raw_packet)->s, size, 1, fp) != 1)
916coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
919 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
921 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
923 if (fwrite(name->
s, name->
length, 1, fp) != 1)
925 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
927 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
942 FILE *fp_orig =
NULL;
955 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
967 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
973 coap_log_debug(
"persist: dynamic resource '%s' being re-created\n", name->
s);
982 session->
proto = e_proto;
984 raw_packet->
length, request)) {
987 if (request->
code == 0 || request->
code > 7) {
991 r = coap_add_dynamic_resource(session, request);
993 r = ctx->unknown_resource;
995 if (!r || !r->handler[request->
code-1])
1011 r->handler[request->
code-1](r,
1048 FILE *fp_new =
NULL;
1057 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
1058 if (fp_orig ==
NULL)
1062 context->dyn_resource_save_file->length + 5);
1066 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1067 strcat(
new,
".tmp");
1068 fp_new = fopen(
new,
"w+");
1074 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1090 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
1091 resource_name, packet))
1094 if (fflush(fp_new) == EOF)
1099 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1122 FILE *fp_orig =
NULL;
1123 FILE *fp_new =
NULL;
1130 coap_op_obs_cnt_deleted(context, resource_name);
1132 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1133 if (fp_orig ==
NULL)
1137 context->dyn_resource_save_file->length + 5);
1141 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1142 strcat(
new,
".tmp");
1143 fp_new = fopen(
new,
"w+");
1149 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1165 if (fflush(fp_new) == EOF)
1170 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1188 const char *dyn_resource_save_file,
1189 const char *observe_save_file,
1190 const char *obs_cnt_save_file,
1191 uint32_t save_freq) {
1195 ret = coap_persist_startup_lkd(context,
1196 dyn_resource_save_file,
1206 const char *dyn_resource_save_file,
1207 const char *observe_save_file,
1208 const char *obs_cnt_save_file,
1209 uint32_t save_freq) {
1211 if (dyn_resource_save_file) {
1212 context->dyn_resource_save_file =
1214 strlen(dyn_resource_save_file));
1215 if (!context->dyn_resource_save_file)
1217 coap_op_dyn_resource_load_disk(context);
1218 context->dyn_resource_added_cb = coap_op_dyn_resource_added;
1219 context->resource_deleted_cb = coap_op_resource_deleted;
1221 if (obs_cnt_save_file) {
1222 context->obs_cnt_save_file =
1224 strlen(obs_cnt_save_file));
1225 if (!context->obs_cnt_save_file)
1227 context->observe_save_freq = save_freq ? save_freq : 1;
1228 coap_op_obs_cnt_load_disk(context);
1229 context->track_observe_value_cb = coap_op_obs_cnt_track_observe;
1230 context->resource_deleted_cb = coap_op_resource_deleted;
1232 if (observe_save_file) {
1233 context->observe_save_file =
1235 strlen(observe_save_file));
1236 if (!context->observe_save_file)
1238 coap_op_observe_load_disk(context);
1239 context->observe_added_cb = coap_op_observe_added;
1240 context->observe_deleted_cb = coap_op_observe_deleted;
1250 context->dyn_resource_save_file =
NULL;
1251 context->obs_cnt_save_file =
NULL;
1252 context->observe_save_file =
NULL;
1264 coap_persist_stop_lkd(context);
1270 if (context ==
NULL)
1273 context->observe_no_clear = 1;
1274 coap_persist_cleanup(context);
1279 const char *dyn_resource_save_file,
1280 const char *observe_save_file,
1281 const char *obs_cnt_save_file,
1282 uint32_t save_freq) {
1284 (void)dyn_resource_save_file;
1285 (void)observe_save_file;
1286 (void)obs_cnt_save_file;
1293 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_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.
uint64_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)
oscore_ctx_t * oscore_find_context(coap_session_t *session, const coap_bin_const_t rcpkey_id, const coap_bin_const_t *ctxkey_id, uint8_t *oscore_r2, oscore_recipient_ctx_t **recipient_ctx)
oscore_find_context - Locate recipient context (and hence OSCORE context)
void oscore_log_hex_value(coap_log_t level, const char *name, coap_bin_const_t *value)
void coap_delete_pdu_lkd(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
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.
@ 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.
coap_resource_dynamic_create_t dyn_create_handler
Dynamc resource create handler.
Iterator to run through PDU options.
size_t length
length of payload
coap_addr_tuple_t addr_info
local and remote addresses
unsigned char * payload
payload
int ifindex
the interface index
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.