Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nanocoap: cache for CoAP responses #13889

Merged
merged 3 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
cgundogan marked this conversation as resolved.
Show resolved Hide resolved
#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 <[email protected]>
*/

#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);
cgundogan marked this conversation as resolved.
Show resolved Hide resolved

/**
* @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