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

FreeBSD Manual Pages

  
 
  

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

NAME
       coap_cache, coap_cache_derive_key, coap_cache_derive_key_w_ignore,
       coap_delete_cache_key, coap_cache_ignore_options, coap_new_cache_entry,
       coap_delete_cache_entry,	coap_cache_get_by_key, coap_cache_get_by_pdu,
       coap_cache_get_pdu, coap_cache_set_app_data, coap_cache_get_app_data -
       Work with CoAP cache functions

SYNOPSIS
       #include	<coap3/coap.h>

       coap_cache_key_t	*coap_cache_derive_key(const coap_session_t *session,
       const coap_pdu_t	*pdu, coap_cache_session_based_t session_based);

       coap_cache_key_t	*coap_cache_derive_key_w_ignore( const coap_session_t
       *session, const coap_pdu_t *pdu,	coap_cache_session_based_t
       session_based, const uint16_t *ignore_options, size_t ignore_count);

       void coap_delete_cache_key(coap_cache_key_t *cache_key);

       int coap_cache_ignore_options(coap_context_t *context, const uint16_t
       *options, size_t	count);

       coap_cache_entry_t *coap_new_cache_entry(coap_session_t *session, const
       coap_pdu_t *pdu,	coap_cache_record_pdu_t	record_pdu,
       coap_cache_session_based_t session_based, unsigned int idle_timeout);

       void coap_delete_cache_entry(coap_context_t *context,
       coap_cache_entry_t *cache_entry);

       coap_cache_entry_t *coap_cache_get_by_key(coap_context_t	*context,
       const coap_cache_key_t *cache_key);

       coap_cache_entry_t *coap_cache_get_by_pdu(coap_session_t	*session,
       const coap_pdu_t	*pdu, coap_cache_session_based_t session_based);

       const coap_pdu_t	*coap_cache_get_pdu(const coap_cache_entry_t
       *cache_entry);

       void coap_cache_set_app_data(coap_cache_entry_t *cache_entry, void
       *data, coap_cache_app_data_free_callback_t callback);

       void *coap_cache_get_app_data(const coap_cache_entry_t *cache_entry);

       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
       The CoAP	Cache provides support for two opaque objects that can be used
       for tracking requests and responses.

       The first is the	ability	to derive a Cache Key from the cacheable parts
       of a CoAP PDU as	defined	in "RFC7252 5.6. Caching" updated by "RFC7641
       2. The Observe Option" and "RFC8132 2. Fetch Method".

       The Cache Key is	a SHA256 digest	if libcoap was built with TLS support,
       otherwise it uses the internal coap_hash() function, using the
       information abstracted from the PDU and (optionally) the	CoAP session.

       This Cache Key can then be used to match	against	incoming PDUs and then
       appropriate action logic	can take place.

       There is	support	for excluding specific CoAP options from the Cache
       Key. Examples could be to exclude CoAP BLOCK1 and BLOCK2	Options	for
       the client or server for	ease of	tracking a large PUT or	GET response,
       but to not exclude these	CoAP options in	a proxy	where it makes sense
       to cache	the individual blocks.

       The second is providing Cache Entries (which can	be looked up by	PDU
       and hence by Cache Key) which hold additional information to make
       information tracking simpler. These Cache Entries are automatically
       deleted when a session closes or	a context is deleted. These Cache
       Entries are maintained on a hashed list for speed of lookup.

       The following enums are defined.

	   typedef enum	coap_cache_session_based_t {
	     COAP_CACHE_NOT_SESSION_BASED,
	     COAP_CACHE_IS_SESSION_BASED
	   } coap_cache_session_based_t;

	   typedef enum	coap_cache_record_pdu_t	{
	     COAP_CACHE_NOT_RECORD_PDU,
	     COAP_CACHE_RECORD_PDU
	   } coap_cache_record_pdu_t;

