Skip to content

Commit

Permalink
Merge pull request #13889 from cgundogan/pr/coca
Browse files Browse the repository at this point in the history
nanocoap: cache for CoAP responses
  • Loading branch information
miri64 authored May 10, 2022
2 parents 59ec6f1 + b4cae9d commit 02fb040
Show file tree
Hide file tree
Showing 11 changed files with 985 additions and 6 deletions.
1 change: 1 addition & 0 deletions dist/tools/doccheck/exclude_patterns
Original file line number Diff line number Diff line change
Expand Up @@ -14273,6 +14273,7 @@ sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_ACCEPT \(macro definiti
sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_BLOCK1 \(macro definition\) of group net_coap is not documented\.
sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_BLOCK2 \(macro definition\) of group net_coap is not documented\.
sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_CONTENT_FORMAT \(macro definition\) of group net_coap is not documented\.
sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_MAX_AGE \(macro definition\) of group net_coap is not documented\.
sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_LOCATION_PATH \(macro definition\) of group net_coap is not documented\.
sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_LOCATION_QUERY \(macro definition\) of group net_coap is not documented\.
sys/include/net/coap\.h:[0-9]+: warning: Member COAP_OPT_OBSERVE \(macro definition\) of group net_coap is not documented\.
Expand Down
5 changes: 5 additions & 0 deletions sys/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,11 @@ ifneq (,$(filter nanocoap_sock,$(USEMODULE)))
USEMODULE += ztimer_msec
endif

ifneq (,$(filter nanocoap_cache,$(USEMODULE)))
USEMODULE += ztimer_sec
USEMODULE += hashes
endif

ifneq (,$(filter nanocoap_%,$(USEMODULE)))
USEMODULE += nanocoap
endif
Expand Down
1 change: 1 addition & 0 deletions sys/include/net/coap.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ extern "C" {
#define COAP_OPT_LOCATION_PATH (8)
#define COAP_OPT_URI_PATH (11)
#define COAP_OPT_CONTENT_FORMAT (12)
#define COAP_OPT_MAX_AGE (14)
#define COAP_OPT_URI_QUERY (15)
#define COAP_OPT_ACCEPT (17)
#define COAP_OPT_LOCATION_QUERY (20)
Expand Down
234 changes: 234 additions & 0 deletions sys/include/net/nanocoap/cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* Copyright (C) 2020 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @defgroup net_nanocoap_cache Nanocoap-Cache implementation
* @ingroup net_nanocoap
* @brief A cache implementation for nanocoap response messages
*
* @{
*
* @file
* @brief nanocoap-cache API
*
* @author Cenk Gündoğan <cenk.guendogan@haw-hamburg.de>
*/

#ifndef NET_NANOCOAP_CACHE_H
#define NET_NANOCOAP_CACHE_H

#include <assert.h>
#include <stdint.h>
#include "clist.h"
#include "net/nanocoap.h"
#include "hashes/sha256.h"
#include "ztimer.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief The number of maximum cache entries.
*/
#ifndef CONFIG_NANOCOAP_CACHE_ENTRIES
#define CONFIG_NANOCOAP_CACHE_ENTRIES (8)
#endif

/**
* @brief The length of the cache key in bytes.
*/
#ifndef CONFIG_NANOCOAP_CACHE_KEY_LENGTH
#define CONFIG_NANOCOAP_CACHE_KEY_LENGTH (8)
#endif

/**
* @brief Size of the buffer to store responses in the cache.
*/
#ifndef CONFIG_NANOCOAP_CACHE_RESPONSE_SIZE
#define CONFIG_NANOCOAP_CACHE_RESPONSE_SIZE (128)
#endif

/**
* @brief Cache container that holds a @p coap_pkt_t struct.
*/
typedef struct {
/**
* @brief needed for clist_t, must be the first struct member!
*/
clist_node_t node;

/**
* @brief the calculated cache key, see nanocoap_cache_key_generate().
*/
uint8_t cache_key[CONFIG_NANOCOAP_CACHE_KEY_LENGTH];

/**
* @brief packet representation of the response
*/
coap_pkt_t response_pkt;

/**
* @brief buffer to hold the response message.
*/
uint8_t response_buf[CONFIG_NANOCOAP_CACHE_RESPONSE_SIZE];

size_t response_len; /**< length of the message in @p response */

unsigned request_method; /**< the method of the initial request */

/**
* @brief absolute system time in seconds until which this cache entry
* is considered valid.
*/
ztimer_now_t max_age;
} nanocoap_cache_entry_t;

/**
* @brief Typedef for the cache replacement strategy on full cache list.
*
* @return 0 on successfully replacing a cache element
* @return -1 on error
*/
typedef int (*nanocoap_cache_replacement_strategy_t)(void);

/**
* @brief Typedef for the cache update strategy on element access.
*
* @param[in] node The accessed node.
*
* @return 0 on successfully updating the element
* @return -1 on error
*/
typedef int (*nanocoap_cache_update_strategy_t)(clist_node_t *node);

/**
* @brief Initializes the internal state of the nanocoap cache.
*/
#if IS_USED(MODULE_NANOCOAP_CACHE)
void nanocoap_cache_init(void);
#else
static inline void nanocoap_cache_init(void)
{
return;
}
#endif

/**
* @brief Returns the number of cached entries.
*
* @return Number of cached entries
*/
size_t nanocoap_cache_used_count(void);

/**
* @brief Returns the number of unused cache entries.
*
* @return Number of unused cache entries
*/
size_t nanocoap_cache_free_count(void);

/**
* @brief Determines if a response is cacheable and modifies the cache
* as reflected in RFC7252, Section 5.9.
* @param[in] cache_key The cache key of the request
* @param[in] request_method The method of the initial request
* @param[in] resp The response to operate on
* @param[in] resp_len The actual length of the response in @p resp
*
* @return 0 on successfully handling the response
* @return -1 on error
*/
int nanocoap_cache_process(const uint8_t *cache_key, unsigned request_method,
const coap_pkt_t *resp, size_t resp_len);
/**
* @brief Creates a new or gets an existing cache entry using the
* request packet.
*
* @param[in] req The request to calculate the cache-key
* @param[in] resp The response to add to the cache
* @param[in] resp_len The actual length of the response message in @p resp
*
* @return The previously existing or newly added cache entry on success
* @return NULL, if there is no space left
*/
nanocoap_cache_entry_t *nanocoap_cache_add_by_req(const coap_pkt_t *req,
const coap_pkt_t *resp,
size_t resp_len);

/**
* @brief Creates a new or gets an existing cache entry using the cache key.
*
* @param[in] cache_key The cache key of the request
* @param[in] request_method The method of the initial request
* @param[in] resp The response to add to the cache
* @param[in] resp_len The actual length of the response in @p resp
*
* @return The previously existing or newly added cache entry on success
* @return NULL, if there is no space left
*/
nanocoap_cache_entry_t *nanocoap_cache_add_by_key(const uint8_t *cache_key,
unsigned request_method,
const coap_pkt_t *resp,
size_t resp_len);

/**
* @brief Performs a cache lookup based on the @p req.
*
* @param[in] req The request to calculate the cache-key
*
* @return An existing cache entry on cache hit
* @return NULL on cache miss
*/
nanocoap_cache_entry_t *nanocoap_cache_request_lookup(const coap_pkt_t *req);

/**
* @brief Performs a cache lookup based on the cache key of a request.
*
* @param[in] cache_key The cache key of a request
*
* @return An existing cache entry on cache hit
* @return NULL on cache miss
*/
nanocoap_cache_entry_t *nanocoap_cache_key_lookup(const uint8_t *cache_key);

/**
* @brief Deletes the provided cache entry @p ce.
*
* @param[in] ce The cache entry to delete
*
* @return 0 on success
* @return -1 if entry is not available in the cache
*/
int nanocoap_cache_del(const nanocoap_cache_entry_t *ce);

/**
* @brief Generates a cache key based on the request @p req.
*
* @param[in] req The request to generate the cache key from
* @param[out] cache_key The generated cache key
*/
void nanocoap_cache_key_generate(const coap_pkt_t *req, uint8_t *cache_key);

/**
* @brief Compares two cache keys.
*
* @param[in] cache_key1 The first cache key in the comparison
* @param[in] cache_key2 The second cache key in the comparison
*
* @return 0 if cache keys are equal
* @return <0 or 0> (see memcmp()) for unequal cache keys
*/
ssize_t nanocoap_cache_key_compare(uint8_t *cache_key1, uint8_t *cache_key2);

#ifdef __cplusplus
}
#endif
#endif /* NET_NANOCOAP_CACHE_H */
/** @} */
Loading

0 comments on commit 02fb040

Please sign in to comment.