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 || 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
316 if (fread(observe_key,
sizeof(*observe_key), 1, fp) == 1) {
318 if (fread(e_proto,
sizeof(*e_proto), 1, fp) != 1)
320 if (fread(e_listen_addr,
sizeof(*e_listen_addr), 1, fp) != 1)
322 if (fread(s_addr_info,
sizeof(*s_addr_info), 1, fp) != 1)
324 if (fread(&size,
sizeof(size), 1, fp) != 1)
326 if (size < 0 || size > 0x10000)
329 if ((scratch) == NULL)
331 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
334 if (fread(&size,
sizeof(size), 1, fp) != 1)
338 else if (size < 0 || size > 0x10000)
344 if (fread(scratch->
s, scratch->
length, 1, fp) != 1)
364 if (fwrite(&observe_key,
sizeof(observe_key), 1, fp) != 1)
366 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
368 if (fwrite(&e_listen_addr,
sizeof(e_listen_addr),
371 if (fwrite(&s_addr_info,
sizeof(s_addr_info), 1, fp) != 1)
373 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
375 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
378 if (fwrite(&oscore_info->
length,
sizeof(oscore_info->
length), 1, fp) != 1)
380 if (fwrite(oscore_info->
s, oscore_info->
length, 1, fp) != 1)
383 ssize_t not_defined = -1;
385 if (fwrite(¬_defined,
sizeof(not_defined), 1, fp) != 1)
401 FILE *fp_orig = fopen((
const char *)ctx->observe_save_file->s,
"r");
417 strcpy(
new, (
const char *)ctx->observe_save_file->s);
419 fp_new = fopen(
new,
"w+");
425 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
426 &s_addr_info, &raw_packet, &oscore_info))
435 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
436 s_addr_info, raw_packet, oscore_info))
449 if (fflush(fp_new) == EOF)
454 (void)rename(
new, (
const char *)ctx->observe_save_file->s);
482 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
496 session->
context->observe_save_file->length + 5);
500 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
502 fp_new = fopen(
new,
"w+");
508 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
509 &s_addr_info, &raw_packet, &oscore_info))
511 if (observe_key != a_observe_key) {
512 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
513 s_addr_info, raw_packet, oscore_info))
527 if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr,
528 *a_s_addr_info, a_raw_packet, a_oscore_info))
531 if (fflush(fp_new) == EOF)
537 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
562 FILE *fp_orig = fopen((
const char *)session->
context->observe_save_file->s,
578 session->
context->observe_save_file->length + 5);
582 strcpy(
new, (
const char *)session->
context->observe_save_file->s);
584 fp_new = fopen(
new,
"w+");
590 if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr,
591 &s_addr_info, &raw_packet, &oscore_info))
593 if (observe_key != d_observe_key) {
594 if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr,
609 if (fflush(fp_new) == EOF)
614 (void)rename(
new, (
const char *)session->
context->observe_save_file->s);
640 FILE *fp = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
646 while (fgets(buf,
sizeof(buf), fp) != NULL) {
647 char *cp = strchr(buf,
' ');
649 uint32_t observe_num;
657 observe_num = atoi(cp);
665 resource_key.
s = (uint8_t *)buf;
666 resource_key.
length = strlen(buf);
669 coap_log_debug(
"persist: Initial observe number being updated\n");
684 uint32_t n_observe_num,
686 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
697 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
699 fp_new = fopen(
new,
"w+");
704 while (fp_orig && fgets(buf,
sizeof(buf), fp_orig) != NULL) {
705 char *cp = strchr(buf,
' ');
706 uint32_t observe_num;
714 observe_num = atoi(cp);
715 resource_key.
s = (uint8_t *)buf;
716 resource_key.
length = strlen(buf);
718 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
722 if (fprintf(fp_new,
"%s %u\n", resource_name->
s, n_observe_num) < 0)
724 if (fflush(fp_new) == EOF)
730 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
752 FILE *fp_orig = fopen((
const char *)context->obs_cnt_save_file->s,
"r");
763 strcpy(
new, (
const char *)context->obs_cnt_save_file->s);
765 fp_new = fopen(
new,
"w+");
770 while (fgets(buf,
sizeof(buf), fp_orig) != NULL) {
771 char *cp = strchr(buf,
' ');
772 uint32_t observe_num;
780 observe_num = atoi(cp);
781 resource_key.
s = (uint8_t *)buf;
782 resource_key.
length = strlen(buf);
784 if (fprintf(fp_new,
"%s %u\n", resource_key.
s, observe_num) < 0)
788 if (fflush(fp_new) == EOF)
793 (void)rename(
new, (
const char *)context->obs_cnt_save_file->s);
814coap_op_dyn_resource_read(FILE *fp,
coap_proto_t *e_proto,
822 if (fread(e_proto,
sizeof(*e_proto), 1, fp) == 1) {
824 if (fread(&size,
sizeof(size), 1, fp) != 1)
826 if (size < 0 || size > 0x10000)
831 if (fread((*name)->s, size, 1, fp) != 1)
833 if (fread(&size,
sizeof(size), 1, fp) != 1)
835 if (size < 0 || size > 0x10000)
840 if (fread((*raw_packet)->s, size, 1, fp) != 1)
852coap_op_dyn_resource_write(FILE *fp,
coap_proto_t e_proto,
855 if (fwrite(&e_proto,
sizeof(e_proto), 1, fp) != 1)
857 if (fwrite(&name->
length,
sizeof(name->
length), 1, fp) != 1)
859 if (fwrite(name->
s, name->
length, 1, fp) != 1)
861 if (fwrite(&raw_packet->
length,
sizeof(raw_packet->
length), 1, fp) != 1)
863 if (fwrite(raw_packet->
s, raw_packet->
length, 1, fp) != 1)
878 FILE *fp_orig = NULL;
891 fp_orig = fopen((
const char *)ctx->dyn_resource_save_file->s,
"r");
903 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
918 session->
proto = e_proto;
920 raw_packet->
length, request)) {
972 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"a");
977 context->dyn_resource_save_file->length + 5);
981 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
983 fp_new = fopen(
new,
"w+");
989 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1005 if (!coap_op_dyn_resource_write(fp_new, session->
proto,
1006 resource_name, packet))
1009 if (fflush(fp_new) == EOF)
1014 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1037 FILE *fp_orig = NULL;
1038 FILE *fp_new = NULL;
1045 coap_op_obs_cnt_deleted(context, resource_name);
1047 fp_orig = fopen((
const char *)context->dyn_resource_save_file->s,
"r");
1048 if (fp_orig == NULL)
1052 context->dyn_resource_save_file->length + 5);
1056 strcpy(
new, (
const char *)context->dyn_resource_save_file->s);
1057 strcat(
new,
".tmp");
1058 fp_new = fopen(
new,
"w+");
1064 if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet))
1080 if (fflush(fp_new) == EOF)
1085 (void)rename(
new, (
const char *)context->dyn_resource_save_file->s);
1103 const char *dyn_resource_save_file,
1104 const char *observe_save_file,
1105 const char *obs_cnt_save_file,
1106 uint32_t save_freq) {
1107 if (dyn_resource_save_file) {
1108 context->dyn_resource_save_file =
1110 strlen(dyn_resource_save_file));
1111 if (!context->dyn_resource_save_file)
1113 coap_op_dyn_resource_load_disk(context);
1117 if (obs_cnt_save_file) {
1118 context->obs_cnt_save_file =
1120 strlen(obs_cnt_save_file));
1121 if (!context->obs_cnt_save_file)
1124 coap_op_obs_cnt_load_disk(context);
1128 if (observe_save_file) {
1129 context->observe_save_file =
1131 strlen(observe_save_file));
1132 if (!context->observe_save_file)
1134 coap_op_observe_load_disk(context);
1146 context->dyn_resource_save_file = NULL;
1147 context->obs_cnt_save_file = NULL;
1148 context->observe_save_file = NULL;
1157 if (context == NULL)
1165 const char *dyn_resource_save_file,
1166 const char *observe_save_file,
1167 const char *obs_cnt_save_file,
1168 uint32_t save_freq) {
1170 (void)dyn_resource_save_file;
1171 (void)observe_save_file;
1172 (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...