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 *op-
     tions, 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_ses-
     sion_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_en-
     try);

     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 ap-
     propriate 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  ex-
     clude these CoAP options in a proxy where it makes sense to cache the indi-
     vidual 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 ses-
     sion  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  infor-
     mation 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 No-
     CacheKey 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 re-
     turned 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 in-
     cluded 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  En-
     try  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 previ-
     ously 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  overwrit-
     ten, 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		   08/02/2026			   COAP_CACHE(3)

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

home | help