20#define min(a,b) ((a) < (b) ? (a) : (b))
25#if COAP_SERVER_SUPPORT && COAP_WITH_OBSERVE_PERSIST
32#if COAP_SERVER_SUPPORT
88#if COAP_CONSTRAINED_STACK
105 if (e_listen_addr == NULL || s_addr_info == NULL || raw_packet == NULL)
114 if (ep->
proto == e_proto &&
128 data = raw_packet->
s;
129 data_len = raw_packet->
length;
167 r = coap_get_resource_from_uri_path_lkd(session->
context,
170 coap_log_warn(
"coap_persist_observe_add: resource '%s' not defined\n",
174 if (!r->observable) {
175 coap_log_warn(
"coap_persist_observe_add: resource '%s' not observable\n",
188#if COAP_OSCORE_SUPPORT
205 const uint8_t *info_buf = oscore_info->
s;
206 size_t info_buf_len = oscore_info->
length;
214 int have_partial_iv = 0;
215 int have_id_context = 0;
230 if (oscore_key_id.
length > info_buf_len)
232 oscore_key_id.
s = info_buf;
233 info_buf += oscore_key_id.
length;
240 if (id_context.
length > info_buf_len)
242 id_context.
s = info_buf;
243 info_buf += id_context.
length;
255 if (aad.
length > info_buf_len)
271 if (partial_iv.
length > info_buf_len)
273 partial_iv.
s = info_buf;
274 info_buf += partial_iv.
length;
287 if (nonce.
length > info_buf_len)
299 have_id_context ? &id_context : NULL, NULL,
300 &session->recipient_ctx);
302 session->oscore_encryption = 1;
304 session->recipient_ctx,
305 have_aad ? &aad : NULL,
306 have_nonce ? &nonce : NULL,
307 have_partial_iv ? &partial_iv : NULL,
311 have_partial_iv ? &partial_iv : NULL);
322 coap_log_warn(
"coap_persist_observe_add: discard malformed PDU\n");
329#if COAP_WITH_OBSERVE_PERSIST
343 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
344 raw_packet && oscore_info);
349 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
351 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
353 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
355 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
357 if (fread(&size,
sizeof(size), 1, fp) != 1)
359 if (size < 0 || size > 0x10000)
362 if ((scratch) == NULL)
364 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
368 if (fread(&size,
sizeof(size), 1, fp) != 1)
373 else if (size < 0 || size > 0x10000)
379 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
390 memset(e_proto, 0,
sizeof(*e_proto));
391 memset(e_listen_addr, 0,
sizeof(*e_listen_addr));
392 memset(s_addr_info, 0,
sizeof(*s_addr_info));
405 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
407 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
409 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
412 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
414 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
416 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
419 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
421 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
424 ssize_t not_defined = -1;
426 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
442 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
459 strcpy(
new, (
const char *)ctx->observe_save_file->s);
461 fp_new = fopen(
new,
"w+");
467 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
468 &s_addr_info, &raw_packet, &oscore_info))
477 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
478 s_addr_info, raw_packet, oscore_info))
491 if (fflush(fp_new) == EOF)
496 (void)rename(
new, (
const char *)ctx->observe_save_file->s);
524 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
538 session->
context->observe_save_file->length + 5);
542 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
544 fp_new = fopen(
new,
"w+");
550 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
551 &s_addr_info, &raw_packet, &oscore_info))
553 if (observe_key != a_observe_key) {
554 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
555 s_addr_info, raw_packet, oscore_info))
569 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
570 *a_s_addr_info, a_raw_packet, a_oscore_info))
573 if (fflush(fp_new) == EOF)
579 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
604 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
620 session->
context->observe_save_file->length + 5);
624 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
626 fp_new = fopen(
new,
"w+");
632 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
633 &s_addr_info, &raw_packet, &oscore_info))
635 if (observe_key != d_observe_key) {
636 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
651 if (fflush(fp_new) == EOF)
656 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
682 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
688 while (fgets(buf,
sizeof(buf), fp) != NULL) {
689 char *cp = strchr(buf,
' ');
691 uint32_t observe_num;
699 observe_num = atoi(cp);
707 resource_key.
s = (uint8_t *)buf;
708 resource_key.
length = strlen(buf);
709 r = coap_get_resource_from_uri_path_lkd(context, &resource_key);
711 coap_log_debug(
"persist: Initial observe number being updated\n");
726 uint32_t n_observe_num,
728 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
739 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
741 fp_new = fopen(
new,
"w+");
746 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) != NULL) {
747 char *cp = strchr(buf,
' ');
748 uint32_t observe_num;
756 observe_num = atoi(cp);
757 resource_key.
s = (uint8_t *)buf;
758 resource_key.
length = strlen(buf);
760 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
764 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
766 if (fflush(fp_new) == EOF)
772 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
794 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
805 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
807 fp_new = fopen(
new,
"w+");
812 while (fgets(buf,
sizeof(buf), fp_orig) != NULL) {
813 char *cp = strchr(buf,
' ');
814 uint32_t observe_num;
822 observe_num = atoi(cp);
823 resource_key.
s = (uint8_t *)buf;
824 resource_key.
length = strlen(buf);
826 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
830 if (fflush(fp_new) == EOF)
835 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
856coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
864 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
866 if (fread(&size,
sizeof(size), 1, fp) != 1)
868 if (size < 0 || size > 0x10000)
873 if (fread((*name)->s, size, 1, fp) != 1)
875 if (fread(&size,
sizeof(size), 1, fp) != 1)
877 if (size < 0 || size > 0x10000)
882 if (fread((*raw_packet)->s, size, 1, fp) != 1)
894coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
897 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
899 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
901 if (fwrite(name->
s, name->
length, 1, fp) != 1)
903 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
905 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
920 FILE *fp_orig = NULL;
933 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
945 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
960 session->
proto = e_proto;
962 raw_packet->
length, request)) {
966 if (!r->handler[request->
code-1])
981 r->handler[request->
code-1](r,
1017 FILE *fp_new = NULL;
1026 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
1027 if (fp_orig == NULL)
1031 context->dyn_resource_save_file->length + 5);
1035 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1036 strcat(
new,
".tmp");
1037 fp_new = fopen(
new,
"w+");
1043 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1059 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
1060 resource_name, packet))
1063 if (fflush(fp_new) == EOF)
1068 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1091 FILE *fp_orig = NULL;
1092 FILE *fp_new = NULL;
1099 coap_op_obs_cnt_deleted(context, resource_name);
1101 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1102 if (fp_orig == NULL)
1106 context->dyn_resource_save_file->length + 5);
1110 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1111 strcat(
new,
".tmp");
1112 fp_new = fopen(
new,
"w+");
1118 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1134 if (fflush(fp_new) == EOF)
1139 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1157 const char *dyn_resource_save_file,
1158 const char *observe_save_file,
1159 const char *obs_cnt_save_file,
1160 uint32_t save_freq) {
1165 dyn_resource_save_file,
1175 const char *dyn_resource_save_file,
1176 const char *observe_save_file,
1177 const char *obs_cnt_save_file,
1178 uint32_t save_freq) {
1180 if (dyn_resource_save_file) {
1181 context->dyn_resource_save_file =
1183 strlen(dyn_resource_save_file));
1184 if (!context->dyn_resource_save_file)
1186 coap_op_dyn_resource_load_disk(context);
1190 if (obs_cnt_save_file) {
1191 context->obs_cnt_save_file =
1193 strlen(obs_cnt_save_file));
1194 if (!context->obs_cnt_save_file)
1197 coap_op_obs_cnt_load_disk(context);
1201 if (observe_save_file) {
1202 context->observe_save_file =
1204 strlen(observe_save_file));
1205 if (!context->observe_save_file)
1207 coap_op_observe_load_disk(context);
1219 context->dyn_resource_save_file = NULL;
1220 context->obs_cnt_save_file = NULL;
1221 context->observe_save_file = NULL;
1239 if (context == NULL)
1248 const char *dyn_resource_save_file,
1249 const char *observe_save_file,
1250 const char *obs_cnt_save_file,
1251 uint32_t save_freq) {
1253 (void)dyn_resource_save_file;
1254 (void)observe_save_file;
1255 (void)obs_cnt_save_file;
struct coap_resource_t coap_resource_t
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 *)
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_release(c, func, failed)
Dummy for no thread-safe code.
#define coap_lock_unlock(c)
Dummy for no thread-safe code.
#define coap_lock_lock(c, failed)
Dummy for no thread-safe code.
#define coap_lock_check_locked(c)
Dummy for no thread-safe code.
#define coap_log_debug(...)
#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_len)
#define CBOR_SIMPLE_VALUE
uint8_t oscore_cbor_get_next_element(const uint8_t **buffer, size_t *buf_len)
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.
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
coap_session_t * coap_endpoint_get_session(coap_endpoint_t *endpoint, const coap_packet_t *packet, coap_tick_t now)
Lookup the server session for the packet received on an endpoint, or create a new one.
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.
void coap_persist_stop_lkd(coap_context_t *context)
Stop tracking persist information, leaving the current persist information in the files defined in co...
void coap_persist_cleanup(coap_context_t *context)
Close down persist tracking, releasing any memory used.
coap_subscription_t * coap_persist_observe_add_lkd(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...
void coap_subscription_init(coap_subscription_t *)
coap_subscription_t * coap_add_observer(coap_resource_t *resource, coap_session_t *session, const coap_bin_const_t *token, const coap_pdu_t *pdu)
Adds the specified peer as observer for resource.
int coap_persist_startup_lkd(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.
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_observe_added_t observe_added
Called when there is a new observe subscription request.
coap_dyn_resource_added_t dyn_resource_added
Callback to save dynamic resource when created.
void * observe_user_data
App provided data for use in observe_added or observe_deleted.
coap_track_observe_value_t track_observe_value
Callback to save observe value when updated.
coap_endpoint_t * endpoint
the endpoints used for listening
uint32_t observe_save_freq
How frequently to update observe value.
uint8_t observe_no_clear
Observe 4.04 not to be sent on deleting resource.
coap_observe_deleted_t observe_deleted
Called when there is a observe subscription de-register request.
coap_resource_t * unknown_resource
can be used for handling unknown resources
coap_resource_deleted_t resource_deleted
Invoked when resource is deleted.
Abstraction of virtual endpoint that can be attached to coap_context_t.
struct coap_endpoint_t * next
coap_address_t bind_addr
local interface address
coap_proto_t proto
protocol used on this interface
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.
Number of notifications that may be sent non-confirmable before a confirmable message is sent to dete...