Skip to content

Commit

Permalink
Merge pull request #20043 from bergzand/pr/nanocoap_cache_options
Browse files Browse the repository at this point in the history
nanocoap/cache: Extend with option-only cache keygen
  • Loading branch information
benpicco authored Feb 12, 2024
2 parents f68f977 + 2c9bf3f commit 2eb8ccb
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 6 deletions.
20 changes: 20 additions & 0 deletions sys/include/net/nanocoap/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,26 @@ int nanocoap_cache_del(const nanocoap_cache_entry_t *ce);
*/
void nanocoap_cache_key_generate(const coap_pkt_t *req, uint8_t *cache_key);

/**
* @brief Generates a cache key based on only the options in @p req
*
* @param[in] req The request to generate the cache key from
* @param[out] cache_key The generated cache key of SHA256_DIGEST_LENGTH bytes
*/
void nanocoap_cache_key_options_generate(const coap_pkt_t *req, void *cache_key);

/**
* @brief Generates a cache key based on only the options in @p req without
* any of the blockwise options included in the key
*
* This function can be used to correlate individual requests that are part of a
* blockwise transfer with each other.
*
* @param[in] req The request to generate the cache key from
* @param[out] cache_key The generated cache key of SHA256_DIGEST_LENGTH bytes
*/
void nanocoap_cache_key_blockreq_options_generate(const coap_pkt_t *req, void *cache_key);

/**
* @brief Compares two cache keys.
*
Expand Down
44 changes: 38 additions & 6 deletions sys/net/application_layer/nanocoap/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,10 @@ size_t nanocoap_cache_free_count(void)
return clist_count(&_empty_list_head);
}

void nanocoap_cache_key_generate(const coap_pkt_t *req, uint8_t *cache_key)
static void _cache_key_digest_opts(const coap_pkt_t *req, sha256_context_t *ctx,
bool include_etag,
bool include_blockwise)
{
sha256_context_t ctx;
sha256_init(&ctx);

coap_optpos_t opt = {0, 0};
uint8_t *value;

Expand All @@ -96,17 +95,50 @@ void nanocoap_cache_key_generate(const coap_pkt_t *req, uint8_t *cache_key)
if (optlen >= 0) {
/* gCoAP forward proxy is ETag-aware, so skip ETag option,
* see https://datatracker.ietf.org/doc/html/rfc7252#section-5.4.2 */
if (IS_USED(MODULE_GCOAP_FORWARD_PROXY) && (opt.opt_num == COAP_OPT_ETAG)) {
if ((!include_etag) && (opt.opt_num == COAP_OPT_ETAG)) {
continue;
}
/* skip NoCacheKey,
see https://tools.ietf.org/html/rfc7252#section-5.4.6 */
if ((opt.opt_num & 0x1E) == 0x1C) {
continue;
}
sha256_update(&ctx, value, optlen);
/* Don't include blockwise (on request) so matching between
* blockwise parts is possible */
if ((!include_blockwise) && (
(opt.opt_num == COAP_OPT_BLOCK2) ||
(opt.opt_num == COAP_OPT_BLOCK1)
)) {
continue;
}
sha256_update(ctx, &opt.opt_num, sizeof(opt.opt_num));
sha256_update(ctx, value, optlen);
}
}
}

void nanocoap_cache_key_options_generate(const coap_pkt_t *req, void *cache_key)
{
sha256_context_t ctx;
sha256_init(&ctx);
_cache_key_digest_opts(req, &ctx, true, true);
sha256_final(&ctx, cache_key);
}

void nanocoap_cache_key_blockreq_options_generate(const coap_pkt_t *req, void *cache_key)
{
sha256_context_t ctx;
sha256_init(&ctx);
_cache_key_digest_opts(req, &ctx, true, false);
sha256_final(&ctx, cache_key);
}

