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;
170 coap_log_warn(
"coap_persist_observe_add: resource '%s' not defined\n",
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 oscore_key_id.
s = info_buf;
231 info_buf += oscore_key_id.
length;
238 id_context.
s = info_buf;
239 info_buf += id_context.
length;
265 partial_iv.
s = info_buf;
266 info_buf += partial_iv.
length;
289 have_id_context ? &id_context : NULL, NULL,
290 &session->recipient_ctx);
292 session->oscore_encryption = 1;
294 session->recipient_ctx,
295 have_aad ? &aad : NULL,
296 have_nonce ? &nonce : NULL,
297 have_partial_iv ? &partial_iv : NULL,
301 have_partial_iv ? &partial_iv : NULL);
312 coap_log_warn(
"coap_persist_observe_add: discard malformed PDU\n");
319#if COAP_WITH_OBSERVE_PERSIST
333 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
334 raw_packet && oscore_info);
339 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
341 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
343 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
345 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
347 if (fread(&size,
sizeof(size), 1, fp) != 1)
349 if (size < 0 || size > 0x10000)
352 if ((scratch) == NULL)
354 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
358 if (fread(&size,
sizeof(size), 1, fp) != 1)
363 else if (size < 0 || size > 0x10000)
369 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
380 memset(e_proto, 0,
sizeof(*e_proto));
381 memset(e_listen_addr, 0,
sizeof(*e_listen_addr));
382 memset(s_addr_info, 0,
sizeof(*s_addr_info));
395 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
397 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
399 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
402 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
404 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
406 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
409 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
411 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
414 ssize_t not_defined = -1;
416 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
432 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
449 strcpy(
new, (
const char *)ctx->observe_save_file->s);
451 fp_new = fopen(
new,
"w+");
457 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
458 &s_addr_info, &raw_packet, &oscore_info))
467 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
468 s_addr_info, raw_packet, oscore_info))
481 if (fflush(fp_new) == EOF)
486 (void)rename(
new, (
const char *)ctx->observe_save_file->s);
514 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
528 session->
context->observe_save_file->length + 5);
532 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
534 fp_new = fopen(
new,
"w+");
540 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
541 &s_addr_info, &raw_packet, &oscore_info))
543 if (observe_key != a_observe_key) {
544 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
545 s_addr_info, raw_packet, oscore_info))
559 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
560 *a_s_addr_info, a_raw_packet, a_oscore_info))
563 if (fflush(fp_new) == EOF)
569 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
594 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
610 session->
context->observe_save_file->length + 5);
614 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
616 fp_new = fopen(
new,
"w+");
622 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
623 &s_addr_info, &raw_packet, &oscore_info))
625 if (observe_key != d_observe_key) {
626 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
641 if (fflush(fp_new) == EOF)
646 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
672 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
678 while (fgets(buf,
sizeof(buf), fp) != NULL) {
679 char *cp = strchr(buf,
' ');
681 uint32_t observe_num;
689 observe_num = atoi(cp);
697 resource_key.
s = (uint8_t *)buf;
698 resource_key.
length = strlen(buf);
701 coap_log_debug(
"persist: Initial observe number being updated\n");
716 uint32_t n_observe_num,
718 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
729 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
731 fp_new = fopen(
new,
"w+");
736 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) != NULL) {
737 char *cp = strchr(buf,
' ');
738 uint32_t observe_num;
746 observe_num = atoi(cp);
747 resource_key.
s = (uint8_t *)buf;
748 resource_key.
length = strlen(buf);
750 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
754 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
756 if (fflush(fp_new) == EOF)
762 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
784 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
795 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
797 fp_new = fopen(
new,
"w+");
802 while (fgets(buf,
sizeof(buf), fp_orig) != NULL) {
803 char *cp = strchr(buf,
' ');
804 uint32_t observe_num;
812 observe_num = atoi(cp);
813 resource_key.
s = (uint8_t *)buf;
814 resource_key.
length = strlen(buf);
816 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
820 if (fflush(fp_new) == EOF)
825 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
846coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
854 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
856 if (fread(&size,
sizeof(size), 1, fp) != 1)
858 if (size < 0 || size > 0x10000)
863 if (fread((*name)->s, size, 1, fp) != 1)
865 if (fread(&size,
sizeof(size), 1, fp) != 1)
867 if (size < 0 || size > 0x10000)
872 if (fread((*raw_packet)->s, size, 1, fp) != 1)
884coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
887 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
889 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
891 if (fwrite(name->
s, name->
length, 1, fp) != 1)
893 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
895 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
910 FILE *fp_orig = NULL;
923 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
935 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
950 session->
proto = e_proto;
952 raw_packet->
length, request)) {
1007 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
1008 if (fp_orig == NULL)
1012 context->dyn_resource_save_file->length + 5);
1016 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1017 strcat(
new,
".tmp");
1018 fp_new = fopen(
new,
"w+");
1024 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1040 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
1041 resource_name, packet))
1044 if (fflush(fp_new) == EOF)
1049 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1072 FILE *fp_orig = NULL;
1073 FILE *fp_new = NULL;
1080 coap_op_obs_cnt_deleted(context, resource_name);
1082 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1083 if (fp_orig == NULL)
1087 context->dyn_resource_save_file->length + 5);
1091 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1092 strcat(
new,
".tmp");
1093 fp_new = fopen(
new,
"w+");
1099 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1115 if (fflush(fp_new) == EOF)
1120 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1138 const char *dyn_resource_save_file,
1139 const char *observe_save_file,
1140 const char *obs_cnt_save_file,
1141 uint32_t save_freq) {
1146 dyn_resource_save_file,
1156 const char *dyn_resource_save_file,
1157 const char *observe_save_file,
1158 const char *obs_cnt_save_file,
1159 uint32_t save_freq) {
1161 if (dyn_resource_save_file) {
1162 context->dyn_resource_save_file =
1164 strlen(dyn_resource_save_file));
1165 if (!context->dyn_resource_save_file)
1167 coap_op_dyn_resource_load_disk(context);
1171 if (obs_cnt_save_file) {
1172 context->obs_cnt_save_file =
1174 strlen(obs_cnt_save_file));
1175 if (!context->obs_cnt_save_file)
1178 coap_op_obs_cnt_load_disk(context);
1182 if (observe_save_file) {
1183 context->observe_save_file =
1185 strlen(observe_save_file));
1186 if (!context->observe_save_file)
1188 coap_op_observe_load_disk(context);
1200 context->dyn_resource_save_file = NULL;
1201 context->obs_cnt_save_file = NULL;
1202 context->observe_save_file = NULL;
1220 if (context == NULL)
1229 const char *dyn_resource_save_file,
1230 const char *observe_save_file,
1231 const char *obs_cnt_save_file,
1232 uint32_t save_freq) {
1234 (void)dyn_resource_save_file;
1235 (void)observe_save_file;
1236 (void)obs_cnt_save_file;
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.
coap_resource_t * coap_get_resource_from_uri_path_lkd(coap_context_t *context, coap_str_const_t *uri_path)
Returns the resource identified by the unique string uri_path.
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_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(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
coap_proto_t
CoAP protocol types.
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 resource that can be attached to coap_context_t.
coap_method_handler_t handler[7]
Used to store handlers for the seven coap methods GET, POST, PUT, DELETE, FETCH, PATCH and IPATCH.
unsigned int observable
can be observed
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...