1c87c5fbaSopenharmony_ci/* coap_subscribe.c -- subscription handling for CoAP 2c87c5fbaSopenharmony_ci * see RFC7641 3c87c5fbaSopenharmony_ci * 4c87c5fbaSopenharmony_ci * Copyright (C) 2010-2019,2022-2023 Olaf Bergmann <bergmann@tzi.org> 5c87c5fbaSopenharmony_ci * 6c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 7c87c5fbaSopenharmony_ci * 8c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see 9c87c5fbaSopenharmony_ci * README for terms of use. 10c87c5fbaSopenharmony_ci */ 11c87c5fbaSopenharmony_ci 12c87c5fbaSopenharmony_ci/** 13c87c5fbaSopenharmony_ci * @file coap_subscribe.c 14c87c5fbaSopenharmony_ci * @brief Subscription handling functions 15c87c5fbaSopenharmony_ci */ 16c87c5fbaSopenharmony_ci 17c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h" 18c87c5fbaSopenharmony_ci 19c87c5fbaSopenharmony_ci#ifndef min 20c87c5fbaSopenharmony_ci#define min(a,b) ((a) < (b) ? (a) : (b)) 21c87c5fbaSopenharmony_ci#endif 22c87c5fbaSopenharmony_ci 23c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 24c87c5fbaSopenharmony_civoid 25c87c5fbaSopenharmony_cicoap_subscription_init(coap_subscription_t *s) { 26c87c5fbaSopenharmony_ci assert(s); 27c87c5fbaSopenharmony_ci memset(s, 0, sizeof(coap_subscription_t)); 28c87c5fbaSopenharmony_ci} 29c87c5fbaSopenharmony_ci 30c87c5fbaSopenharmony_civoid 31c87c5fbaSopenharmony_cicoap_persist_track_funcs(coap_context_t *context, 32c87c5fbaSopenharmony_ci coap_observe_added_t observe_added, 33c87c5fbaSopenharmony_ci coap_observe_deleted_t observe_deleted, 34c87c5fbaSopenharmony_ci coap_track_observe_value_t track_observe_value, 35c87c5fbaSopenharmony_ci coap_dyn_resource_added_t dyn_resource_added, 36c87c5fbaSopenharmony_ci coap_resource_deleted_t resource_deleted, 37c87c5fbaSopenharmony_ci uint32_t save_freq, 38c87c5fbaSopenharmony_ci void *user_data) { 39c87c5fbaSopenharmony_ci context->observe_added = observe_added; 40c87c5fbaSopenharmony_ci context->observe_deleted = observe_deleted; 41c87c5fbaSopenharmony_ci context->observe_user_data = user_data; 42c87c5fbaSopenharmony_ci context->observe_save_freq = save_freq ? save_freq : 1; 43c87c5fbaSopenharmony_ci context->track_observe_value = track_observe_value; 44c87c5fbaSopenharmony_ci context->dyn_resource_added = dyn_resource_added; 45c87c5fbaSopenharmony_ci context->resource_deleted = resource_deleted; 46c87c5fbaSopenharmony_ci} 47c87c5fbaSopenharmony_ci 48c87c5fbaSopenharmony_cicoap_subscription_t * 49c87c5fbaSopenharmony_cicoap_persist_observe_add(coap_context_t *context, 50c87c5fbaSopenharmony_ci coap_proto_t e_proto, 51c87c5fbaSopenharmony_ci const coap_address_t *e_listen_addr, 52c87c5fbaSopenharmony_ci const coap_addr_tuple_t *s_addr_info, 53c87c5fbaSopenharmony_ci const coap_bin_const_t *raw_packet, 54c87c5fbaSopenharmony_ci const coap_bin_const_t *oscore_info) { 55c87c5fbaSopenharmony_ci coap_session_t *session = NULL; 56c87c5fbaSopenharmony_ci const uint8_t *data; 57c87c5fbaSopenharmony_ci size_t data_len; 58c87c5fbaSopenharmony_ci coap_pdu_t *pdu = NULL; 59c87c5fbaSopenharmony_ci#if COAP_CONSTRAINED_STACK 60c87c5fbaSopenharmony_ci /* e_packet protected by mutex m_persist_add */ 61c87c5fbaSopenharmony_ci static coap_packet_t e_packet; 62c87c5fbaSopenharmony_ci#else /* ! COAP_CONSTRAINED_STACK */ 63c87c5fbaSopenharmony_ci coap_packet_t e_packet; 64c87c5fbaSopenharmony_ci#endif /* ! COAP_CONSTRAINED_STACK */ 65c87c5fbaSopenharmony_ci coap_packet_t *packet = &e_packet; 66c87c5fbaSopenharmony_ci coap_tick_t now; 67c87c5fbaSopenharmony_ci coap_string_t *uri_path = NULL; 68c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 69c87c5fbaSopenharmony_ci coap_opt_t *observe; 70c87c5fbaSopenharmony_ci int observe_action; 71c87c5fbaSopenharmony_ci coap_resource_t *r; 72c87c5fbaSopenharmony_ci coap_subscription_t *s; 73c87c5fbaSopenharmony_ci coap_endpoint_t *ep; 74c87c5fbaSopenharmony_ci 75c87c5fbaSopenharmony_ci if (e_listen_addr == NULL || s_addr_info == NULL || raw_packet == NULL) 76c87c5fbaSopenharmony_ci return NULL; 77c87c5fbaSopenharmony_ci 78c87c5fbaSopenharmony_ci /* Will be creating a local 'open' session */ 79c87c5fbaSopenharmony_ci if (e_proto != COAP_PROTO_UDP) 80c87c5fbaSopenharmony_ci return NULL; 81c87c5fbaSopenharmony_ci 82c87c5fbaSopenharmony_ci ep = context->endpoint; 83c87c5fbaSopenharmony_ci while (ep) { 84c87c5fbaSopenharmony_ci if (ep->proto == e_proto && 85c87c5fbaSopenharmony_ci memcmp(e_listen_addr, &ep->bind_addr, sizeof(ep->bind_addr)) == 0) 86c87c5fbaSopenharmony_ci break; 87c87c5fbaSopenharmony_ci ep = ep->next; 88c87c5fbaSopenharmony_ci } 89c87c5fbaSopenharmony_ci if (!ep) 90c87c5fbaSopenharmony_ci return NULL; 91c87c5fbaSopenharmony_ci 92c87c5fbaSopenharmony_ci#if COAP_CONSTRAINED_STACK 93c87c5fbaSopenharmony_ci coap_mutex_lock(&m_persist_add); 94c87c5fbaSopenharmony_ci#endif /* COAP_CONSTRAINED_STACK */ 95c87c5fbaSopenharmony_ci 96c87c5fbaSopenharmony_ci /* Build up packet */ 97c87c5fbaSopenharmony_ci memcpy(&packet->addr_info, s_addr_info, sizeof(packet->addr_info)); 98c87c5fbaSopenharmony_ci packet->ifindex = 0; 99c87c5fbaSopenharmony_ci memcpy(&packet->payload, &raw_packet->s, sizeof(packet->payload)); 100c87c5fbaSopenharmony_ci packet->length = raw_packet->length; 101c87c5fbaSopenharmony_ci 102c87c5fbaSopenharmony_ci data = raw_packet->s; 103c87c5fbaSopenharmony_ci data_len = raw_packet->length; 104c87c5fbaSopenharmony_ci if (data_len < 4) 105c87c5fbaSopenharmony_ci goto malformed; 106c87c5fbaSopenharmony_ci 107c87c5fbaSopenharmony_ci /* Get the session */ 108c87c5fbaSopenharmony_ci 109c87c5fbaSopenharmony_ci coap_ticks(&now); 110c87c5fbaSopenharmony_ci session = coap_endpoint_get_session(ep, packet, now); 111c87c5fbaSopenharmony_ci if (session == NULL) 112c87c5fbaSopenharmony_ci goto fail; 113c87c5fbaSopenharmony_ci /* Need max space incase PDU is updated with updated token, huge size etc. */ 114c87c5fbaSopenharmony_ci pdu = coap_pdu_init(0, 0, 0, 0); 115c87c5fbaSopenharmony_ci if (!pdu) 116c87c5fbaSopenharmony_ci goto fail; 117c87c5fbaSopenharmony_ci 118c87c5fbaSopenharmony_ci if (!coap_pdu_parse(session->proto, data, data_len, pdu)) { 119c87c5fbaSopenharmony_ci goto malformed; 120c87c5fbaSopenharmony_ci } 121c87c5fbaSopenharmony_ci pdu->max_size = pdu->used_size; 122c87c5fbaSopenharmony_ci 123c87c5fbaSopenharmony_ci if (pdu->code != COAP_REQUEST_CODE_GET && 124c87c5fbaSopenharmony_ci pdu->code != COAP_REQUEST_CODE_FETCH) 125c87c5fbaSopenharmony_ci goto malformed; 126c87c5fbaSopenharmony_ci 127c87c5fbaSopenharmony_ci observe = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter); 128c87c5fbaSopenharmony_ci if (observe == NULL) 129c87c5fbaSopenharmony_ci goto malformed; 130c87c5fbaSopenharmony_ci observe_action = coap_decode_var_bytes(coap_opt_value(observe), 131c87c5fbaSopenharmony_ci coap_opt_length(observe)); 132c87c5fbaSopenharmony_ci if (observe_action != COAP_OBSERVE_ESTABLISH) 133c87c5fbaSopenharmony_ci goto malformed; 134c87c5fbaSopenharmony_ci 135c87c5fbaSopenharmony_ci /* Get the resource */ 136c87c5fbaSopenharmony_ci 137c87c5fbaSopenharmony_ci uri_path = coap_get_uri_path(pdu); 138c87c5fbaSopenharmony_ci if (!uri_path) 139c87c5fbaSopenharmony_ci goto malformed; 140c87c5fbaSopenharmony_ci 141c87c5fbaSopenharmony_ci r = coap_get_resource_from_uri_path(session->context, 142c87c5fbaSopenharmony_ci (coap_str_const_t *)uri_path); 143c87c5fbaSopenharmony_ci if (r == NULL) { 144c87c5fbaSopenharmony_ci coap_log_warn("coap_persist_observe_add: resource '%s' not defined\n", 145c87c5fbaSopenharmony_ci uri_path->s); 146c87c5fbaSopenharmony_ci goto fail; 147c87c5fbaSopenharmony_ci } 148c87c5fbaSopenharmony_ci if (!r->observable) { 149c87c5fbaSopenharmony_ci coap_log_warn("coap_persist_observe_add: resource '%s' not observable\n", 150c87c5fbaSopenharmony_ci uri_path->s); 151c87c5fbaSopenharmony_ci goto fail; 152c87c5fbaSopenharmony_ci } 153c87c5fbaSopenharmony_ci coap_delete_string(uri_path); 154c87c5fbaSopenharmony_ci uri_path = NULL; 155c87c5fbaSopenharmony_ci 156c87c5fbaSopenharmony_ci /* Create / update subscription for observing */ 157c87c5fbaSopenharmony_ci /* Now set up the subscription */ 158c87c5fbaSopenharmony_ci s = coap_add_observer(r, session, &pdu->actual_token, pdu); 159c87c5fbaSopenharmony_ci if (s == NULL) 160c87c5fbaSopenharmony_ci goto fail; 161c87c5fbaSopenharmony_ci 162c87c5fbaSopenharmony_ci#if COAP_OSCORE_SUPPORT 163c87c5fbaSopenharmony_ci if (oscore_info) { 164c87c5fbaSopenharmony_ci coap_log_debug("persist: OSCORE association being updated\n"); 165c87c5fbaSopenharmony_ci /* 166c87c5fbaSopenharmony_ci * Need to track the association used for tracking this observe, done as 167c87c5fbaSopenharmony_ci * a CBOR array. Written in coap_add_observer(). 168c87c5fbaSopenharmony_ci * 169c87c5fbaSopenharmony_ci * If an entry is null, then use nil, else a set of bytes 170c87c5fbaSopenharmony_ci * 171c87c5fbaSopenharmony_ci * Currently tracking 5 items 172c87c5fbaSopenharmony_ci * recipient_id 173c87c5fbaSopenharmony_ci * id_context 174c87c5fbaSopenharmony_ci * aad (from oscore_association_t) 175c87c5fbaSopenharmony_ci * partial_iv (from oscore_association_t) 176c87c5fbaSopenharmony_ci * nonce (from oscore_association_t) 177c87c5fbaSopenharmony_ci */ 178c87c5fbaSopenharmony_ci oscore_ctx_t *osc_ctx; 179c87c5fbaSopenharmony_ci const uint8_t *info_buf = oscore_info->s; 180c87c5fbaSopenharmony_ci size_t info_buf_len = oscore_info->length; 181c87c5fbaSopenharmony_ci size_t ret = 0; 182c87c5fbaSopenharmony_ci coap_bin_const_t oscore_key_id; 183c87c5fbaSopenharmony_ci coap_bin_const_t partial_iv; 184c87c5fbaSopenharmony_ci coap_bin_const_t aad; 185c87c5fbaSopenharmony_ci coap_bin_const_t id_context; 186c87c5fbaSopenharmony_ci coap_bin_const_t nonce; 187c87c5fbaSopenharmony_ci int have_aad = 0; 188c87c5fbaSopenharmony_ci int have_partial_iv = 0; 189c87c5fbaSopenharmony_ci int have_id_context = 0; 190c87c5fbaSopenharmony_ci int have_nonce = 0; 191c87c5fbaSopenharmony_ci 192c87c5fbaSopenharmony_ci ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len); 193c87c5fbaSopenharmony_ci if (ret != CBOR_ARRAY) 194c87c5fbaSopenharmony_ci goto oscore_fail; 195c87c5fbaSopenharmony_ci if (oscore_cbor_get_element_size(&info_buf, &info_buf_len) != 5) 196c87c5fbaSopenharmony_ci goto oscore_fail; 197c87c5fbaSopenharmony_ci 198c87c5fbaSopenharmony_ci /* recipient_id */ 199c87c5fbaSopenharmony_ci ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len); 200c87c5fbaSopenharmony_ci if (ret != CBOR_BYTE_STRING) 201c87c5fbaSopenharmony_ci goto oscore_fail; 202c87c5fbaSopenharmony_ci oscore_key_id.length = oscore_cbor_get_element_size(&info_buf, 203c87c5fbaSopenharmony_ci &info_buf_len); 204c87c5fbaSopenharmony_ci oscore_key_id.s = info_buf; 205c87c5fbaSopenharmony_ci info_buf += oscore_key_id.length; 206c87c5fbaSopenharmony_ci 207c87c5fbaSopenharmony_ci /* id_context */ 208c87c5fbaSopenharmony_ci ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len); 209c87c5fbaSopenharmony_ci if (ret == CBOR_BYTE_STRING) { 210c87c5fbaSopenharmony_ci id_context.length = oscore_cbor_get_element_size(&info_buf, 211c87c5fbaSopenharmony_ci &info_buf_len); 212c87c5fbaSopenharmony_ci id_context.s = info_buf; 213c87c5fbaSopenharmony_ci info_buf += id_context.length; 214c87c5fbaSopenharmony_ci have_id_context = 1; 215c87c5fbaSopenharmony_ci } else if (ret == CBOR_SIMPLE_VALUE && 216c87c5fbaSopenharmony_ci oscore_cbor_get_element_size(&info_buf, 217c87c5fbaSopenharmony_ci &info_buf_len) == CBOR_NULL) { 218c87c5fbaSopenharmony_ci } else 219c87c5fbaSopenharmony_ci goto oscore_fail; 220c87c5fbaSopenharmony_ci 221c87c5fbaSopenharmony_ci /* aad */ 222c87c5fbaSopenharmony_ci ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len); 223c87c5fbaSopenharmony_ci if (ret == CBOR_BYTE_STRING) { 224c87c5fbaSopenharmony_ci aad.length = oscore_cbor_get_element_size(&info_buf, &info_buf_len); 225c87c5fbaSopenharmony_ci aad.s = info_buf; 226c87c5fbaSopenharmony_ci info_buf += aad.length; 227c87c5fbaSopenharmony_ci have_aad = 1; 228c87c5fbaSopenharmony_ci } else if (ret == CBOR_SIMPLE_VALUE && 229c87c5fbaSopenharmony_ci oscore_cbor_get_element_size(&info_buf, 230c87c5fbaSopenharmony_ci &info_buf_len) == CBOR_NULL) { 231c87c5fbaSopenharmony_ci } else 232c87c5fbaSopenharmony_ci goto oscore_fail; 233c87c5fbaSopenharmony_ci 234c87c5fbaSopenharmony_ci /* partial_iv */ 235c87c5fbaSopenharmony_ci ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len); 236c87c5fbaSopenharmony_ci if (ret == CBOR_BYTE_STRING) { 237c87c5fbaSopenharmony_ci partial_iv.length = oscore_cbor_get_element_size(&info_buf, 238c87c5fbaSopenharmony_ci &info_buf_len); 239c87c5fbaSopenharmony_ci partial_iv.s = info_buf; 240c87c5fbaSopenharmony_ci info_buf += partial_iv.length; 241c87c5fbaSopenharmony_ci have_partial_iv = 1; 242c87c5fbaSopenharmony_ci } else if (ret == CBOR_SIMPLE_VALUE && 243c87c5fbaSopenharmony_ci oscore_cbor_get_element_size(&info_buf, 244c87c5fbaSopenharmony_ci &info_buf_len) == CBOR_NULL) { 245c87c5fbaSopenharmony_ci } else 246c87c5fbaSopenharmony_ci goto oscore_fail; 247c87c5fbaSopenharmony_ci 248c87c5fbaSopenharmony_ci /* nonce */ 249c87c5fbaSopenharmony_ci ret = oscore_cbor_get_next_element(&info_buf, &info_buf_len); 250c87c5fbaSopenharmony_ci if (ret == CBOR_BYTE_STRING) { 251c87c5fbaSopenharmony_ci nonce.length = oscore_cbor_get_element_size(&info_buf, 252c87c5fbaSopenharmony_ci &info_buf_len); 253c87c5fbaSopenharmony_ci nonce.s = info_buf; 254c87c5fbaSopenharmony_ci info_buf += nonce.length; 255c87c5fbaSopenharmony_ci have_nonce = 1; 256c87c5fbaSopenharmony_ci } else if (ret == CBOR_SIMPLE_VALUE && 257c87c5fbaSopenharmony_ci oscore_cbor_get_element_size(&info_buf, 258c87c5fbaSopenharmony_ci &info_buf_len) == CBOR_NULL) { 259c87c5fbaSopenharmony_ci } else 260c87c5fbaSopenharmony_ci goto oscore_fail; 261c87c5fbaSopenharmony_ci 262c87c5fbaSopenharmony_ci osc_ctx = oscore_find_context(session->context, oscore_key_id, 263c87c5fbaSopenharmony_ci have_id_context ? &id_context : NULL, NULL, 264c87c5fbaSopenharmony_ci &session->recipient_ctx); 265c87c5fbaSopenharmony_ci if (osc_ctx) { 266c87c5fbaSopenharmony_ci session->oscore_encryption = 1; 267c87c5fbaSopenharmony_ci oscore_new_association(session, pdu, &pdu->actual_token, 268c87c5fbaSopenharmony_ci session->recipient_ctx, 269c87c5fbaSopenharmony_ci have_aad ? &aad : NULL, 270c87c5fbaSopenharmony_ci have_nonce ? &nonce : NULL, 271c87c5fbaSopenharmony_ci have_partial_iv ? &partial_iv : NULL, 272c87c5fbaSopenharmony_ci 1); 273c87c5fbaSopenharmony_ci coap_log_debug("persist: OSCORE association added\n"); 274c87c5fbaSopenharmony_ci oscore_log_hex_value(COAP_LOG_OSCORE, "partial_iv", 275c87c5fbaSopenharmony_ci have_partial_iv ? &partial_iv : NULL); 276c87c5fbaSopenharmony_ci } 277c87c5fbaSopenharmony_ci } 278c87c5fbaSopenharmony_cioscore_fail: 279c87c5fbaSopenharmony_ci#else /* ! COAP_OSCORE_SUPPORT */ 280c87c5fbaSopenharmony_ci (void)oscore_info; 281c87c5fbaSopenharmony_ci#endif /* ! COAP_OSCORE_SUPPORT */ 282c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 283c87c5fbaSopenharmony_ci#if COAP_CONSTRAINED_STACK 284c87c5fbaSopenharmony_ci coap_mutex_unlock(&m_persist_add); 285c87c5fbaSopenharmony_ci#endif /* COAP_CONSTRAINED_STACK */ 286c87c5fbaSopenharmony_ci return s; 287c87c5fbaSopenharmony_ci 288c87c5fbaSopenharmony_cimalformed: 289c87c5fbaSopenharmony_ci coap_log_warn("coap_persist_observe_add: discard malformed PDU\n"); 290c87c5fbaSopenharmony_cifail: 291c87c5fbaSopenharmony_ci#if COAP_CONSTRAINED_STACK 292c87c5fbaSopenharmony_ci coap_mutex_unlock(&m_persist_add); 293c87c5fbaSopenharmony_ci#endif /* COAP_CONSTRAINED_STACK */ 294c87c5fbaSopenharmony_ci coap_delete_string(uri_path); 295c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 296c87c5fbaSopenharmony_ci return NULL; 297c87c5fbaSopenharmony_ci} 298c87c5fbaSopenharmony_ci 299c87c5fbaSopenharmony_ci#if COAP_WITH_OBSERVE_PERSIST 300c87c5fbaSopenharmony_ci#include <stdio.h> 301c87c5fbaSopenharmony_ci 302c87c5fbaSopenharmony_ci/* 303c87c5fbaSopenharmony_ci * read in active observe entry. 304c87c5fbaSopenharmony_ci */ 305c87c5fbaSopenharmony_cistatic int 306c87c5fbaSopenharmony_cicoap_op_observe_read(FILE *fp, coap_subscription_t **observe_key, 307c87c5fbaSopenharmony_ci coap_proto_t *e_proto, coap_address_t *e_listen_addr, 308c87c5fbaSopenharmony_ci coap_addr_tuple_t *s_addr_info, 309c87c5fbaSopenharmony_ci coap_bin_const_t **raw_packet, coap_bin_const_t **oscore_info) { 310c87c5fbaSopenharmony_ci ssize_t size; 311c87c5fbaSopenharmony_ci coap_binary_t *scratch = NULL; 312c87c5fbaSopenharmony_ci 313c87c5fbaSopenharmony_ci assert(fp && observe_key && e_proto && e_listen_addr && s_addr_info && 314c87c5fbaSopenharmony_ci raw_packet && oscore_info); 315c87c5fbaSopenharmony_ci 316c87c5fbaSopenharmony_ci *raw_packet = NULL; 317c87c5fbaSopenharmony_ci *oscore_info = NULL; 318c87c5fbaSopenharmony_ci 319c87c5fbaSopenharmony_ci if (fread(observe_key, sizeof(*observe_key), 1, fp) == 1) { 320c87c5fbaSopenharmony_ci /* New record 'key proto listen addr_info len raw_packet len oscore' */ 321c87c5fbaSopenharmony_ci if (fread(e_proto, sizeof(*e_proto), 1, fp) != 1) 322c87c5fbaSopenharmony_ci goto fail; 323c87c5fbaSopenharmony_ci if (fread(e_listen_addr, sizeof(*e_listen_addr), 1, fp) != 1) 324c87c5fbaSopenharmony_ci goto fail; 325c87c5fbaSopenharmony_ci if (fread(s_addr_info, sizeof(*s_addr_info), 1, fp) != 1) 326c87c5fbaSopenharmony_ci goto fail; 327c87c5fbaSopenharmony_ci if (fread(&size, sizeof(size), 1, fp) != 1) 328c87c5fbaSopenharmony_ci goto fail; 329c87c5fbaSopenharmony_ci if (size < 0 || size > 0x10000) 330c87c5fbaSopenharmony_ci goto fail; 331c87c5fbaSopenharmony_ci scratch = coap_new_binary(size); 332c87c5fbaSopenharmony_ci if ((scratch) == NULL) 333c87c5fbaSopenharmony_ci goto fail; 334c87c5fbaSopenharmony_ci if (fread(scratch->s, scratch->length, 1, fp) != 1) 335c87c5fbaSopenharmony_ci goto fail; 336c87c5fbaSopenharmony_ci *raw_packet = (coap_bin_const_t *)scratch; 337c87c5fbaSopenharmony_ci scratch = NULL; 338c87c5fbaSopenharmony_ci if (fread(&size, sizeof(size), 1, fp) != 1) 339c87c5fbaSopenharmony_ci goto fail; 340c87c5fbaSopenharmony_ci /* If size == -1, then no oscore information */ 341c87c5fbaSopenharmony_ci if (size == -1) 342c87c5fbaSopenharmony_ci return 1; 343c87c5fbaSopenharmony_ci else if (size < 0 || size > 0x10000) 344c87c5fbaSopenharmony_ci goto fail; 345c87c5fbaSopenharmony_ci else { 346c87c5fbaSopenharmony_ci scratch = coap_new_binary(size); 347c87c5fbaSopenharmony_ci if (scratch == NULL) 348c87c5fbaSopenharmony_ci goto fail; 349c87c5fbaSopenharmony_ci if (fread(scratch->s, scratch->length, 1, fp) != 1) 350c87c5fbaSopenharmony_ci goto fail; 351c87c5fbaSopenharmony_ci *oscore_info = (coap_bin_const_t *)scratch; 352c87c5fbaSopenharmony_ci } 353c87c5fbaSopenharmony_ci return 1; 354c87c5fbaSopenharmony_ci } 355c87c5fbaSopenharmony_cifail: 356c87c5fbaSopenharmony_ci coap_delete_bin_const(*raw_packet); 357c87c5fbaSopenharmony_ci coap_delete_binary(scratch); 358c87c5fbaSopenharmony_ci 359c87c5fbaSopenharmony_ci *observe_key = NULL; 360c87c5fbaSopenharmony_ci memset(e_proto, 0, sizeof(*e_proto)); 361c87c5fbaSopenharmony_ci memset(e_listen_addr, 0, sizeof(*e_listen_addr)); 362c87c5fbaSopenharmony_ci memset(s_addr_info, 0, sizeof(*s_addr_info)); 363c87c5fbaSopenharmony_ci *raw_packet = NULL; 364c87c5fbaSopenharmony_ci return 0; 365c87c5fbaSopenharmony_ci} 366c87c5fbaSopenharmony_ci 367c87c5fbaSopenharmony_ci/* 368c87c5fbaSopenharmony_ci * write out active observe entry. 369c87c5fbaSopenharmony_ci */ 370c87c5fbaSopenharmony_cistatic int 371c87c5fbaSopenharmony_cicoap_op_observe_write(FILE *fp, coap_subscription_t *observe_key, 372c87c5fbaSopenharmony_ci coap_proto_t e_proto, coap_address_t e_listen_addr, 373c87c5fbaSopenharmony_ci coap_addr_tuple_t s_addr_info, 374c87c5fbaSopenharmony_ci coap_bin_const_t *raw_packet, coap_bin_const_t *oscore_info) { 375c87c5fbaSopenharmony_ci if (fwrite(&observe_key, sizeof(observe_key), 1, fp) != 1) 376c87c5fbaSopenharmony_ci goto fail; 377c87c5fbaSopenharmony_ci if (fwrite(&e_proto, sizeof(e_proto), 1, fp) != 1) 378c87c5fbaSopenharmony_ci goto fail; 379c87c5fbaSopenharmony_ci if (fwrite(&e_listen_addr, sizeof(e_listen_addr), 380c87c5fbaSopenharmony_ci 1, fp) != 1) 381c87c5fbaSopenharmony_ci goto fail; 382c87c5fbaSopenharmony_ci if (fwrite(&s_addr_info, sizeof(s_addr_info), 1, fp) != 1) 383c87c5fbaSopenharmony_ci goto fail; 384c87c5fbaSopenharmony_ci if (fwrite(&raw_packet->length, sizeof(raw_packet->length), 1, fp) != 1) 385c87c5fbaSopenharmony_ci goto fail; 386c87c5fbaSopenharmony_ci if (fwrite(raw_packet->s, raw_packet->length, 1, fp) != 1) 387c87c5fbaSopenharmony_ci goto fail; 388c87c5fbaSopenharmony_ci if (oscore_info) { 389c87c5fbaSopenharmony_ci if (fwrite(&oscore_info->length, sizeof(oscore_info->length), 1, fp) != 1) 390c87c5fbaSopenharmony_ci goto fail; 391c87c5fbaSopenharmony_ci if (fwrite(oscore_info->s, oscore_info->length, 1, fp) != 1) 392c87c5fbaSopenharmony_ci goto fail; 393c87c5fbaSopenharmony_ci } else { 394c87c5fbaSopenharmony_ci ssize_t not_defined = -1; 395c87c5fbaSopenharmony_ci 396c87c5fbaSopenharmony_ci if (fwrite(¬_defined, sizeof(not_defined), 1, fp) != 1) 397c87c5fbaSopenharmony_ci goto fail; 398c87c5fbaSopenharmony_ci } 399c87c5fbaSopenharmony_ci return 1; 400c87c5fbaSopenharmony_cifail: 401c87c5fbaSopenharmony_ci return 0; 402c87c5fbaSopenharmony_ci} 403c87c5fbaSopenharmony_ci 404c87c5fbaSopenharmony_ci/* 405c87c5fbaSopenharmony_ci * This should be called before coap_persist_track_funcs() to prevent 406c87c5fbaSopenharmony_ci * coap_op_observe_added() getting unnecessarily called. 407c87c5fbaSopenharmony_ci * It should be called after init_resources() and coap_op_resource_load_disk() 408c87c5fbaSopenharmony_ci * so that all the resources are in place. 409c87c5fbaSopenharmony_ci */ 410c87c5fbaSopenharmony_cistatic void 411c87c5fbaSopenharmony_cicoap_op_observe_load_disk(coap_context_t *ctx) { 412c87c5fbaSopenharmony_ci FILE *fp_orig = fopen((const char *)ctx->observe_save_file->s, "r"); 413c87c5fbaSopenharmony_ci FILE *fp_new = NULL; 414c87c5fbaSopenharmony_ci coap_subscription_t *observe_key = NULL; 415c87c5fbaSopenharmony_ci coap_proto_t e_proto; 416c87c5fbaSopenharmony_ci coap_address_t e_listen_addr; 417c87c5fbaSopenharmony_ci coap_addr_tuple_t s_addr_info; 418c87c5fbaSopenharmony_ci coap_bin_const_t *raw_packet = NULL; 419c87c5fbaSopenharmony_ci coap_bin_const_t *oscore_info = NULL; 420c87c5fbaSopenharmony_ci char *new = NULL; 421c87c5fbaSopenharmony_ci 422c87c5fbaSopenharmony_ci if (fp_orig == NULL) 423c87c5fbaSopenharmony_ci goto fail; 424c87c5fbaSopenharmony_ci 425c87c5fbaSopenharmony_ci new = coap_malloc_type(COAP_STRING, ctx->observe_save_file->length + 5); 426c87c5fbaSopenharmony_ci if (!new) 427c87c5fbaSopenharmony_ci goto fail; 428c87c5fbaSopenharmony_ci 429c87c5fbaSopenharmony_ci strcpy(new, (const char *)ctx->observe_save_file->s); 430c87c5fbaSopenharmony_ci strcat(new, ".tmp"); 431c87c5fbaSopenharmony_ci fp_new = fopen(new, "w+"); 432c87c5fbaSopenharmony_ci if (fp_new == NULL) 433c87c5fbaSopenharmony_ci goto fail; 434c87c5fbaSopenharmony_ci 435c87c5fbaSopenharmony_ci /* Go through and load oscore entry, updating key on the way */ 436c87c5fbaSopenharmony_ci while (1) { 437c87c5fbaSopenharmony_ci if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr, 438c87c5fbaSopenharmony_ci &s_addr_info, &raw_packet, &oscore_info)) 439c87c5fbaSopenharmony_ci break; 440c87c5fbaSopenharmony_ci coap_log_debug("persist: New session/observe being created\n"); 441c87c5fbaSopenharmony_ci observe_key = coap_persist_observe_add(ctx, e_proto, 442c87c5fbaSopenharmony_ci &e_listen_addr, 443c87c5fbaSopenharmony_ci &s_addr_info, 444c87c5fbaSopenharmony_ci raw_packet, 445c87c5fbaSopenharmony_ci oscore_info); 446c87c5fbaSopenharmony_ci if (observe_key) { 447c87c5fbaSopenharmony_ci if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr, 448c87c5fbaSopenharmony_ci s_addr_info, raw_packet, oscore_info)) 449c87c5fbaSopenharmony_ci goto fail; 450c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 451c87c5fbaSopenharmony_ci raw_packet = NULL; 452c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 453c87c5fbaSopenharmony_ci oscore_info = NULL; 454c87c5fbaSopenharmony_ci } 455c87c5fbaSopenharmony_ci } 456c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 457c87c5fbaSopenharmony_ci raw_packet = NULL; 458c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 459c87c5fbaSopenharmony_ci oscore_info = NULL; 460c87c5fbaSopenharmony_ci 461c87c5fbaSopenharmony_ci if (fflush(fp_new) == EOF) 462c87c5fbaSopenharmony_ci goto fail; 463c87c5fbaSopenharmony_ci fclose(fp_new); 464c87c5fbaSopenharmony_ci fclose(fp_orig); 465c87c5fbaSopenharmony_ci /* Either old or new is in place */ 466c87c5fbaSopenharmony_ci (void)rename(new, (const char *)ctx->observe_save_file->s); 467c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 468c87c5fbaSopenharmony_ci return; 469c87c5fbaSopenharmony_ci 470c87c5fbaSopenharmony_cifail: 471c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 472c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 473c87c5fbaSopenharmony_ci if (fp_new) 474c87c5fbaSopenharmony_ci fclose(fp_new); 475c87c5fbaSopenharmony_ci if (fp_orig) 476c87c5fbaSopenharmony_ci fclose(fp_orig); 477c87c5fbaSopenharmony_ci if (new) { 478c87c5fbaSopenharmony_ci (void)remove(new); 479c87c5fbaSopenharmony_ci } 480c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 481c87c5fbaSopenharmony_ci return; 482c87c5fbaSopenharmony_ci} 483c87c5fbaSopenharmony_ci 484c87c5fbaSopenharmony_ci/* 485c87c5fbaSopenharmony_ci * client has registered a new observe subscription request. 486c87c5fbaSopenharmony_ci */ 487c87c5fbaSopenharmony_cistatic int 488c87c5fbaSopenharmony_cicoap_op_observe_added(coap_session_t *session, 489c87c5fbaSopenharmony_ci coap_subscription_t *a_observe_key, 490c87c5fbaSopenharmony_ci coap_proto_t a_e_proto, coap_address_t *a_e_listen_addr, 491c87c5fbaSopenharmony_ci coap_addr_tuple_t *a_s_addr_info, 492c87c5fbaSopenharmony_ci coap_bin_const_t *a_raw_packet, 493c87c5fbaSopenharmony_ci coap_bin_const_t *a_oscore_info, void *user_data) { 494c87c5fbaSopenharmony_ci FILE *fp_orig = fopen((const char *)session->context->observe_save_file->s, 495c87c5fbaSopenharmony_ci "r"); 496c87c5fbaSopenharmony_ci FILE *fp_new = NULL; 497c87c5fbaSopenharmony_ci coap_subscription_t *observe_key = NULL; 498c87c5fbaSopenharmony_ci coap_proto_t e_proto; 499c87c5fbaSopenharmony_ci coap_address_t e_listen_addr; 500c87c5fbaSopenharmony_ci coap_addr_tuple_t s_addr_info; 501c87c5fbaSopenharmony_ci coap_bin_const_t *raw_packet = NULL; 502c87c5fbaSopenharmony_ci coap_bin_const_t *oscore_info = NULL; 503c87c5fbaSopenharmony_ci char *new = NULL; 504c87c5fbaSopenharmony_ci 505c87c5fbaSopenharmony_ci (void)user_data; 506c87c5fbaSopenharmony_ci 507c87c5fbaSopenharmony_ci new = coap_malloc_type(COAP_STRING, 508c87c5fbaSopenharmony_ci session->context->observe_save_file->length + 5); 509c87c5fbaSopenharmony_ci if (!new) 510c87c5fbaSopenharmony_ci goto fail; 511c87c5fbaSopenharmony_ci 512c87c5fbaSopenharmony_ci strcpy(new, (const char *)session->context->observe_save_file->s); 513c87c5fbaSopenharmony_ci strcat(new, ".tmp"); 514c87c5fbaSopenharmony_ci fp_new = fopen(new, "w+"); 515c87c5fbaSopenharmony_ci if (fp_new == NULL) 516c87c5fbaSopenharmony_ci goto fail; 517c87c5fbaSopenharmony_ci 518c87c5fbaSopenharmony_ci /* Go through and delete observe entry if it exists */ 519c87c5fbaSopenharmony_ci while (fp_orig) { 520c87c5fbaSopenharmony_ci if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr, 521c87c5fbaSopenharmony_ci &s_addr_info, &raw_packet, &oscore_info)) 522c87c5fbaSopenharmony_ci break; 523c87c5fbaSopenharmony_ci if (observe_key != a_observe_key) { 524c87c5fbaSopenharmony_ci if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr, 525c87c5fbaSopenharmony_ci s_addr_info, raw_packet, oscore_info)) 526c87c5fbaSopenharmony_ci goto fail; 527c87c5fbaSopenharmony_ci } 528c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 529c87c5fbaSopenharmony_ci raw_packet = NULL; 530c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 531c87c5fbaSopenharmony_ci oscore_info = NULL; 532c87c5fbaSopenharmony_ci } 533c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 534c87c5fbaSopenharmony_ci raw_packet = NULL; 535c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 536c87c5fbaSopenharmony_ci oscore_info = NULL; 537c87c5fbaSopenharmony_ci 538c87c5fbaSopenharmony_ci /* Add in new entry to the end */ 539c87c5fbaSopenharmony_ci if (!coap_op_observe_write(fp_new, a_observe_key, a_e_proto, *a_e_listen_addr, 540c87c5fbaSopenharmony_ci *a_s_addr_info, a_raw_packet, a_oscore_info)) 541c87c5fbaSopenharmony_ci goto fail; 542c87c5fbaSopenharmony_ci 543c87c5fbaSopenharmony_ci if (fflush(fp_new) == EOF) 544c87c5fbaSopenharmony_ci goto fail; 545c87c5fbaSopenharmony_ci fclose(fp_new); 546c87c5fbaSopenharmony_ci if (fp_orig) 547c87c5fbaSopenharmony_ci fclose(fp_orig); 548c87c5fbaSopenharmony_ci /* Either old or new is in place */ 549c87c5fbaSopenharmony_ci (void)rename(new, (const char *)session->context->observe_save_file->s); 550c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 551c87c5fbaSopenharmony_ci return 1; 552c87c5fbaSopenharmony_ci 553c87c5fbaSopenharmony_cifail: 554c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 555c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 556c87c5fbaSopenharmony_ci if (fp_new) 557c87c5fbaSopenharmony_ci fclose(fp_new); 558c87c5fbaSopenharmony_ci if (fp_orig) 559c87c5fbaSopenharmony_ci fclose(fp_orig); 560c87c5fbaSopenharmony_ci if (new) { 561c87c5fbaSopenharmony_ci (void)remove(new); 562c87c5fbaSopenharmony_ci } 563c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 564c87c5fbaSopenharmony_ci return 0; 565c87c5fbaSopenharmony_ci} 566c87c5fbaSopenharmony_ci 567c87c5fbaSopenharmony_ci/* 568c87c5fbaSopenharmony_ci * client has de-registered a observe subscription request. 569c87c5fbaSopenharmony_ci */ 570c87c5fbaSopenharmony_cistatic int 571c87c5fbaSopenharmony_cicoap_op_observe_deleted(coap_session_t *session, 572c87c5fbaSopenharmony_ci coap_subscription_t *d_observe_key, 573c87c5fbaSopenharmony_ci void *user_data) { 574c87c5fbaSopenharmony_ci FILE *fp_orig = fopen((const char *)session->context->observe_save_file->s, 575c87c5fbaSopenharmony_ci "r"); 576c87c5fbaSopenharmony_ci FILE *fp_new = NULL; 577c87c5fbaSopenharmony_ci coap_subscription_t *observe_key = NULL; 578c87c5fbaSopenharmony_ci coap_proto_t e_proto; 579c87c5fbaSopenharmony_ci coap_address_t e_listen_addr; 580c87c5fbaSopenharmony_ci coap_addr_tuple_t s_addr_info; 581c87c5fbaSopenharmony_ci coap_bin_const_t *raw_packet = NULL; 582c87c5fbaSopenharmony_ci coap_bin_const_t *oscore_info = NULL; 583c87c5fbaSopenharmony_ci char *new = NULL; 584c87c5fbaSopenharmony_ci 585c87c5fbaSopenharmony_ci (void)user_data; 586c87c5fbaSopenharmony_ci 587c87c5fbaSopenharmony_ci if (fp_orig == NULL) 588c87c5fbaSopenharmony_ci goto fail; 589c87c5fbaSopenharmony_ci new = coap_malloc_type(COAP_STRING, 590c87c5fbaSopenharmony_ci session->context->observe_save_file->length + 5); 591c87c5fbaSopenharmony_ci if (!new) 592c87c5fbaSopenharmony_ci goto fail; 593c87c5fbaSopenharmony_ci 594c87c5fbaSopenharmony_ci strcpy(new, (const char *)session->context->observe_save_file->s); 595c87c5fbaSopenharmony_ci strcat(new, ".tmp"); 596c87c5fbaSopenharmony_ci fp_new = fopen(new, "w+"); 597c87c5fbaSopenharmony_ci if (fp_new == NULL) 598c87c5fbaSopenharmony_ci goto fail; 599c87c5fbaSopenharmony_ci 600c87c5fbaSopenharmony_ci /* Go through and locate observe entry to delete and not copy it across */ 601c87c5fbaSopenharmony_ci while (1) { 602c87c5fbaSopenharmony_ci if (!coap_op_observe_read(fp_orig, &observe_key, &e_proto, &e_listen_addr, 603c87c5fbaSopenharmony_ci &s_addr_info, &raw_packet, &oscore_info)) 604c87c5fbaSopenharmony_ci break; 605c87c5fbaSopenharmony_ci if (observe_key != d_observe_key) { 606c87c5fbaSopenharmony_ci if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr, 607c87c5fbaSopenharmony_ci s_addr_info, (coap_bin_const_t *)raw_packet, 608c87c5fbaSopenharmony_ci (coap_bin_const_t *)oscore_info)) 609c87c5fbaSopenharmony_ci goto fail; 610c87c5fbaSopenharmony_ci } 611c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 612c87c5fbaSopenharmony_ci raw_packet = NULL; 613c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 614c87c5fbaSopenharmony_ci oscore_info = NULL; 615c87c5fbaSopenharmony_ci } 616c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 617c87c5fbaSopenharmony_ci raw_packet = NULL; 618c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 619c87c5fbaSopenharmony_ci oscore_info = NULL; 620c87c5fbaSopenharmony_ci 621c87c5fbaSopenharmony_ci if (fflush(fp_new) == EOF) 622c87c5fbaSopenharmony_ci goto fail; 623c87c5fbaSopenharmony_ci fclose(fp_new); 624c87c5fbaSopenharmony_ci fclose(fp_orig); 625c87c5fbaSopenharmony_ci /* Either old or new is in place */ 626c87c5fbaSopenharmony_ci (void)rename(new, (const char *)session->context->observe_save_file->s); 627c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 628c87c5fbaSopenharmony_ci return 1; 629c87c5fbaSopenharmony_ci 630c87c5fbaSopenharmony_cifail: 631c87c5fbaSopenharmony_ci coap_delete_bin_const(raw_packet); 632c87c5fbaSopenharmony_ci coap_delete_bin_const(oscore_info); 633c87c5fbaSopenharmony_ci if (fp_new) 634c87c5fbaSopenharmony_ci fclose(fp_new); 635c87c5fbaSopenharmony_ci if (fp_orig) 636c87c5fbaSopenharmony_ci fclose(fp_orig); 637c87c5fbaSopenharmony_ci if (new) { 638c87c5fbaSopenharmony_ci (void)remove(new); 639c87c5fbaSopenharmony_ci } 640c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 641c87c5fbaSopenharmony_ci return 0; 642c87c5fbaSopenharmony_ci} 643c87c5fbaSopenharmony_ci 644c87c5fbaSopenharmony_ci/* 645c87c5fbaSopenharmony_ci * This should be called before coap_persist_track_funcs() to prevent 646c87c5fbaSopenharmony_ci * coap_op_obs_cnt_track_observe() getting unnecessarily called. 647c87c5fbaSopenharmony_ci * Should be called after coap_op_dyn_resource_load_disk() to make sure that 648c87c5fbaSopenharmony_ci * all the resources are in the right place. 649c87c5fbaSopenharmony_ci */ 650c87c5fbaSopenharmony_cistatic void 651c87c5fbaSopenharmony_cicoap_op_obs_cnt_load_disk(coap_context_t *context) { 652c87c5fbaSopenharmony_ci FILE *fp = fopen((const char *)context->obs_cnt_save_file->s, "r"); 653c87c5fbaSopenharmony_ci char buf[1500]; 654c87c5fbaSopenharmony_ci 655c87c5fbaSopenharmony_ci if (fp == NULL) 656c87c5fbaSopenharmony_ci return; 657c87c5fbaSopenharmony_ci 658c87c5fbaSopenharmony_ci while (fgets(buf, sizeof(buf), fp) != NULL) { 659c87c5fbaSopenharmony_ci char *cp = strchr(buf, ' '); 660c87c5fbaSopenharmony_ci coap_str_const_t resource_key; 661c87c5fbaSopenharmony_ci uint32_t observe_num; 662c87c5fbaSopenharmony_ci coap_resource_t *r; 663c87c5fbaSopenharmony_ci 664c87c5fbaSopenharmony_ci if (!cp) 665c87c5fbaSopenharmony_ci break; 666c87c5fbaSopenharmony_ci 667c87c5fbaSopenharmony_ci *cp = '\000'; 668c87c5fbaSopenharmony_ci cp++; 669c87c5fbaSopenharmony_ci observe_num = atoi(cp); 670c87c5fbaSopenharmony_ci /* 671c87c5fbaSopenharmony_ci * Need to assume 0 .. (context->observe_save_freq-1) have in addition 672c87c5fbaSopenharmony_ci * been sent so need to round up to latest possible send value 673c87c5fbaSopenharmony_ci */ 674c87c5fbaSopenharmony_ci observe_num = ((observe_num + context->observe_save_freq) / 675c87c5fbaSopenharmony_ci context->observe_save_freq) * 676c87c5fbaSopenharmony_ci context->observe_save_freq - 1; 677c87c5fbaSopenharmony_ci resource_key.s = (uint8_t *)buf; 678c87c5fbaSopenharmony_ci resource_key.length = strlen(buf); 679c87c5fbaSopenharmony_ci r = coap_get_resource_from_uri_path(context, &resource_key); 680c87c5fbaSopenharmony_ci if (r) { 681c87c5fbaSopenharmony_ci coap_log_debug("persist: Initial observe number being updated\n"); 682c87c5fbaSopenharmony_ci coap_persist_set_observe_num(r, observe_num); 683c87c5fbaSopenharmony_ci } 684c87c5fbaSopenharmony_ci } 685c87c5fbaSopenharmony_ci fclose(fp); 686c87c5fbaSopenharmony_ci} 687c87c5fbaSopenharmony_ci 688c87c5fbaSopenharmony_ci/* 689c87c5fbaSopenharmony_ci * Called when the observe value of a resource has been changed, but limited 690c87c5fbaSopenharmony_ci * to be called every context->context->observe_save_freq to reduce update 691c87c5fbaSopenharmony_ci * overheads. 692c87c5fbaSopenharmony_ci */ 693c87c5fbaSopenharmony_cistatic int 694c87c5fbaSopenharmony_cicoap_op_obs_cnt_track_observe(coap_context_t *context, 695c87c5fbaSopenharmony_ci coap_str_const_t *resource_name, 696c87c5fbaSopenharmony_ci uint32_t n_observe_num, 697c87c5fbaSopenharmony_ci void *user_data) { 698c87c5fbaSopenharmony_ci FILE *fp_orig = fopen((const char *)context->obs_cnt_save_file->s, "r"); 699c87c5fbaSopenharmony_ci FILE *fp_new = NULL; 700c87c5fbaSopenharmony_ci char buf[1500]; 701c87c5fbaSopenharmony_ci char *new = NULL; 702c87c5fbaSopenharmony_ci 703c87c5fbaSopenharmony_ci (void)user_data; 704c87c5fbaSopenharmony_ci 705c87c5fbaSopenharmony_ci new = coap_malloc_type(COAP_STRING, context->obs_cnt_save_file->length + 5); 706c87c5fbaSopenharmony_ci if (!new) 707c87c5fbaSopenharmony_ci goto fail; 708c87c5fbaSopenharmony_ci 709c87c5fbaSopenharmony_ci strcpy(new, (const char *)context->obs_cnt_save_file->s); 710c87c5fbaSopenharmony_ci strcat(new, ".tmp"); 711c87c5fbaSopenharmony_ci fp_new = fopen(new, "w+"); 712c87c5fbaSopenharmony_ci if (fp_new == NULL) 713c87c5fbaSopenharmony_ci goto fail; 714c87c5fbaSopenharmony_ci 715c87c5fbaSopenharmony_ci /* Go through and locate resource entry to update */ 716c87c5fbaSopenharmony_ci while (fp_orig && fgets(buf, sizeof(buf), fp_orig) != NULL) { 717c87c5fbaSopenharmony_ci char *cp = strchr(buf, ' '); 718c87c5fbaSopenharmony_ci uint32_t observe_num; 719c87c5fbaSopenharmony_ci coap_bin_const_t resource_key; 720c87c5fbaSopenharmony_ci 721c87c5fbaSopenharmony_ci if (!cp) 722c87c5fbaSopenharmony_ci break; 723c87c5fbaSopenharmony_ci 724c87c5fbaSopenharmony_ci *cp = '\000'; 725c87c5fbaSopenharmony_ci cp++; 726c87c5fbaSopenharmony_ci observe_num = atoi(cp); 727c87c5fbaSopenharmony_ci resource_key.s = (uint8_t *)buf; 728c87c5fbaSopenharmony_ci resource_key.length = strlen(buf); 729c87c5fbaSopenharmony_ci if (!coap_binary_equal(resource_name, &resource_key)) { 730c87c5fbaSopenharmony_ci if (fprintf(fp_new, "%s %u\n", resource_key.s, observe_num) < 0) 731c87c5fbaSopenharmony_ci goto fail; 732c87c5fbaSopenharmony_ci } 733c87c5fbaSopenharmony_ci } 734c87c5fbaSopenharmony_ci if (fprintf(fp_new, "%s %u\n", resource_name->s, n_observe_num) < 0) 735c87c5fbaSopenharmony_ci goto fail; 736c87c5fbaSopenharmony_ci if (fflush(fp_new) == EOF) 737c87c5fbaSopenharmony_ci goto fail; 738c87c5fbaSopenharmony_ci fclose(fp_new); 739c87c5fbaSopenharmony_ci if (fp_orig) 740c87c5fbaSopenharmony_ci fclose(fp_orig); 741c87c5fbaSopenharmony_ci /* Either old or new is in place */ 742c87c5fbaSopenharmony_ci (void)rename(new, (const char *)context->obs_cnt_save_file->s); 743c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 744c87c5fbaSopenharmony_ci return 1; 745c87c5fbaSopenharmony_ci 746c87c5fbaSopenharmony_cifail: 747c87c5fbaSopenharmony_ci if (fp_new) 748c87c5fbaSopenharmony_ci fclose(fp_new); 749c87c5fbaSopenharmony_ci if (fp_orig) 750c87c5fbaSopenharmony_ci fclose(fp_orig); 751c87c5fbaSopenharmony_ci if (new) { 752c87c5fbaSopenharmony_ci (void)remove(new); 753c87c5fbaSopenharmony_ci } 754c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 755c87c5fbaSopenharmony_ci return 0; 756c87c5fbaSopenharmony_ci} 757c87c5fbaSopenharmony_ci 758c87c5fbaSopenharmony_ci/* 759c87c5fbaSopenharmony_ci * Called when a resource has been deleted. 760c87c5fbaSopenharmony_ci */ 761c87c5fbaSopenharmony_cistatic int 762c87c5fbaSopenharmony_cicoap_op_obs_cnt_deleted(coap_context_t *context, 763c87c5fbaSopenharmony_ci coap_str_const_t *resource_name) { 764c87c5fbaSopenharmony_ci FILE *fp_orig = fopen((const char *)context->obs_cnt_save_file->s, "r"); 765c87c5fbaSopenharmony_ci FILE *fp_new = NULL; 766c87c5fbaSopenharmony_ci char buf[1500]; 767c87c5fbaSopenharmony_ci char *new = NULL; 768c87c5fbaSopenharmony_ci 769c87c5fbaSopenharmony_ci if (fp_orig == NULL) 770c87c5fbaSopenharmony_ci goto fail; 771c87c5fbaSopenharmony_ci new = coap_malloc_type(COAP_STRING, context->obs_cnt_save_file->length + 5); 772c87c5fbaSopenharmony_ci if (!new) 773c87c5fbaSopenharmony_ci goto fail; 774c87c5fbaSopenharmony_ci 775c87c5fbaSopenharmony_ci strcpy(new, (const char *)context->obs_cnt_save_file->s); 776c87c5fbaSopenharmony_ci strcat(new, ".tmp"); 777c87c5fbaSopenharmony_ci fp_new = fopen(new, "w+"); 778c87c5fbaSopenharmony_ci if (fp_new == NULL) 779c87c5fbaSopenharmony_ci goto fail; 780c87c5fbaSopenharmony_ci 781c87c5fbaSopenharmony_ci /* Go through and locate resource entry to delete */ 782c87c5fbaSopenharmony_ci while (fgets(buf, sizeof(buf), fp_orig) != NULL) { 783c87c5fbaSopenharmony_ci char *cp = strchr(buf, ' '); 784c87c5fbaSopenharmony_ci uint32_t observe_num; 785c87c5fbaSopenharmony_ci coap_bin_const_t resource_key; 786c87c5fbaSopenharmony_ci 787c87c5fbaSopenharmony_ci if (!cp) 788c87c5fbaSopenharmony_ci break; 789c87c5fbaSopenharmony_ci 790c87c5fbaSopenharmony_ci *cp = '\000'; 791c87c5fbaSopenharmony_ci cp++; 792c87c5fbaSopenharmony_ci observe_num = atoi(cp); 793c87c5fbaSopenharmony_ci resource_key.s = (uint8_t *)buf; 794c87c5fbaSopenharmony_ci resource_key.length = strlen(buf); 795c87c5fbaSopenharmony_ci if (!coap_binary_equal(resource_name, &resource_key)) { 796c87c5fbaSopenharmony_ci if (fprintf(fp_new, "%s %u\n", resource_key.s, observe_num) < 0) 797c87c5fbaSopenharmony_ci goto fail; 798c87c5fbaSopenharmony_ci } 799c87c5fbaSopenharmony_ci } 800c87c5fbaSopenharmony_ci if (fflush(fp_new) == EOF) 801c87c5fbaSopenharmony_ci goto fail; 802c87c5fbaSopenharmony_ci fclose(fp_new); 803c87c5fbaSopenharmony_ci fclose(fp_orig); 804c87c5fbaSopenharmony_ci /* Either old or new is in place */ 805c87c5fbaSopenharmony_ci (void)rename(new, (const char *)context->obs_cnt_save_file->s); 806c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 807c87c5fbaSopenharmony_ci return 1; 808c87c5fbaSopenharmony_ci 809c87c5fbaSopenharmony_cifail: 810c87c5fbaSopenharmony_ci if (fp_new) 811c87c5fbaSopenharmony_ci fclose(fp_new); 812c87c5fbaSopenharmony_ci if (fp_orig) 813c87c5fbaSopenharmony_ci fclose(fp_orig); 814c87c5fbaSopenharmony_ci if (new) { 815c87c5fbaSopenharmony_ci (void)remove(new); 816c87c5fbaSopenharmony_ci } 817c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 818c87c5fbaSopenharmony_ci return 0; 819c87c5fbaSopenharmony_ci} 820c87c5fbaSopenharmony_ci 821c87c5fbaSopenharmony_ci/* 822c87c5fbaSopenharmony_ci * read in dynamic resource entry, allocating name & raw_packet 823c87c5fbaSopenharmony_ci * which need to be freed off by caller. 824c87c5fbaSopenharmony_ci */ 825c87c5fbaSopenharmony_cistatic int 826c87c5fbaSopenharmony_cicoap_op_dyn_resource_read(FILE *fp, coap_proto_t *e_proto, 827c87c5fbaSopenharmony_ci coap_string_t **name, 828c87c5fbaSopenharmony_ci coap_binary_t **raw_packet) { 829c87c5fbaSopenharmony_ci ssize_t size; 830c87c5fbaSopenharmony_ci 831c87c5fbaSopenharmony_ci *name = NULL; 832c87c5fbaSopenharmony_ci *raw_packet = NULL; 833c87c5fbaSopenharmony_ci 834c87c5fbaSopenharmony_ci if (fread(e_proto, sizeof(*e_proto), 1, fp) == 1) { 835c87c5fbaSopenharmony_ci /* New record 'proto len resource_name len raw_packet' */ 836c87c5fbaSopenharmony_ci if (fread(&size, sizeof(size), 1, fp) != 1) 837c87c5fbaSopenharmony_ci goto fail; 838c87c5fbaSopenharmony_ci if (size < 0 || size > 0x10000) 839c87c5fbaSopenharmony_ci goto fail; 840c87c5fbaSopenharmony_ci *name = coap_new_string(size); 841c87c5fbaSopenharmony_ci if (!(*name)) 842c87c5fbaSopenharmony_ci goto fail; 843c87c5fbaSopenharmony_ci if (fread((*name)->s, size, 1, fp) != 1) 844c87c5fbaSopenharmony_ci goto fail; 845c87c5fbaSopenharmony_ci if (fread(&size, sizeof(size), 1, fp) != 1) 846c87c5fbaSopenharmony_ci goto fail; 847c87c5fbaSopenharmony_ci if (size < 0 || size > 0x10000) 848c87c5fbaSopenharmony_ci goto fail; 849c87c5fbaSopenharmony_ci *raw_packet = coap_new_binary(size); 850c87c5fbaSopenharmony_ci if (!(*raw_packet)) 851c87c5fbaSopenharmony_ci goto fail; 852c87c5fbaSopenharmony_ci if (fread((*raw_packet)->s, size, 1, fp) != 1) 853c87c5fbaSopenharmony_ci goto fail; 854c87c5fbaSopenharmony_ci return 1; 855c87c5fbaSopenharmony_ci } 856c87c5fbaSopenharmony_cifail: 857c87c5fbaSopenharmony_ci return 0; 858c87c5fbaSopenharmony_ci} 859c87c5fbaSopenharmony_ci 860c87c5fbaSopenharmony_ci/* 861c87c5fbaSopenharmony_ci * write out dynamic resource entry. 862c87c5fbaSopenharmony_ci */ 863c87c5fbaSopenharmony_cistatic int 864c87c5fbaSopenharmony_cicoap_op_dyn_resource_write(FILE *fp, coap_proto_t e_proto, 865c87c5fbaSopenharmony_ci coap_str_const_t *name, 866c87c5fbaSopenharmony_ci coap_bin_const_t *raw_packet) { 867c87c5fbaSopenharmony_ci if (fwrite(&e_proto, sizeof(e_proto), 1, fp) != 1) 868c87c5fbaSopenharmony_ci goto fail; 869c87c5fbaSopenharmony_ci if (fwrite(&name->length, sizeof(name->length), 1, fp) != 1) 870c87c5fbaSopenharmony_ci goto fail; 871c87c5fbaSopenharmony_ci if (fwrite(name->s, name->length, 1, fp) != 1) 872c87c5fbaSopenharmony_ci goto fail; 873c87c5fbaSopenharmony_ci if (fwrite(&raw_packet->length, sizeof(raw_packet->length), 1, fp) != 1) 874c87c5fbaSopenharmony_ci goto fail; 875c87c5fbaSopenharmony_ci if (fwrite(raw_packet->s, raw_packet->length, 1, fp) != 1) 876c87c5fbaSopenharmony_ci goto fail; 877c87c5fbaSopenharmony_ci return 1; 878c87c5fbaSopenharmony_cifail: 879c87c5fbaSopenharmony_ci return 0; 880c87c5fbaSopenharmony_ci} 881c87c5fbaSopenharmony_ci 882c87c5fbaSopenharmony_ci/* 883c87c5fbaSopenharmony_ci * This should be called before coap_persist_track_funcs() to prevent 884c87c5fbaSopenharmony_ci * coap_op_dyn_resource_added() getting unnecessarily called. 885c87c5fbaSopenharmony_ci * 886c87c5fbaSopenharmony_ci * Each record 'proto len resource_name len raw_packet' 887c87c5fbaSopenharmony_ci */ 888c87c5fbaSopenharmony_cistatic void 889c87c5fbaSopenharmony_cicoap_op_dyn_resource_load_disk(coap_context_t *ctx) { 890c87c5fbaSopenharmony_ci FILE *fp_orig = NULL; 891c87c5fbaSopenharmony_ci coap_proto_t e_proto; 892c87c5fbaSopenharmony_ci coap_string_t *name = NULL; 893c87c5fbaSopenharmony_ci coap_binary_t *raw_packet = NULL; 894c87c5fbaSopenharmony_ci coap_resource_t *r; 895c87c5fbaSopenharmony_ci coap_session_t *session = NULL; 896c87c5fbaSopenharmony_ci coap_pdu_t *request = NULL; 897c87c5fbaSopenharmony_ci coap_pdu_t *response = NULL; 898c87c5fbaSopenharmony_ci coap_string_t *query = NULL; 899c87c5fbaSopenharmony_ci 900c87c5fbaSopenharmony_ci if (!ctx->unknown_resource) 901c87c5fbaSopenharmony_ci return; 902c87c5fbaSopenharmony_ci 903c87c5fbaSopenharmony_ci fp_orig = fopen((const char *)ctx->dyn_resource_save_file->s, "r"); 904c87c5fbaSopenharmony_ci if (fp_orig == NULL) 905c87c5fbaSopenharmony_ci return; 906c87c5fbaSopenharmony_ci session = (coap_session_t *)coap_malloc_type(COAP_SESSION, 907c87c5fbaSopenharmony_ci sizeof(coap_session_t)); 908c87c5fbaSopenharmony_ci if (!session) 909c87c5fbaSopenharmony_ci goto fail; 910c87c5fbaSopenharmony_ci memset(session, 0, sizeof(coap_session_t)); 911c87c5fbaSopenharmony_ci session->context = ctx; 912c87c5fbaSopenharmony_ci 913c87c5fbaSopenharmony_ci /* Go through and create each dynamic resource if it does not exist*/ 914c87c5fbaSopenharmony_ci while (1) { 915c87c5fbaSopenharmony_ci if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet)) 916c87c5fbaSopenharmony_ci break; 917c87c5fbaSopenharmony_ci r = coap_get_resource_from_uri_path(ctx, (coap_str_const_t *)name); 918c87c5fbaSopenharmony_ci if (!r) { 919c87c5fbaSopenharmony_ci /* Create the new resource using the application logic */ 920c87c5fbaSopenharmony_ci 921c87c5fbaSopenharmony_ci coap_log_debug("persist: dynamic resource being re-created\n"); 922c87c5fbaSopenharmony_ci /* 923c87c5fbaSopenharmony_ci * Need max space incase PDU is updated with updated token, 924c87c5fbaSopenharmony_ci * huge size etc. 925c87c5fbaSopenharmony_ci * */ 926c87c5fbaSopenharmony_ci request = coap_pdu_init(0, 0, 0, 0); 927c87c5fbaSopenharmony_ci if (!request) 928c87c5fbaSopenharmony_ci goto fail; 929c87c5fbaSopenharmony_ci 930c87c5fbaSopenharmony_ci session->proto = e_proto; 931c87c5fbaSopenharmony_ci if (!coap_pdu_parse(session->proto, raw_packet->s, 932c87c5fbaSopenharmony_ci raw_packet->length, request)) { 933c87c5fbaSopenharmony_ci goto fail; 934c87c5fbaSopenharmony_ci } 935c87c5fbaSopenharmony_ci if (!ctx->unknown_resource->handler[request->code-1]) 936c87c5fbaSopenharmony_ci goto fail; 937c87c5fbaSopenharmony_ci response = coap_pdu_init(0, 0, 0, 0); 938c87c5fbaSopenharmony_ci if (!response) 939c87c5fbaSopenharmony_ci goto fail; 940c87c5fbaSopenharmony_ci query = coap_get_query(request); 941c87c5fbaSopenharmony_ci /* Call the application handler to set up this dynamic resource */ 942c87c5fbaSopenharmony_ci ctx->unknown_resource->handler[request->code-1](ctx->unknown_resource, 943c87c5fbaSopenharmony_ci session, request, 944c87c5fbaSopenharmony_ci query, response); 945c87c5fbaSopenharmony_ci coap_delete_string(query); 946c87c5fbaSopenharmony_ci query = NULL; 947c87c5fbaSopenharmony_ci coap_delete_pdu(request); 948c87c5fbaSopenharmony_ci request = NULL; 949c87c5fbaSopenharmony_ci coap_delete_pdu(response); 950c87c5fbaSopenharmony_ci response = NULL; 951c87c5fbaSopenharmony_ci } 952c87c5fbaSopenharmony_ci coap_delete_string(name); 953c87c5fbaSopenharmony_ci coap_delete_binary(raw_packet); 954c87c5fbaSopenharmony_ci } 955c87c5fbaSopenharmony_cifail: 956c87c5fbaSopenharmony_ci coap_delete_string(name); 957c87c5fbaSopenharmony_ci coap_delete_binary(raw_packet); 958c87c5fbaSopenharmony_ci coap_delete_string(query); 959c87c5fbaSopenharmony_ci coap_delete_pdu(request); 960c87c5fbaSopenharmony_ci coap_delete_pdu(response); 961c87c5fbaSopenharmony_ci fclose(fp_orig); 962c87c5fbaSopenharmony_ci coap_free_type(COAP_SESSION, session); 963c87c5fbaSopenharmony_ci} 964c87c5fbaSopenharmony_ci 965c87c5fbaSopenharmony_ci/* 966c87c5fbaSopenharmony_ci * Server has set up a new dynamic resource agains a request for an unknown 967c87c5fbaSopenharmony_ci * resource. 968c87c5fbaSopenharmony_ci */ 969c87c5fbaSopenharmony_cistatic int 970c87c5fbaSopenharmony_cicoap_op_dyn_resource_added(coap_session_t *session, 971c87c5fbaSopenharmony_ci coap_str_const_t *resource_name, 972c87c5fbaSopenharmony_ci coap_bin_const_t *packet, 973c87c5fbaSopenharmony_ci void *user_data) { 974c87c5fbaSopenharmony_ci FILE *fp_orig; 975c87c5fbaSopenharmony_ci FILE *fp_new = NULL; 976c87c5fbaSopenharmony_ci char *new = NULL; 977c87c5fbaSopenharmony_ci coap_context_t *context = session->context; 978c87c5fbaSopenharmony_ci coap_string_t *name = NULL; 979c87c5fbaSopenharmony_ci coap_binary_t *raw_packet = NULL; 980c87c5fbaSopenharmony_ci coap_proto_t e_proto; 981c87c5fbaSopenharmony_ci 982c87c5fbaSopenharmony_ci (void)user_data; 983c87c5fbaSopenharmony_ci 984c87c5fbaSopenharmony_ci fp_orig = fopen((const char *)context->dyn_resource_save_file->s, "a"); 985c87c5fbaSopenharmony_ci if (fp_orig == NULL) 986c87c5fbaSopenharmony_ci return 0; 987c87c5fbaSopenharmony_ci 988c87c5fbaSopenharmony_ci new = coap_malloc_type(COAP_STRING, 989c87c5fbaSopenharmony_ci context->dyn_resource_save_file->length + 5); 990c87c5fbaSopenharmony_ci if (!new) 991c87c5fbaSopenharmony_ci goto fail; 992c87c5fbaSopenharmony_ci 993c87c5fbaSopenharmony_ci strcpy(new, (const char *)context->dyn_resource_save_file->s); 994c87c5fbaSopenharmony_ci strcat(new, ".tmp"); 995c87c5fbaSopenharmony_ci fp_new = fopen(new, "w+"); 996c87c5fbaSopenharmony_ci if (fp_new == NULL) 997c87c5fbaSopenharmony_ci goto fail; 998c87c5fbaSopenharmony_ci 999c87c5fbaSopenharmony_ci /* Go through and locate duplicate resource to delete */ 1000c87c5fbaSopenharmony_ci while (1) { 1001c87c5fbaSopenharmony_ci if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet)) 1002c87c5fbaSopenharmony_ci break; 1003c87c5fbaSopenharmony_ci if (!coap_string_equal(resource_name, name)) { 1004c87c5fbaSopenharmony_ci /* Copy across non-matching entry */ 1005c87c5fbaSopenharmony_ci if (!coap_op_dyn_resource_write(fp_new, e_proto, (coap_str_const_t *)name, 1006c87c5fbaSopenharmony_ci (coap_bin_const_t *)raw_packet)) 1007c87c5fbaSopenharmony_ci break; 1008c87c5fbaSopenharmony_ci } 1009c87c5fbaSopenharmony_ci coap_delete_string(name); 1010c87c5fbaSopenharmony_ci name = NULL; 1011c87c5fbaSopenharmony_ci coap_delete_binary(raw_packet); 1012c87c5fbaSopenharmony_ci raw_packet = NULL; 1013c87c5fbaSopenharmony_ci } 1014c87c5fbaSopenharmony_ci coap_delete_string(name); 1015c87c5fbaSopenharmony_ci coap_delete_binary(raw_packet); 1016c87c5fbaSopenharmony_ci /* Add new entry to the end */ 1017c87c5fbaSopenharmony_ci if (!coap_op_dyn_resource_write(fp_new, session->proto, 1018c87c5fbaSopenharmony_ci resource_name, packet)) 1019c87c5fbaSopenharmony_ci goto fail; 1020c87c5fbaSopenharmony_ci 1021c87c5fbaSopenharmony_ci if (fflush(fp_new) == EOF) 1022c87c5fbaSopenharmony_ci goto fail; 1023c87c5fbaSopenharmony_ci fclose(fp_new); 1024c87c5fbaSopenharmony_ci fclose(fp_orig); 1025c87c5fbaSopenharmony_ci /* Either old or new is in place */ 1026c87c5fbaSopenharmony_ci (void)rename(new, (const char *)context->dyn_resource_save_file->s); 1027c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 1028c87c5fbaSopenharmony_ci return 1; 1029c87c5fbaSopenharmony_ci 1030c87c5fbaSopenharmony_cifail: 1031c87c5fbaSopenharmony_ci if (fp_new) 1032c87c5fbaSopenharmony_ci fclose(fp_new); 1033c87c5fbaSopenharmony_ci if (fp_orig) 1034c87c5fbaSopenharmony_ci fclose(fp_orig); 1035c87c5fbaSopenharmony_ci if (new) { 1036c87c5fbaSopenharmony_ci (void)remove(new); 1037c87c5fbaSopenharmony_ci } 1038c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 1039c87c5fbaSopenharmony_ci return 0; 1040c87c5fbaSopenharmony_ci} 1041c87c5fbaSopenharmony_ci 1042c87c5fbaSopenharmony_ci/* 1043c87c5fbaSopenharmony_ci * Server has deleted a resource 1044c87c5fbaSopenharmony_ci */ 1045c87c5fbaSopenharmony_cistatic int 1046c87c5fbaSopenharmony_cicoap_op_resource_deleted(coap_context_t *context, 1047c87c5fbaSopenharmony_ci coap_str_const_t *resource_name, 1048c87c5fbaSopenharmony_ci void *user_data) { 1049c87c5fbaSopenharmony_ci FILE *fp_orig = NULL; 1050c87c5fbaSopenharmony_ci FILE *fp_new = NULL; 1051c87c5fbaSopenharmony_ci char *new = NULL; 1052c87c5fbaSopenharmony_ci coap_proto_t e_proto; 1053c87c5fbaSopenharmony_ci coap_string_t *name = NULL; 1054c87c5fbaSopenharmony_ci coap_binary_t *raw_packet = NULL; 1055c87c5fbaSopenharmony_ci (void)user_data; 1056c87c5fbaSopenharmony_ci 1057c87c5fbaSopenharmony_ci coap_op_obs_cnt_deleted(context, resource_name); 1058c87c5fbaSopenharmony_ci 1059c87c5fbaSopenharmony_ci fp_orig = fopen((const char *)context->dyn_resource_save_file->s, "r"); 1060c87c5fbaSopenharmony_ci if (fp_orig == NULL) 1061c87c5fbaSopenharmony_ci return 1; 1062c87c5fbaSopenharmony_ci 1063c87c5fbaSopenharmony_ci new = coap_malloc_type(COAP_STRING, 1064c87c5fbaSopenharmony_ci context->dyn_resource_save_file->length + 5); 1065c87c5fbaSopenharmony_ci if (!new) 1066c87c5fbaSopenharmony_ci goto fail; 1067c87c5fbaSopenharmony_ci 1068c87c5fbaSopenharmony_ci strcpy(new, (const char *)context->dyn_resource_save_file->s); 1069c87c5fbaSopenharmony_ci strcat(new, ".tmp"); 1070c87c5fbaSopenharmony_ci fp_new = fopen(new, "w+"); 1071c87c5fbaSopenharmony_ci if (fp_new == NULL) 1072c87c5fbaSopenharmony_ci goto fail; 1073c87c5fbaSopenharmony_ci 1074c87c5fbaSopenharmony_ci /* Go through and locate resource to delete and not copy it across */ 1075c87c5fbaSopenharmony_ci while (1) { 1076c87c5fbaSopenharmony_ci if (!coap_op_dyn_resource_read(fp_orig, &e_proto, &name, &raw_packet)) 1077c87c5fbaSopenharmony_ci break; 1078c87c5fbaSopenharmony_ci if (!coap_string_equal(resource_name, name)) { 1079c87c5fbaSopenharmony_ci /* Copy across non-matching entry */ 1080c87c5fbaSopenharmony_ci if (!coap_op_dyn_resource_write(fp_new, e_proto, (coap_str_const_t *)name, 1081c87c5fbaSopenharmony_ci (coap_bin_const_t *)raw_packet)) 1082c87c5fbaSopenharmony_ci break; 1083c87c5fbaSopenharmony_ci } 1084c87c5fbaSopenharmony_ci coap_delete_string(name); 1085c87c5fbaSopenharmony_ci name = NULL; 1086c87c5fbaSopenharmony_ci coap_delete_binary(raw_packet); 1087c87c5fbaSopenharmony_ci raw_packet = NULL; 1088c87c5fbaSopenharmony_ci } 1089c87c5fbaSopenharmony_ci coap_delete_string(name); 1090c87c5fbaSopenharmony_ci coap_delete_binary(raw_packet); 1091c87c5fbaSopenharmony_ci 1092c87c5fbaSopenharmony_ci if (fflush(fp_new) == EOF) 1093c87c5fbaSopenharmony_ci goto fail; 1094c87c5fbaSopenharmony_ci fclose(fp_new); 1095c87c5fbaSopenharmony_ci fclose(fp_orig); 1096c87c5fbaSopenharmony_ci /* Either old or new is in place */ 1097c87c5fbaSopenharmony_ci (void)rename(new, (const char *)context->dyn_resource_save_file->s); 1098c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 1099c87c5fbaSopenharmony_ci return 1; 1100c87c5fbaSopenharmony_ci 1101c87c5fbaSopenharmony_cifail: 1102c87c5fbaSopenharmony_ci if (fp_new) 1103c87c5fbaSopenharmony_ci fclose(fp_new); 1104c87c5fbaSopenharmony_ci if (fp_orig) 1105c87c5fbaSopenharmony_ci fclose(fp_orig); 1106c87c5fbaSopenharmony_ci if (new) { 1107c87c5fbaSopenharmony_ci (void)remove(new); 1108c87c5fbaSopenharmony_ci } 1109c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, new); 1110c87c5fbaSopenharmony_ci return 0; 1111c87c5fbaSopenharmony_ci} 1112c87c5fbaSopenharmony_ci 1113c87c5fbaSopenharmony_ciint 1114c87c5fbaSopenharmony_cicoap_persist_startup(coap_context_t *context, 1115c87c5fbaSopenharmony_ci const char *dyn_resource_save_file, 1116c87c5fbaSopenharmony_ci const char *observe_save_file, 1117c87c5fbaSopenharmony_ci const char *obs_cnt_save_file, 1118c87c5fbaSopenharmony_ci uint32_t save_freq) { 1119c87c5fbaSopenharmony_ci if (dyn_resource_save_file) { 1120c87c5fbaSopenharmony_ci context->dyn_resource_save_file = 1121c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)dyn_resource_save_file, 1122c87c5fbaSopenharmony_ci strlen(dyn_resource_save_file)); 1123c87c5fbaSopenharmony_ci if (!context->dyn_resource_save_file) 1124c87c5fbaSopenharmony_ci return 0; 1125c87c5fbaSopenharmony_ci coap_op_dyn_resource_load_disk(context); 1126c87c5fbaSopenharmony_ci context->dyn_resource_added = coap_op_dyn_resource_added; 1127c87c5fbaSopenharmony_ci context->resource_deleted = coap_op_resource_deleted; 1128c87c5fbaSopenharmony_ci } 1129c87c5fbaSopenharmony_ci if (obs_cnt_save_file) { 1130c87c5fbaSopenharmony_ci context->obs_cnt_save_file = 1131c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)obs_cnt_save_file, 1132c87c5fbaSopenharmony_ci strlen(obs_cnt_save_file)); 1133c87c5fbaSopenharmony_ci if (!context->obs_cnt_save_file) 1134c87c5fbaSopenharmony_ci return 0; 1135c87c5fbaSopenharmony_ci context->observe_save_freq = save_freq ? save_freq : 1; 1136c87c5fbaSopenharmony_ci coap_op_obs_cnt_load_disk(context); 1137c87c5fbaSopenharmony_ci context->track_observe_value = coap_op_obs_cnt_track_observe; 1138c87c5fbaSopenharmony_ci context->resource_deleted = coap_op_resource_deleted; 1139c87c5fbaSopenharmony_ci } 1140c87c5fbaSopenharmony_ci if (observe_save_file) { 1141c87c5fbaSopenharmony_ci context->observe_save_file = 1142c87c5fbaSopenharmony_ci coap_new_bin_const((const uint8_t *)observe_save_file, 1143c87c5fbaSopenharmony_ci strlen(observe_save_file)); 1144c87c5fbaSopenharmony_ci if (!context->observe_save_file) 1145c87c5fbaSopenharmony_ci return 0; 1146c87c5fbaSopenharmony_ci coap_op_observe_load_disk(context); 1147c87c5fbaSopenharmony_ci context->observe_added = coap_op_observe_added; 1148c87c5fbaSopenharmony_ci context->observe_deleted = coap_op_observe_deleted; 1149c87c5fbaSopenharmony_ci } 1150c87c5fbaSopenharmony_ci return 1; 1151c87c5fbaSopenharmony_ci} 1152c87c5fbaSopenharmony_ci 1153c87c5fbaSopenharmony_civoid 1154c87c5fbaSopenharmony_cicoap_persist_cleanup(coap_context_t *context) { 1155c87c5fbaSopenharmony_ci coap_delete_bin_const(context->dyn_resource_save_file); 1156c87c5fbaSopenharmony_ci coap_delete_bin_const(context->obs_cnt_save_file); 1157c87c5fbaSopenharmony_ci coap_delete_bin_const(context->observe_save_file); 1158c87c5fbaSopenharmony_ci context->dyn_resource_save_file = NULL; 1159c87c5fbaSopenharmony_ci context->obs_cnt_save_file = NULL; 1160c87c5fbaSopenharmony_ci context->observe_save_file = NULL; 1161c87c5fbaSopenharmony_ci 1162c87c5fbaSopenharmony_ci /* Close down any tracking */ 1163c87c5fbaSopenharmony_ci coap_persist_track_funcs(context, NULL, NULL, NULL, NULL, 1164c87c5fbaSopenharmony_ci NULL, 0, NULL); 1165c87c5fbaSopenharmony_ci} 1166c87c5fbaSopenharmony_ci 1167c87c5fbaSopenharmony_civoid 1168c87c5fbaSopenharmony_cicoap_persist_stop(coap_context_t *context) { 1169c87c5fbaSopenharmony_ci if (context == NULL) 1170c87c5fbaSopenharmony_ci return; 1171c87c5fbaSopenharmony_ci context->observe_no_clear = 1; 1172c87c5fbaSopenharmony_ci coap_persist_cleanup(context); 1173c87c5fbaSopenharmony_ci} 1174c87c5fbaSopenharmony_ci#else /* ! COAP_WITH_OBSERVE_PERSIST */ 1175c87c5fbaSopenharmony_ciint 1176c87c5fbaSopenharmony_cicoap_persist_startup(coap_context_t *context, 1177c87c5fbaSopenharmony_ci const char *dyn_resource_save_file, 1178c87c5fbaSopenharmony_ci const char *observe_save_file, 1179c87c5fbaSopenharmony_ci const char *obs_cnt_save_file, 1180c87c5fbaSopenharmony_ci uint32_t save_freq) { 1181c87c5fbaSopenharmony_ci (void)context; 1182c87c5fbaSopenharmony_ci (void)dyn_resource_save_file; 1183c87c5fbaSopenharmony_ci (void)observe_save_file; 1184c87c5fbaSopenharmony_ci (void)obs_cnt_save_file; 1185c87c5fbaSopenharmony_ci (void)save_freq; 1186c87c5fbaSopenharmony_ci return 0; 1187c87c5fbaSopenharmony_ci} 1188c87c5fbaSopenharmony_ci 1189c87c5fbaSopenharmony_civoid 1190c87c5fbaSopenharmony_cicoap_persist_stop(coap_context_t *context) { 1191c87c5fbaSopenharmony_ci context->observe_no_clear = 1; 1192c87c5fbaSopenharmony_ci /* Close down any tracking */ 1193c87c5fbaSopenharmony_ci coap_persist_track_funcs(context, NULL, NULL, NULL, NULL, 1194c87c5fbaSopenharmony_ci NULL, 0, NULL); 1195c87c5fbaSopenharmony_ci} 1196c87c5fbaSopenharmony_ci 1197c87c5fbaSopenharmony_ci#endif /* ! COAP_WITH_OBSERVE_PERSIST */ 1198c87c5fbaSopenharmony_ci 1199c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1200