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_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)

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>

home | help