20#define min(a,b) ((a) < (b) ? (a) : (b))
23#if COAP_SERVER_SUPPORT
79#if COAP_CONSTRAINED_STACK
96 if (e_listen_addr == NULL || s_addr_info == NULL || raw_packet == NULL)
105 if (ep->
proto == e_proto &&
113#if COAP_CONSTRAINED_STACK
123 data = raw_packet->
s;
124 data_len = raw_packet->
length;
165 coap_log_warn(
"coap_persist_observe_add: resource '%s' not defined\n",
170 coap_log_warn(
"coap_persist_observe_add: resource '%s' not observable\n",
183#if COAP_OSCORE_SUPPORT
200 const uint8_t *info_buf = oscore_info->
s;
201 size_t info_buf_len = oscore_info->
length;
209 int have_partial_iv = 0;
210 int have_id_context = 0;
225 oscore_key_id.
s = info_buf;
226 info_buf += oscore_key_id.
length;
233 id_context.
s = info_buf;
234 info_buf += id_context.
length;
260 partial_iv.
s = info_buf;
261 info_buf += partial_iv.
length;
284 have_id_context ? &id_context : NULL, NULL,
285 &session->recipient_ctx);
287 session->oscore_encryption = 1;
289 session->recipient_ctx,
290 have_aad ? &aad : NULL,
291 have_nonce ? &nonce : NULL,
292 have_partial_iv ? &partial_iv : NULL,
296 have_partial_iv ? &partial_iv : NULL);
304#if COAP_CONSTRAINED_STACK
310 coap_log_warn(
"coap_persist_observe_add: discard malformed PDU\n");
312#if COAP_CONSTRAINED_STACK
320#if COAP_WITH_OBSERVE_PERSIST
334 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
335 raw_packet && oscore_info);
340 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
342 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
344 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
346 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
348 if (fread(&size,
sizeof(size), 1, fp) != 1)
350 if (size < 0 || size > 0x10000)
353 if ((scratch) == NULL)
355 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
359 if (fread(&size,
sizeof(size), 1, fp) != 1)
364 else if (size < 0 || size > 0x10000)
370 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
381 memset(e_proto, 0,
sizeof(*e_proto));
382 memset(e_listen_addr, 0,
sizeof(*e_listen_addr));
383 memset(s_addr_info, 0,
sizeof(*s_addr_info));
396 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
398 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
400 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
403 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
405 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
407 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
410 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
412 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
415 ssize_t not_defined = -1;
417 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
433 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
450 strcpy(
new, (
const char *)ctx->observe_save_file->s);
452 fp_new = fopen(
new,
"w+");
458 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
459 &s_addr_info, &raw_packet, &oscore_info))
468 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
469 s_addr_info, raw_packet, oscore_info))
482 if (fflush(fp_new) == EOF)
487 (void)rename(
new, (
const char *)ctx->observe_save_file->s);
515 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
529 session->
context->observe_save_file->length + 5);
533 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
535 fp_new = fopen(
new,
"w+");
541 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
542 &s_addr_info, &raw_packet, &oscore_info))
544 if (observe_key != a_observe_key) {
545 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
546 s_addr_info, raw_packet, oscore_info))
560 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
561 *a_s_addr_info, a_raw_packet, a_oscore_info))
564 if (fflush(fp_new) == EOF)
570 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
595 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
611 session->
context->observe_save_file->length + 5);
615 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
617 fp_new = fopen(
new,
"w+");
623 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
624 &s_addr_info, &raw_packet, &oscore_info))
626 if (observe_key != d_observe_key) {
627 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
642 if (fflush(fp_new) == EOF)
647 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
673 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
679 while (fgets(buf,
sizeof(buf), fp) != NULL) {
680 char *cp = strchr(buf,
' ');
682 uint32_t observe_num;
690 observe_num = atoi(cp);
698 resource_key.
s = (uint8_t *)buf;
699 resource_key.
length = strlen(buf);
702 coap_log_debug(
"persist: Initial observe number being updated\n");
717 uint32_t n_observe_num,
719 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
730 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
732 fp_new = fopen(
new,
"w+");
737 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) != NULL) {
738 char *cp = strchr(buf,
' ');
739 uint32_t observe_num;
747 observe_num = atoi(cp);
748 resource_key.
s = (uint8_t *)buf;
749 resource_key.
length = strlen(buf);
751 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
755 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
757 if (fflush(fp_new) == EOF)
763 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
785 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
796 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
798 fp_new = fopen(
new,
"w+");
803 while (fgets(buf,
sizeof(buf), fp_orig) != NULL) {
804 char *cp = strchr(buf,
' ');
805 uint32_t observe_num;
813 observe_num = atoi(cp);
814 resource_key.
s = (uint8_t *)buf;
815 resource_key.
length = strlen(buf);
817 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
821 if (fflush(fp_new) == EOF)
826 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
847coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
855 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
857 if (fread(&size,
sizeof(size), 1, fp) != 1)
859 if (size < 0 || size > 0x10000)
864 if (fread((*name)->s, size, 1, fp) != 1)
866 if (fread(&size,
sizeof(size), 1, fp) != 1)
868 if (size < 0 || size > 0x10000)
873 if (fread((*raw_packet)->s, size, 1, fp) != 1)
885coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
888 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
890 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
892 if (fwrite(name->
s, name->
length, 1, fp) != 1)
894 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
896 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
911 FILE *fp_orig = NULL;
924 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
936 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
951 session->
proto = e_proto;
953 raw_packet->
length, request)) {
1008 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
1009 if (fp_orig == NULL)
1013 context->dyn_resource_save_file->length + 5);
1017 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1018 strcat(
new,
".tmp");
1019 fp_new = fopen(
new,
"w+");
1025 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1041 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
1042 resource_name, packet))
1045 if (fflush(fp_new) == EOF)
1050 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1073 FILE *fp_orig = NULL;
1074 FILE *fp_new = NULL;
1081 coap_op_obs_cnt_deleted(context, resource_name);
1083 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1084 if (fp_orig == NULL)
1088 context->dyn_resource_save_file->length + 5);
1092 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1093 strcat(
new,
".tmp");
1094 fp_new = fopen(
new,
"w+");
1100 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1116 if (fflush(fp_new) == EOF)
1121 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1139 const char *dyn_resource_save_file,
1140 const char *observe_save_file,
1141 const char *obs_cnt_save_file,
1142 uint32_t save_freq) {
1147 dyn_resource_save_file,
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) {
1162 if (dyn_resource_save_file) {
1163 context->dyn_resource_save_file =
1165 strlen(dyn_resource_save_file));
1166 if (!context->dyn_resource_save_file)
1168 coap_op_dyn_resource_load_disk(context);
1172 if (obs_cnt_save_file) {
1173 context->obs_cnt_save_file =
1175 strlen(obs_cnt_save_file));
1176 if (!context->obs_cnt_save_file)
1179 coap_op_obs_cnt_load_disk(context);
1183 if (observe_save_file) {
1184 context->observe_save_file =
1186 strlen(observe_save_file));
1187 if (!context->observe_save_file)
1189 coap_op_observe_load_disk(context);
1201 context->dyn_resource_save_file = NULL;
1202 context->obs_cnt_save_file = NULL;
1203 context->observe_save_file = NULL;
1221 if (context == NULL)
1230 const char *dyn_resource_save_file,
1231 const char *observe_save_file,
1232 const char *obs_cnt_save_file,
1233 uint32_t save_freq) {
1235 (void)dyn_resource_save_file;
1236 (void)observe_save_file;
1237 (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().
#define coap_mutex_unlock(a)
#define coap_mutex_lock(a)
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
#define coap_lock_callback_release(c, func, failed)
#define coap_lock_unlock(c)
#define coap_lock_lock(c, failed)
#define coap_lock_check_locked(c)
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_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.
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...