FreeBSD Manual Pages
COAP_PERSIST(3) libcoap Manual COAP_PERSIST(3) NAME coap_persist, coap_persist_startup, coap_persist_stop, coap_per- sist_track_funcs, coap_persist_observe_add, coap_persist_set_observe_num - Work with CoAP persist support SYNOPSIS #include <coap3/coap.h> int coap_persist_startup(coap_context_t *context, const char *dyn_re- source_save_file, const char *observe_save_file, const char *obs_cnt_save_file, uint32_t save_freq); void coap_persist_stop(coap_context_t *context); void coap_persist_track_funcs(coap_context_t *context, coap_observe_added_t observe_added, coap_observe_deleted_t observe_deleted, coap_track_ob- serve_value_t track_observe_value, coap_dyn_resource_added_t dyn_re- source_added, coap_resource_deleted_t resource_deleted, uint32_t save_freq, void *user_data); 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); void coap_persist_set_observe_num(coap_resource_t *resource, uint32_t start_observe_no); For specific (D)TLS library support, link with -lcoap-3-notls, -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls, -lcoap-3-wolfssl or -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default (D)TLS library support. DESCRIPTION When a coap-server is restarted, state information does not usually persist over the restart. libcoap has optional compiled in support for maintaining resources that were dynamically created, tracking ongoing observe subscrip- tions and maintaining OSCORE protection. There are callbacks provided to support doing this as an alternative per- sist storage in the coap-server application. NOTE: The observe persist support is only available for UDP sessions. When using the libcoap compiled in support, only two functions need to be called by the application. coap_persist_startup() defines the file names to use for maintaining the persist information over an application restart, and coap_persist_stop() is called to preserve any persist information over the server restart. FUNCTIONS Function: coap_persist_startup() The coap_persist_startup() function is used to enable persist tracking for context so when a coap-server is restarted, the persist tracked information can be added back in for the server logic. dyn_resource_save_file is used to save the current list of resources created from a request to the unknown resource. observe_save_file is used to save the current list of active ob- serve subscriptions. obs_cnt_save_file is used to save the current observe counter used when sending an observe unsolicited response. obs_cnt_save_file only gets updated every save_freq updates. If any of the files exist and are not empty, when coap_persist_startup() is called, the information is loaded back into the server logic, and for the active observe subscriptions a new server session is created for sending out the ongoing observe updates (UDP only supported). If a file is defined as NULL, then that particular persist information is not tracked by the libcoap module. This allows a combination of coap_per- sist_track_funcs() for customized persist tracking followed by a call to coap_persist_startup(). Function: coap_persist_stop() The coap_persist_stop() function is used to disable any current persist tracking as set up by coap_persist_startup() for context and preserve the tracking for when the coap-server application restarts. If using coap_persist_track_funcs(), then calling coap_persist_stop() will stop any 4.04 unsolicited response messages being sent when a resource that has an active observe subscription is deleted (as happens when coap_free_context() is subsequentially called). Function: coap_persist_track_funcs() The coap_persist_track_funcs() function is used to setup callback functions associated with context that track information so that the current tracked information state can be rebuilt following a server application restart. It is the responsibility of the server application to track the appropriate information. The observe_added callback function prototype, called when a client sub- scribes to a resource for observation, is defined as: /** * Callback handler definition called when a new observe has been set up, * as defined in coap_persist_track_funcs(). * * @param session The current session. * @param observe_key The pointer to the subscription. * @param e_proto The CoAP protocol in use for the session / endpoint. * @param e_listen_addr The IP/port that the endpoint is listening on. * @param s_addr_info Local / Remote IP addresses. ports etc. of session. * @param raw_packet L7 packet as seen on the wire (could be concatenated if * Block1 FETCH is being used). * @param oscore_info Has OSCORE information if OSCORE is protecting the * session or NULL if OSCORE is not in use. * @param user_data Application provided information from * coap_persist_track_funcs(). * * @return @c 1 if success else @c 0. */ typedef 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); The observe_deleted callback function prototype, called when a client re- moves the subscription to a resource for observation, is defined as: /** * Callback handler definition called when an observe is being removed, * as defined in coap_persist_track_funcs(). * * @param session The current session. * @param observe_key The pointer to the subscription. * @param user_data Application provided information from * coap_persist_track_funcs(). * * @return @c 1 if success else @c 0. */ typedef int (*coap_observe_deleted_t)(coap_session_t *session, coap_subscription_t *observe_key, void *user_data); The track_observe_value callback function prototype, called when a new un- solicited observe response is went (every save_freq), is defined as: /** * Callback handler definition called when an observe unsolicited response is * being sent, as defined in coap_persist_track_funcs(). * * Note: This will only get called every save_freq as defined by * coap_persist_track_funcs(). * * @param context The current CoAP context. * @param resource_name The uri path name of the resource. * @param observe_num The current observe value just sent. * @param user_data Application provided information from * coap_persist_track_funcs(). * * @return @c 1 if success else @c 0. */ typedef int (*coap_track_observe_value_t)(coap_context_t *context, coap_str_const_t *resource_name, uint32_t observe_num, void *user_data); The dyn_resource_added callback function prototype, called whenever a re- source is created from a request that is calling the resource unknown han- dler, is defined as: /** * Callback handler definition called when a dynamic resource is getting * created, as defined in coap_persist_track_funcs(). * * @param session The current CoAP session. * @param resource_name The uri path name of the resource. * @param raw_packet L7 packet as seen on the wire (could be concatenated if * Block1 PUT/POST/FETCH used to create resource). * @param user_data Application provided information from * coap_persist_track_funcs(). * * @return @c 1 if success else @c 0. */ typedef 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); The resource_deleted callback function prototype, called whenever a re- source is deleted, is defined as: /** * Callback handler definition called when resource is removed, * as defined in coap_persist_track_funcs(). * * This will remove any dynamic resources that are being tracked as well * as any observe value tracking. * * @param context The current CoAP context. * @param resource_name The uri path name of the resource. * @param user_data Application provided information from * coap_persist_track_funcs(). * * @return @c 1 if success else @c 0. */ typedef int (*coap_resource_deleted_t)(coap_context_t *context, coap_str_const_t *resource_name, void *user_data); save_freq defines the frequency of the update to the observe value when libcoap calls track_observe_value. user_data is application defined and is passed into all of the callback handlers. Function: coap_persist_observe_add() The coap_persist_observe_add() function is used to set up a session and a observe subscription request (typically following a server reboot) so that a client can continue to receive unsolicited observe responses without hav- ing to establish a new session and issue a new observe subscription re- quest. The new session is associated with the endpoint defined by e_proto and e_listen_address. The session has the IP addresses as defined by s_addr_info. raw_packet contains the layer 7 of the IP packet that was originally used to request the observe subscription. Optional oscore_info defines the OSCORE information if packets are protected by OSCORE. e_proto, e_listen_addr, s_addr_info, raw_packet and oscore_info are the same as passed into the coap_observe_added_t callback. Function: coap_persist_set_observe_num() The coap_persist_set_observe_num() function is used to update the re- source's current observe counter to start from start_observe_no instead of 0, RETURN VALUES coap_persist_startup() returns 1 on success else 0. coap_persist_observe_add() returns a newly created observe subscription or NULL on failure. EXAMPLES Simple Time Server #include <coap3/coap.h> #include <stdio.h> coap_resource_t *time_resource = NULL; /* specific GET "time" handler, called from hnd_get_generic() */ static void hnd_get_time(coap_resource_t *resource, coap_session_t *session, const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { unsigned char buf[40]; size_t len; time_t now; (void)resource; (void)session; /* ... Additional analysis code for resource, request pdu etc. ... */ /* After analysis, generate a suitable response */ /* Note that token, if set, is already in the response pdu */ now = time(NULL); if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) { /* Output secs since Jan 1 1970 */ len = snprintf((char *)buf, sizeof(buf), "%lu", now); } else { /* Output human-readable time */ struct tm *tmp; tmp = gmtime(&now); if (!tmp) { /* If 'now' is not valid */ coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND); return; } len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp); } coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); /* * Invoke coap_add_data_large_response() to do all the hard work. * * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in * Define how long this response is valid for (secs) - 1 - to add in. * ETAG Option added internally with unique value as param set to 0 * * OBSERVE Option added internally if needed within the function * BLOCK2 Option added internally if output too large * SIZE2 Option added internally */ coap_add_data_large_response(resource, session, request, response, query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0, len, buf, NULL, NULL); } /* Generic GET handler */ static void hnd_get_generic(coap_resource_t *resource, coap_session_t *session, const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) { coap_str_const_t *uri_path = coap_resource_get_uri_path(resource); if (!uri_path) { /* Unexpected Failure */ coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); return; } /* Is this the "time" resource" ? */ if (coap_string_equal(uri_path, coap_make_str_const("time"))) { hnd_get_time(resource, session, request, query, response); return; } /* Other resources code */ /* Failure response */ coap_pdu_set_code(response, COAP_RESPONSE_CODE_BAD_REQUEST); } /* Initialize generic GET handler */ static void init_resources(coap_context_t *ctx) { coap_resource_t *r; /* Create a resource to return return or update time */ r = coap_resource_init(coap_make_str_const("time"), COAP_RESOURCE_FLAGS_NOTIFY_CON); /* We are using a generic GET handler here */ coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_generic); coap_resource_set_get_observable(r, 1); coap_add_resource(ctx, r); time_resource = r; } int main(int argc, char *argv[]) { coap_context_t *ctx = NULL; coap_endpoint_t *ep = NULL; coap_address_t addr; unsigned wait_ms; struct timeval tv_last = {0, 0}; /* Remove (void) definition if variable is used */ (void)argc; (void)argv; /* Initialize libcoap library */ coap_startup(); memset(&tv_last, 0, sizeof(tv_last)); /* Create the libcoap context */ ctx = coap_new_context(NULL); if (!ctx) { exit(1); } /* See coap_block(3) */ coap_context_set_block_mode(ctx, COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); coap_address_init(&addr); addr.addr.sa.sa_family = AF_INET; addr.addr.sin.sin_port = ntohs(COAP_DEFAULT_PORT); ep = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP); /* Other Set up Code */ init_resources(ctx); if (!coap_persist_startup(ctx, "/tmp/coap_dyn_resource_save_file", "/tmp/coap_observe_save_file", "/tmp/coap_obs_cnt_save_file", 10)) { fprintf(stderr, "Unable to set up persist logic\n"); exit(1); } wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; while (1) { int result = coap_io_process(ctx, wait_ms); if (result < 0) { break; } else if (result && (unsigned)result < wait_ms) { /* decrement if there is a result wait time returned */ wait_ms -= result; } else { /* * result == 0, or result >= wait_ms * (wait_ms could have decremented to a small value, below * the granularity of the timer in coap_io_process() and hence * result == 0) */ wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; } if (time_resource) { struct timeval tv_now; if (gettimeofday(&tv_now, NULL) == 0) { if (tv_last.tv_sec != tv_now.tv_sec) { /* Happens once per second */ tv_last = tv_now; coap_resource_notify_observers(time_resource, NULL); } /* need to wait until next second starts if wait_ms is too large */ unsigned next_sec_ms = 1000 - (tv_now.tv_usec / 1000); if (next_sec_ms && next_sec_ms < wait_ms) wait_ms = next_sec_ms; } } } coap_persist_stop(ctx); coap_free_context(ctx); coap_cleanup(); exit(0); } SEE ALSO coap_block(3), coap_context(3), coap_handler(3), coap_init(3), coap_ob- serve(3), coap_pdu_setup(3), coap_resource(3) and coap_session(3) FURTHER INFORMATION See "RFC7252: The Constrained Application Protocol (CoAP)" "RFC7641: Observing Resources in the Constrained Application Protocol (CoAP)" "RFC8613: Object Security for Constrained RESTful Environments (OSCORE)" for further information. BUGS Please raise an issue on GitHub at https://github.com/obgm/libcoap/issues to report any bugs. Please raise a Pull Request at https://github.com/obgm/libcoap/pulls for any fixes. AUTHORS The libcoap project <libcoap-developers@lists.sourceforge.net> coap_persist 4.3.5 08/02/2026 COAP_PERSIST(3)
NAME | SYNOPSIS | DESCRIPTION | FUNCTIONS | RETURN VALUES | EXAMPLES | SEE ALSO | FURTHER INFORMATION | BUGS | AUTHORS
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=coap_persist&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>