FUNCTIONS
       Function: coap_cache_derive_key()

       The coap_cache_derive_key() function abstracts all the non NoCacheKey
       CoAP options, ignores the CoAP Observe option and includes a FETCH body
       from pdu. If session_based is COAP_CACHE_IS_SESSION_BASED, then session
       pointer is also included. CoAP options can be specifically ignored by
       the use of coap_cache_ignore_options(). A digest	is then	built from all
       of the information and returned.	NULL is	returned on error.

       Function: coap_cache_derive_key_w_ignore()

       The coap_cache_derive_key_w_ignore() function abstracts all the non
       NoCacheKey CoAP options,	ignores	the CoAP Observe option	and includes a
       FETCH body from pdu. Further options to ignore are specified by the
       ignore_count of ignore_options. If session_based	is
       COAP_CACHE_IS_SESSION_BASED, then session pointer is also included. A
       digest is then built from all of	the information	and returned. NULL is
       returned	on error.

       Function: coap_delete_cache_key()

       The coap_delete_cache_key() function deletes the	cache_key that was
       returned	from a coap_cache_derive_key() or
       coap_cache_derive_key_w_ignore()	call.

       Function: coap_cache_ignore_options()

       The coap_cache_ignore_options() function	is used	to store in context a
       list of count options held in options. The specified options will not
       be included in the data used for	the coap_cache_derive_key() function.

       Function: coap_new_cache_entry()

       The coap_new_cache_entry() function will	create a new Cache Entry based
       on the Cache Key	derived	from the pdu, session_based and	session. If
       record_pdu is COAP_CACHE_RECORD_PDU, then a copy	of the pdu is stored
       in the Cache Entry for subsequent retrieval. The	Cache Entry can	also
       store application specific data (coap_cache_set_app_data() and
       coap_cache_get_app_data()). idle_timeout	in seconds defines the length
       of time not being used before it	gets deleted. If idle_timeout is set
       to 0, then the Cache Entry will not get idle expired. The created Cache
       Entry is	returned, or NULL on error.

       Function: coap_delete_cache_entry()

       The coap_delete_cache_entry() function can be used to delete the	Cache
       Entry cache_entry held within context. This will	remove the Cache Entry
       from the	hash lookup list and free off any internally held data.	If the
       Cache Entry is session based, then it will automatically	get deleted
       when the	session	is freed off or	when the idle timeout expires.

       Function: coap_cache_get_by_key()

       The coap_cache_get_by_key() function will locate	the Cache Entry	held
       in the context environment that has Cache Key cache_key.	Returns	NULL
       if the Cache Key	was not	found.

       Function: coap_cache_get_by_pdu()

       The coap_cache_get_by_pdu() function will locate	the Cache Entry	held
       in the session environment that has a Cache Key derived from the	pdu
       and whether session_based or not. This function calls
       coap_cache_derive_key() internally, and so normally
       coap_cache_ignore_options() would have previously been called with
       COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2	to ignore the values held
       within these options.

       Function: coap_cache_get_pdu()

       The coap_cache_get_pdu()	function returns the PDU that was stored with
       the Cache Entry when it was created with	coap_new_cache_entry() and
       record_pdu was set to COAP_CACHE_RECORD_PDU. If a PDU was not initially
       stored, NULL is returned. NOTE: A copy of the returned PDU must be
       taken for use in	sending	a CoAP packet using coap_pdu_duplicate().

       Function: coap_cache_set_app_data()

       The coap_cache_set_app_data() function is used to associate data	with
       the cache_entry.	If callback is not NULL, it points to a	function to
       free off	data when the cache_entry is deleted. If any data has been
       previously stored in the	cache_entry, the pointer to the	old data will
       get overwritten,	but the	old data will not get freed off.

       The callback handler function prototype is defined as:

	   /**
	    * Callback to free off the app data	when the cache-entry is
	    * being deleted / freed off.
	    *
	    * @param data  The app data	to be freed off.
	    */
	   typedef void	(*coap_cache_app_data_free_callback_t)(void *data);

       Function: coap_cache_get_app_data()

       The coap_cache_get_app_data() function is used to get the previously
       stored data in the cache_entry.

RETURN VALUES
       coap_cache_derive_key() and coap_cache_derive_key_w_ignore() returns a
       newly created Cache Key or NULL if there	is a creation failure.

       coap_cache_ignore_options() returns 1 if	success, 0 on failure.

       coap_new_cache_entry(), coap_cache_get_by_key() and
       coap_cache_get_by_pdu() return the Cache	Entry or NULL if there is a
       failure.

       coap_cache_get_pdu() returns the	PDU that is held within	the Cache
       Entry or	NULL if	there is no PDU	available.

       coap_cache_get_app_data() returns the application data value previously
       set by the coap_cache_set_app_data() function or	NULL.