void nanocoap_cache_key_generate(const coap_pkt_t *req, uint8_t *cache_key)
{
sha256_context_t ctx;
sha256_init(&ctx);

_cache_key_digest_opts(req, &ctx, !(IS_USED(MODULE_GCOAP_FORWARD_PROXY)), true);
switch (req->hdr->code) {
case COAP_METHOD_FETCH:
sha256_update(&ctx, req->payload, req->payload_len);
Expand Down
55 changes: 55 additions & 0 deletions tests/unittests/tests-nanocoap_cache/tests-nanocoap_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,60 @@ static void test_nanocoap_cache__cachekey(void)
/* compare 3. and 1. packet */
TEST_ASSERT(nanocoap_cache_key_compare(digest2, digest1) > 0);
}

static void test_nanocoap_cache__cachekey_blockwise(void)
{
uint8_t digest1[SHA256_DIGEST_LENGTH];
uint8_t digest2[SHA256_DIGEST_LENGTH];
uint8_t buf1[_BUF_SIZE];
uint8_t buf2[_BUF_SIZE];
coap_pkt_t pkt1;
coap_pkt_t pkt2;
uint16_t msgid = 0xABCD;
uint8_t token[2] = {0xDA, 0xEC};
char path[] = "/time";
size_t len;
coap_block1_t blockopt = {
.offset = 0,
.blknum = 0,
.szx = 2,
.more = 1,
};

/* 1. packet */
len = coap_build_hdr((coap_hdr_t *)&buf1[0], COAP_TYPE_NON,
&token[0], 2, COAP_METHOD_GET, msgid);
coap_pkt_init(&pkt1, &buf1[0], sizeof(buf1), len);
coap_opt_add_string(&pkt1, COAP_OPT_URI_PATH, &path[0], '/');
coap_opt_add_block1_control(&pkt1, &blockopt);
coap_opt_finish(&pkt1, COAP_OPT_FINISH_NONE);


Check warning on line 105 in tests/unittests/tests-nanocoap_cache/tests-nanocoap_cache.c

View workflow job for this annotation

GitHub Actions / static-tests

too many consecutive empty lines
blockopt.offset = 128;
blockopt.blknum = 2;

/* 2. packet */
len = coap_build_hdr((coap_hdr_t *)&buf2[0], COAP_TYPE_NON,
&token[0], 2, COAP_METHOD_GET, msgid);
coap_pkt_init(&pkt2, &buf2[0], sizeof(buf2), len);
coap_opt_add_string(&pkt2, COAP_OPT_URI_PATH, &path[0], '/');
coap_opt_add_block1_control(&pkt1, &blockopt);
coap_opt_finish(&pkt2, COAP_OPT_FINISH_NONE);

nanocoap_cache_key_blockreq_options_generate((const coap_pkt_t *) &pkt1, digest1);
nanocoap_cache_key_blockreq_options_generate((const coap_pkt_t *) &pkt2, digest2);

/* compare 1. and 2. packet. Should be equal except for blockwise */
TEST_ASSERT_EQUAL_INT(0, nanocoap_cache_key_compare(digest1, digest2));

/* Now with the blockwise option in the digest */
nanocoap_cache_key_options_generate((const coap_pkt_t *) &pkt1, digest1);
nanocoap_cache_key_options_generate((const coap_pkt_t *) &pkt2, digest2);

/* compare 1. and 2. packet. Should no longer be equal */
TEST_ASSERT(nanocoap_cache_key_compare(digest2, digest1) != 0);
}

static void test_nanocoap_cache__add(void)
{
uint8_t buf[_BUF_SIZE];
Expand Down Expand Up @@ -263,6 +317,7 @@ Test *tests_nanocoap_cache_tests(void)
new_TestFixture(test_nanocoap_cache__add),
new_TestFixture(test_nanocoap_cache__del),
new_TestFixture(test_nanocoap_cache__cachekey),
new_TestFixture(test_nanocoap_cache__cachekey_blockwise),
new_TestFixture(test_nanocoap_cache__max_age),
};

Expand Down

0 comments on commit 2eb8ccb

Please sign in to comment.