20#define min(a,b) ((a) < (b) ? (a) : (b))
23#if COAP_SERVER_SUPPORT
59#if COAP_CONSTRAINED_STACK
60 COAP_MUTEX_DEFINE(e_static_mutex);
75 if (e_listen_addr == NULL || s_addr_info == NULL || packet == NULL)
84 if (ep->
proto == e_proto &&
90#if COAP_CONSTRAINED_STACK
91 coap_mutex_lock(&e_static_mutex);
99 data_len = raw_packet->
length;
140 coap_log_warn(
"coap_persist_observe_add: resource '%s' not defined\n",
145 coap_log_warn(
"coap_persist_observe_add: resource '%s' not observable\n",
158#if COAP_OSCORE_SUPPORT
175 const uint8_t *info_buf = oscore_info->
s;
176 size_t info_buf_len = oscore_info->
length;
184 int have_partial_iv = 0;
185 int have_id_context = 0;
200 oscore_key_id.
s = info_buf;
201 info_buf += oscore_key_id.
length;
208 id_context.
s = info_buf;
209 info_buf += id_context.
length;
235 partial_iv.
s = info_buf;
236 info_buf += partial_iv.
length;
259 have_id_context ? &id_context : NULL, NULL,
260 &session->recipient_ctx);
262 session->oscore_encryption = 1;
264 session->recipient_ctx,
265 have_aad ? &aad : NULL,
266 have_nonce ? &nonce : NULL,
267 have_partial_iv ? &partial_iv : NULL,
271 have_partial_iv ? &partial_iv : NULL);
279#if COAP_CONSTRAINED_STACK
280 coap_mutex_unlock(&e_static_mutex);
285 coap_log_warn(
"coap_persist_observe_add: discard malformed PDU\n");
287#if COAP_CONSTRAINED_STACK
288 coap_mutex_unlock(&e_static_mutex);
295#if COAP_WITH_OBSERVE_PERSIST
312 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
314 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
316 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
318 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
320 if (fread(&size,
sizeof(size), 1, fp) != 1)
323 if ((scratch) == NULL)
325 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
328 if (fread(&size,
sizeof(size), 1, fp) != 1)
330 if ((ssize_t)size == -1)
336 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
354 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
356 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
358 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
361 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
363 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
365 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
368 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
370 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
373 ssize_t not_defined = -1;
375 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
391 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
407 strcpy(
new, (
const char *)ctx->observe_save_file->s);
409 fp_new = fopen(
new,
"w+");
415 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
416 &s_addr_info, &raw_packet, &oscore_info))
425 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
426 s_addr_info, raw_packet, oscore_info))
439 if (fflush(fp_new) == EOF)
444 rename(
new, (
const char *)ctx->observe_save_file->s);
470 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
484 session->
context->observe_save_file->length + 5);
488 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
490 fp_new = fopen(
new,
"w+");
496 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
497 &s_addr_info, &raw_packet, &oscore_info))
499 if (observe_key != a_observe_key) {
500 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
501 s_addr_info, raw_packet, oscore_info))
515 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
516 *a_s_addr_info, a_raw_packet, a_oscore_info))
519 if (fflush(fp_new) == EOF)
525 rename(
new, (
const char *)session->
context->observe_save_file->s);
548 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
564 session->
context->observe_save_file->length + 5);
568 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
570 fp_new = fopen(
new,
"w+");
576 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
577 &s_addr_info, &raw_packet, &oscore_info))
579 if (observe_key != d_observe_key) {
580 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
595 if (fflush(fp_new) == EOF)
600 rename(
new, (
const char *)session->
context->observe_save_file->s);
624 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
630 while (fgets(buf,
sizeof(buf), fp) != NULL) {
631 char *cp = strchr(buf,
' ');
633 uint32_t observe_num;
641 observe_num = atoi(cp);
649 resource_key.
s = (uint8_t *)buf;
650 resource_key.
length = strlen(buf);
653 coap_log_debug(
"persist: Initial observe number being updated\n");
668 uint32_t n_observe_num,
670 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
681 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
683 fp_new = fopen(
new,
"w+");
688 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) != NULL) {
689 char *cp = strchr(buf,
' ');
690 uint32_t observe_num;
698 observe_num = atoi(cp);
699 resource_key.
s = (uint8_t *)buf;
700 resource_key.
length = strlen(buf);
702 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
706 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
708 if (fflush(fp_new) == EOF)
714 rename(
new, (
const char *)context->obs_cnt_save_file->s);
734 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
745 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
747 fp_new = fopen(
new,
"w+");
752 while (fgets(buf,
sizeof(buf), fp_orig) != NULL) {
753 char *cp = strchr(buf,
' ');
754 uint32_t observe_num;
762 observe_num = atoi(cp);
763 resource_key.
s = (uint8_t *)buf;
764 resource_key.
length = strlen(buf);
766 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
770 if (fflush(fp_new) == EOF)
775 rename(
new, (
const char *)context->obs_cnt_save_file->s);
794coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
802 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
804 if (fread(&size,
sizeof(size), 1, fp) != 1)
809 if (fread((*name)->s, size, 1, fp) != 1)
811 if (fread(&size,
sizeof(size), 1, fp) != 1)
816 if (fread((*raw_packet)->s, size, 1, fp) != 1)
828coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
831 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
833 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
835 if (fwrite(name->
s, name->
length, 1, fp) != 1)
837 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
839 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
854 FILE *fp_orig = NULL;
867 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
879 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
894 session->
proto = e_proto;
896 raw_packet->
length, request)) {
948 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
953 context->dyn_resource_save_file->length + 5);
957 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
959 fp_new = fopen(
new,
"w+");
965 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
981 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
982 resource_name, packet))
985 if (fflush(fp_new) == EOF)
990 rename(
new, (
const char *)context->dyn_resource_save_file->s);
1011 FILE *fp_orig = NULL;
1012 FILE *fp_new = NULL;
1019 coap_op_obs_cnt_deleted(context, resource_name);
1021 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1022 if (fp_orig == NULL)
1026 context->dyn_resource_save_file->length + 5);
1030 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1031 strcat(
new,
".tmp");
1032 fp_new = fopen(
new,
"w+");
1038 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1054 if (fflush(fp_new) == EOF)
1059 rename(
new, (
const char *)context->dyn_resource_save_file->s);
1075 const char *dyn_resource_save_file,
1076 const char *observe_save_file,
1077 const char *obs_cnt_save_file,
1078 uint32_t save_freq) {
1079 if (dyn_resource_save_file) {
1080 context->dyn_resource_save_file =
1082 strlen(dyn_resource_save_file));
1083 if (!context->dyn_resource_save_file)
1085 coap_op_dyn_resource_load_disk(context);
1089 if (obs_cnt_save_file) {
1090 context->obs_cnt_save_file =
1092 strlen(obs_cnt_save_file));
1093 if (!context->obs_cnt_save_file)
1096 coap_op_obs_cnt_load_disk(context);
1100 if (observe_save_file) {
1101 context->observe_save_file =
1103 strlen(observe_save_file));
1104 if (!context->observe_save_file)
1106 coap_op_observe_load_disk(context);
1118 context->dyn_resource_save_file = NULL;
1119 context->obs_cnt_save_file = NULL;
1120 context->observe_save_file = NULL;
1135 const char *dyn_resource_save_file,
1136 const char *observe_save_file,
1137 const char *obs_cnt_save_file,
1138 uint32_t save_freq) {
1140 (void)dyn_resource_save_file;
1141 (void)observe_save_file;
1142 (void)obs_cnt_save_file;
Pulls together all the internal only header files.
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(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(...)
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_stop(coap_context_t *context)
Stop tracking persist information, leaving the current persist information in the files defined in co...
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...
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...
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.
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...
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_cleanup(coap_context_t *context)
Close down persist tracking, releasing any memory used.
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.
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.
coap_addr_tuple_t addr_info
local and remote addresses
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...