20#define min(a,b) ((a) < (b) ? (a) : (b))
23#if COAP_SERVER_SUPPORT
59#if COAP_CONSTRAINED_STACK
75 if (e_listen_addr == NULL || s_addr_info == NULL || raw_packet == NULL)
84 if (ep->
proto == e_proto &&
92#if COAP_CONSTRAINED_STACK
93 coap_mutex_lock(&m_persist_add);
102 data = raw_packet->
s;
103 data_len = raw_packet->
length;
144 coap_log_warn(
"coap_persist_observe_add: resource '%s' not defined\n",
149 coap_log_warn(
"coap_persist_observe_add: resource '%s' not observable\n",
162#if COAP_OSCORE_SUPPORT
179 const uint8_t *info_buf = oscore_info->
s;
180 size_t info_buf_len = oscore_info->
length;
188 int have_partial_iv = 0;
189 int have_id_context = 0;
204 oscore_key_id.
s = info_buf;
205 info_buf += oscore_key_id.
length;
212 id_context.
s = info_buf;
213 info_buf += id_context.
length;
239 partial_iv.
s = info_buf;
240 info_buf += partial_iv.
length;
263 have_id_context ? &id_context : NULL, NULL,
264 &session->recipient_ctx);
266 session->oscore_encryption = 1;
268 session->recipient_ctx,
269 have_aad ? &aad : NULL,
270 have_nonce ? &nonce : NULL,
271 have_partial_iv ? &partial_iv : NULL,
275 have_partial_iv ? &partial_iv : NULL);
283#if COAP_CONSTRAINED_STACK
284 coap_mutex_unlock(&m_persist_add);
289 coap_log_warn(
"coap_persist_observe_add: discard malformed PDU\n");
291#if COAP_CONSTRAINED_STACK
292 coap_mutex_unlock(&m_persist_add);
299#if COAP_WITH_OBSERVE_PERSIST
313 assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info &&
314 raw_packet && oscore_info);
319 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
321 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
323 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
325 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
327 if (fread(&size,
sizeof(size), 1, fp) != 1)
329 if (size < 0 || size > 0x10000)
332 if ((scratch) == NULL)
334 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
338 if (fread(&size,
sizeof(size), 1, fp) != 1)
343 else if (size < 0 || size > 0x10000)
349 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
360 memset(e_proto, 0,
sizeof(*e_proto));
361 memset(e_listen_addr, 0,
sizeof(*e_listen_addr));
362 memset(s_addr_info, 0,
sizeof(*s_addr_info));
375 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
377 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
379 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
382 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
384 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
386 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
389 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
391 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
394 ssize_t not_defined = -1;
396 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
412 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
429 strcpy(
new, (
const char *)ctx->observe_save_file->s);
431 fp_new = fopen(
new,
"w+");
437 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
438 &s_addr_info, &raw_packet, &oscore_info))
447 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
448 s_addr_info, raw_packet, oscore_info))
461 if (fflush(fp_new) == EOF)
466 (void)rename(
new, (
const char *)ctx->observe_save_file->s);
494 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
508 session->
context->observe_save_file->length + 5);
512 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
514 fp_new = fopen(
new,
"w+");
520 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
521 &s_addr_info, &raw_packet, &oscore_info))
523 if (observe_key != a_observe_key) {
524 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
525 s_addr_info, raw_packet, oscore_info))
539 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
540 *a_s_addr_info, a_raw_packet, a_oscore_info))
543 if (fflush(fp_new) == EOF)
549 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
574 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
590 session->
context->observe_save_file->length + 5);
594 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
596 fp_new = fopen(
new,
"w+");
602 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
603 &s_addr_info, &raw_packet, &oscore_info))
605 if (observe_key != d_observe_key) {
606 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
621 if (fflush(fp_new) == EOF)
626 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
652 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
658 while (fgets(buf,
sizeof(buf), fp) != NULL) {
659 char *cp = strchr(buf,
' ');
661 uint32_t observe_num;
669 observe_num = atoi(cp);
677 resource_key.
s = (uint8_t *)buf;
678 resource_key.
length = strlen(buf);
681 coap_log_debug(
"persist: Initial observe number being updated\n");
696 uint32_t n_observe_num,
698 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
709 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
711 fp_new = fopen(
new,
"w+");
716 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) != NULL) {
717 char *cp = strchr(buf,
' ');
718 uint32_t observe_num;
726 observe_num = atoi(cp);
727 resource_key.
s = (uint8_t *)buf;
728 resource_key.
length = strlen(buf);
730 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
734 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
736 if (fflush(fp_new) == EOF)
742 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
764 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
775 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
777 fp_new = fopen(
new,
"w+");
782 while (fgets(buf,
sizeof(buf), fp_orig) != NULL) {
783 char *cp = strchr(buf,
' ');
784 uint32_t observe_num;
792 observe_num = atoi(cp);
793 resource_key.
s = (uint8_t *)buf;
794 resource_key.
length = strlen(buf);
796 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
800 if (fflush(fp_new) == EOF)
805 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
826coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
834 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
836 if (fread(&size,
sizeof(size), 1, fp) != 1)
838 if (size < 0 || size > 0x10000)
843 if (fread((*name)->s, size, 1, fp) != 1)
845 if (fread(&size,
sizeof(size), 1, fp) != 1)
847 if (size < 0 || size > 0x10000)
852 if (fread((*raw_packet)->s, size, 1, fp) != 1)
864coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
867 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
869 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
871 if (fwrite(name->
s, name->
length, 1, fp) != 1)
873 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
875 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
890 FILE *fp_orig = NULL;
903 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
915 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
930 session->
proto = e_proto;
932 raw_packet->
length, request)) {
984 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
989 context->dyn_resource_save_file->length + 5);
993 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
995 fp_new = fopen(
new,
"w+");
1001 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1017 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
1018 resource_name, packet))
1021 if (fflush(fp_new) == EOF)
1026 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1049 FILE *fp_orig = NULL;
1050 FILE *fp_new = NULL;
1057 coap_op_obs_cnt_deleted(context, resource_name);
1059 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1060 if (fp_orig == NULL)
1064 context->dyn_resource_save_file->length + 5);
1068 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1069 strcat(
new,
".tmp");
1070 fp_new = fopen(
new,
"w+");
1076 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1092 if (fflush(fp_new) == EOF)
1097 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1115 const char *dyn_resource_save_file,
1116 const char *observe_save_file,
1117 const char *obs_cnt_save_file,
1118 uint32_t save_freq) {
1119 if (dyn_resource_save_file) {
1120 context->dyn_resource_save_file =
1122 strlen(dyn_resource_save_file));
1123 if (!context->dyn_resource_save_file)
1125 coap_op_dyn_resource_load_disk(context);
1129 if (obs_cnt_save_file) {
1130 context->obs_cnt_save_file =
1132 strlen(obs_cnt_save_file));
1133 if (!context->obs_cnt_save_file)
1136 coap_op_obs_cnt_load_disk(context);
1140 if (observe_save_file) {
1141 context->observe_save_file =
1143 strlen(observe_save_file));
1144 if (!context->observe_save_file)
1146 coap_op_observe_load_disk(context);
1158 context->dyn_resource_save_file = NULL;
1159 context->obs_cnt_save_file = NULL;
1160 context->observe_save_file = NULL;
1169 if (context == NULL)
1177 const char *dyn_resource_save_file,
1178 const char *observe_save_file,
1179 const char *obs_cnt_save_file,
1180 uint32_t save_freq) {
1182 (void)dyn_resource_save_file;
1183 (void)observe_save_file;
1184 (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.
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...