Skip to content

Commit

Permalink
gcoap/forward_proxy: integrate nanocoap_cache
Browse files Browse the repository at this point in the history
  • Loading branch information
cgundogan committed May 13, 2020
1 parent 437e728 commit 7cf2d95
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
2 changes: 1 addition & 1 deletion sys/include/net/gcoap/forward_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void gcoap_forward_proxy_init(void);
/**
* @brief Handles proxied requests
*
* @param[in] pkt Packet to parse
* @param[in] pkt The incoming request
* @param[in] client Endpoint of the client
*
* @return 0 if parsing was successful
Expand Down
93 changes: 87 additions & 6 deletions sys/net/application_layer/gcoap/forward_proxy/forward_proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@
#include "net/gcoap.h"
#include "net/gcoap/forward_proxy.h"
#include "uri_parser.h"
#include "net/nanocoap/cache.h"

#define ENABLE_DEBUG (0)
#include "debug.h"

typedef struct {
int in_use;
sock_udp_ep_t ep;
#if IS_ACTIVE(MODULE_NANOCOAP_CACHE)
uint8_t cache_key[NANOCOAP_CACHE_KEY_LENGTH];
#endif
} client_ep_t;

static uint8_t proxy_req_buf[CONFIG_GCOAP_PDU_BUF_SIZE];
Expand Down Expand Up @@ -51,8 +55,61 @@ gcoap_listener_t forward_proxy_listener = {
void gcoap_forward_proxy_init(void)
{
gcoap_register_listener(&forward_proxy_listener);

/* initialize the nanocoap cache operation, if compiled */
if (IS_ACTIVE(MODULE_NANOCOAP_CACHE)) {
nanocoap_cache_init();
}
}

static int _cache_build_response(nanocoap_cache_entry_t *ce,
coap_pkt_t *pdu,
uint8_t *buf,
size_t len)
{
/* Use the same code from the cached content. Use other header
* fields from the incoming request */
gcoap_resp_init(pdu, buf, len, ce->response_pkt.hdr->code);
/* copy all options and possible payload from the cached response
* to the new response */
unsigned header_len_req = coap_get_total_hdr_len(pdu);
unsigned header_len_cached = coap_get_total_hdr_len(&ce->response_pkt);
unsigned opt_payload_len = ce->response_len - header_len_cached;

memcpy((buf + header_len_req),
(ce->response_buf + header_len_cached),
opt_payload_len);
return header_len_req + opt_payload_len;
}

static int _cache_lookup_and_process(coap_pkt_t *pdu,
uint8_t *buf,
size_t len,
client_ep_t *cep)
{
(void) cep;

uint8_t cache_key[SHA256_DIGEST_LENGTH];
uint64_t now = xtimer_now_usec64();
nanocoap_cache_key_generate(pdu, cache_key);
nanocoap_cache_entry_t *ce = nanocoap_cache_key_lookup(cache_key);

/* cache hit, methods are equal, and cache entry is not stale */
if (ce &&
(ce->request_method == coap_get_code(pdu)) &&
(ce->max_age > now)) {
/* use response from cache */
return _cache_build_response(ce, pdu, buf, len);
}

#if IS_ACTIVE(MODULE_NANOCOAP_CACHE)
memcpy(cep->cache_key, cache_key, NANOCOAP_CACHE_KEY_LENGTH);
#endif

return 0;
}


static client_ep_t *_allocate_client_ep(sock_udp_ep_t *ep)
{
client_ep_t *cep;
Expand Down Expand Up @@ -94,24 +151,25 @@ static int _request_matcher_forward_proxy(const coap_pkt_t *pdu,
static ssize_t _forward_proxy_handler(coap_pkt_t *pdu, uint8_t *buf,
size_t len, void *ctx)
{
int pdu_len = 0;
sock_udp_ep_t *remote = (sock_udp_ep_t *)ctx;

int proxy_res = gcoap_forward_proxy_request_process(pdu, remote);
pdu_len = gcoap_forward_proxy_request_process(pdu, remote);

/* Out of memory, reply with 5.00 */
if (proxy_res == -ENOMEM) {
if (pdu_len == -ENOMEM) {
return gcoap_response(pdu, buf, len, COAP_CODE_INTERNAL_SERVER_ERROR);
}
/* Proxy-Uri malformed, reply with 4.02 */
else if (proxy_res == -EINVAL) {
else if (pdu_len == -EINVAL) {
return gcoap_response(pdu, buf, len, COAP_CODE_BAD_OPTION);
}
/* scheme not supported */
else if (proxy_res == -EPERM) {
else if (pdu_len == -EPERM) {
return gcoap_response(pdu, buf, len, COAP_CODE_PROXYING_NOT_SUPPORTED);
}

return 0;
return pdu_len;
}

static bool _parse_endpoint(sock_udp_ep_t *remote,
Expand Down Expand Up @@ -200,12 +258,22 @@ static void _forward_resp_handler(const gcoap_request_memo_t *memo,
{
(void) remote; /* this is the origin server */
client_ep_t *cep = (client_ep_t *)memo->context;
coap_pkt_t req;

req.hdr = (coap_hdr_t *) &memo->msg.hdr_buf[0];

/* forward the response packet as-is to the client */
gcoap_forward_proxy_dispatch((uint8_t *)pdu->hdr,
(pdu->payload -
(uint8_t *)pdu->hdr + pdu->payload_len),
&cep->ep);

#if IS_ACTIVE(MODULE_NANOCOAP_CACHE)
size_t pdu_len = pdu->payload_len +
(pdu->payload - (uint8_t *)pdu->hdr);
nanocoap_cache_process(cep->cache_key, coap_get_code(&req), pdu, pdu_len);
#endif

_free_client_ep(cep);
}

Expand Down Expand Up @@ -322,7 +390,6 @@ int gcoap_forward_proxy_request_process(coap_pkt_t *pkt,
sock_udp_ep_t *client) {
char *uri;
uri_parser_result_t urip;

ssize_t optlen = 0;

client_ep_t *cep = _allocate_client_ep(client);
Expand All @@ -331,6 +398,20 @@ int gcoap_forward_proxy_request_process(coap_pkt_t *pkt,
return -ENOMEM;
}

if (IS_ACTIVE(MODULE_NANOCOAP_CACHE)) {
int pdu_len = _cache_lookup_and_process(pkt,
(uint8_t *)pkt->hdr,
CONFIG_GCOAP_PDU_BUF_SIZE,
cep);
/* if a valid cache entry was found, then pdu_len contains the
* length of that response message */
if (pdu_len > 0) {
_free_client_ep(cep);
return pdu_len;
}
/* if there was no cache hit, then we continue forwarding */
}

optlen = coap_get_proxy_uri(pkt, &uri);

if (optlen < 0) {
Expand Down

0 comments on commit 7cf2d95

Please sign in to comment.