Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
COAP_PERSIST(3)			libcoap	Manual		       COAP_PERSIST(3)

NAME
       coap_persist, coap_persist_startup, coap_persist_stop,
       coap_persist_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_resource_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_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);

       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 subscriptions and maintaining OSCORE protection.

       There are callbacks provided to support doing this as an	alternative
       persist 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 observe 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_persist_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
       subscribes 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
       removes 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
       unsolicited 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
       resource	is created from	a request that is calling the resource unknown
       handler,	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
       resource	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 having to establish a new session and issue a new observe
       subscription request. 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
       resource'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_observe(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		  11/03/2025		       COAP_PERSIST(3)

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.0>

home | help