EXAMPLES
       PUT Handler supporting BLOCK1

	   #include <coap3/coap.h>

	   static coap_binary_t	*example_data_ptr = NULL;
	   static int example_data_media_type =	COAP_MEDIATYPE_TEXT_PLAIN;

	   static void
	   cache_free_app_data(void *data) {
	     coap_binary_t *bdata = (coap_binary_t *)data;
	     coap_delete_binary(bdata);
	   }

	   /*
	    * Large Data PUT handler
	    */

	   static void
	   hnd_put_example_data(coap_context_t *ctx,
				coap_resource_t	*resource,
				coap_session_t *session,
				coap_pdu_t *request,
				coap_binary_t *token,
				coap_string_t *query,
				coap_pdu_t *response) {
	     size_t size;
	     const uint8_t *data;
	     coap_opt_iterator_t opt_iter;
	     coap_opt_t	*option;
	     size_t offset;
	     size_t total;
	     coap_binary_t *data_so_far;

	     /*	Remove (void) definition if variable is	used */
	     (void)ctx;
	     (void)token;
	     (void)query;

	     if	(coap_get_data_large(request, &size, &data, &offset, &total) &&
		 size != total)	{
	       /*
		* A part of the	data has been received (COAP_BLOCK_SINGLE_BODY not set).
		* However, total unfortunately is only an indication, so it is not safe	to
		* allocate a block based on total.  As per
		* https://rfc-editor.org/rfc/rfc7959#section-4
		*   o  In a request carrying a Block1 Option, to indicate the current
		*	  estimate the client has of the total size of the resource
		*	  representation, measured in bytes ("size indication").
		*
		* coap_cache_ignore_options() must have	previously been	called with at
		* least	COAP_OPTION_BLOCK1 set as the option value will	change per block.
		*/
	       coap_cache_entry_t *cache_entry = coap_cache_get_by_pdu(session,
								       request,
								       COAP_CACHE_IS_SESSION_BASED);

	       if (offset == 0)	{
		 if (!cache_entry) {
		   /*
		    * Set idle_timeout parameter to COAP_MAX_TRANSMIT_WAIT if you want
		    * early removal on transmission failure. 0 means only delete when
		    * the session is deleted as	session_based is set here.
		    */
		   cache_entry = coap_new_cache_entry(session, request,
						      COAP_CACHE_NOT_RECORD_PDU,
						      COAP_CACHE_IS_SESSION_BASED, 0);
		 } else	{
		   data_so_far = coap_cache_get_app_data(cache_entry);
		   if (data_so_far) {
		     coap_delete_binary(data_so_far);
		     data_so_far = NULL;
		   }
		   coap_cache_set_app_data(cache_entry,	NULL, NULL);
		 }
	       }
	       if (!cache_entry) {
		 if (offset == 0) {
		   coap_log_warn("Unable to create a new cache entry\n");
		 } else	{
		   coap_log_warn(
		       "No cache entry available for the non-first BLOCK\n");
		 }
		 coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR);
		 return;
	       }

	       if (size) {
		 /* Add	in the new data	to cache entry */
		 data_so_far = coap_cache_get_app_data(cache_entry);
		 data_so_far = coap_block_build_body(data_so_far, size,	data,
						     offset, total);
		 /* Yes, data_so_far can be NULL if error */
		 coap_cache_set_app_data(cache_entry, data_so_far, cache_free_app_data);
	       }
	       if (offset + size == total) {
		 /* All	the data is now	in */
		 data_so_far = coap_cache_get_app_data(cache_entry);
		 coap_cache_set_app_data(cache_entry, NULL, NULL);
	       } else {
		 /* Give us the	next block response */
		 coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTINUE);
		 return;
	       }
	     } else {
	       /* single body of data received */
	       data_so_far = coap_new_binary(size);
	       if (data_so_far)	{
		 memcpy(data_so_far->s,	data, size);
	       }
	     }

	     if	(example_data_ptr) {
	       /* pre-existed response */
	       coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
	       coap_delete_binary(example_data_ptr);
	     } else {
	       /* just generated response */
	       coap_pdu_set_code(response, COAP_RESPONSE_CODE_CREATED);
	     }

	     example_data_ptr =	data_so_far;
	     if	((option = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT,
					     &opt_iter)) != NULL) {
	       example_data_media_type =
		   coap_decode_var_bytes(coap_opt_value(option),
					 coap_opt_length(option));
	     } else {
	       example_data_media_type = COAP_MEDIATYPE_TEXT_PLAIN;
	     }

	     coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED);
	     coap_resource_notify_observers(resource, NULL);
	   }

	   int
	   main(int argc, char *argv[])	{
	     coap_context_t *ctx = NULL;  /* Set up as normal */
	     /*	... */
	     uint16_t cache_ignore_options[] = { COAP_OPTION_BLOCK1,
						 COAP_OPTION_BLOCK2
					       };

	     /*	Initialize libcoap library */
	     coap_startup();

	     /*	Remove (void) definition if variable is	used */
	     (void)argc;
	     (void)argv;

	     /*	... */

	     /*	Define the options to ignore when setting up cache-keys	*/
	     coap_cache_ignore_options(ctx, cache_ignore_options,
				       sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0]));

	     /*	... */
	     coap_cleanup();

	   }

SEE ALSO
       coap_block(3), coap_init(3), coap_pdu_setup(3), coap_resource(3)	and
       coap_string(3)

FURTHER	INFORMATION
       See

       "RFC7252: The Constrained Application Protocol (CoAP)"

       "RFC7959: Block-Wise Transfers in the Constrained Application Protocol
       (CoAP)"

       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_cache 4.3.5		  11/03/2025			 COAP_CACHE(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=coap_cache_get_app_data&sektion=3&manpath=FreeBSD+Ports+15.0>

home | help