mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:52:44 +01:00
Merge pull request #20454 from mariemC/mariem/coap-coaps-forward-proxy
gcoap: add coaps forward proxy
This commit is contained in:
commit
a5996e22b8
@ -70,6 +70,7 @@ PSEUDOMODULES += evtimer_mbox
|
|||||||
PSEUDOMODULES += fatfs_vfs_format
|
PSEUDOMODULES += fatfs_vfs_format
|
||||||
PSEUDOMODULES += fmt_%
|
PSEUDOMODULES += fmt_%
|
||||||
PSEUDOMODULES += gcoap_forward_proxy
|
PSEUDOMODULES += gcoap_forward_proxy
|
||||||
|
PSEUDOMODULES += gcoap_forward_proxy_thread
|
||||||
PSEUDOMODULES += gcoap_fileserver
|
PSEUDOMODULES += gcoap_fileserver
|
||||||
PSEUDOMODULES += gcoap_dtls
|
PSEUDOMODULES += gcoap_dtls
|
||||||
## @addtogroup net_gcoap_dns
|
## @addtogroup net_gcoap_dns
|
||||||
|
@ -471,6 +471,10 @@ ifneq (,$(filter gcoap_forward_proxy,$(USEMODULE)))
|
|||||||
USEMODULE += uri_parser
|
USEMODULE += uri_parser
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter gcoap_forward_proxy_thread,$(USEMODULE)))
|
||||||
|
USEMODULE += gcoap_forward_proxy
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter gcoap_dtls,$(USEMODULE)))
|
ifneq (,$(filter gcoap_dtls,$(USEMODULE)))
|
||||||
USEMODULE += gcoap
|
USEMODULE += gcoap
|
||||||
USEMODULE += dsm
|
USEMODULE += dsm
|
||||||
|
@ -6,3 +6,7 @@ endif
|
|||||||
CONFIG_GCOAP_PDU_BUF_SIZE := $(or $(CONFIG_GCOAP_PDU_BUF_SIZE),128)
|
CONFIG_GCOAP_PDU_BUF_SIZE := $(or $(CONFIG_GCOAP_PDU_BUF_SIZE),128)
|
||||||
# the initial DTLS handshake may exceed the block size
|
# the initial DTLS handshake may exceed the block size
|
||||||
DTLS_MAX_BUF ?= $(shell echo $$(((${CONFIG_GCOAP_PDU_BUF_SIZE} + 36) > 200 ? (${CONFIG_GCOAP_PDU_BUF_SIZE} + 36) : 200 )))
|
DTLS_MAX_BUF ?= $(shell echo $$(((${CONFIG_GCOAP_PDU_BUF_SIZE} + 36) > 200 ? (${CONFIG_GCOAP_PDU_BUF_SIZE} + 36) : 200 )))
|
||||||
|
|
||||||
|
ifneq (,$(filter gcoap_forward_proxy,$(USEMODULE)))
|
||||||
|
INCLUDES += -I$(RIOTBASE)/sys/net/application_layer/gcoap/include
|
||||||
|
endif
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "net/nanocoap/cache.h"
|
#include "net/nanocoap/cache.h"
|
||||||
#include "ztimer.h"
|
#include "ztimer.h"
|
||||||
|
|
||||||
|
#include "forward_proxy_internal.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG 0
|
#define ENABLE_DEBUG 0
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
@ -34,16 +36,7 @@
|
|||||||
#define CLIENT_EP_FLAGS_ETAG_LEN_MASK 0x0f
|
#define CLIENT_EP_FLAGS_ETAG_LEN_MASK 0x0f
|
||||||
#define CLIENT_EP_FLAGS_ETAG_LEN_POS 0U
|
#define CLIENT_EP_FLAGS_ETAG_LEN_POS 0U
|
||||||
|
|
||||||
typedef struct {
|
extern kernel_pid_t forward_proxy_pid;
|
||||||
sock_udp_ep_t ep;
|
|
||||||
uint16_t mid;
|
|
||||||
uint8_t flags;
|
|
||||||
#if IS_USED(MODULE_NANOCOAP_CACHE)
|
|
||||||
uint8_t req_etag[COAP_ETAG_LENGTH_MAX];
|
|
||||||
#endif
|
|
||||||
ztimer_t empty_ack_timer;
|
|
||||||
event_t event;
|
|
||||||
} client_ep_t;
|
|
||||||
|
|
||||||
extern uint16_t gcoap_next_msg_id(void);
|
extern uint16_t gcoap_next_msg_id(void);
|
||||||
extern void gcoap_forward_proxy_post_event(void *arg);
|
extern void gcoap_forward_proxy_post_event(void *arg);
|
||||||
@ -87,6 +80,9 @@ gcoap_listener_t forward_proxy_listener = {
|
|||||||
void gcoap_forward_proxy_init(void)
|
void gcoap_forward_proxy_init(void)
|
||||||
{
|
{
|
||||||
gcoap_register_listener(&forward_proxy_listener);
|
gcoap_register_listener(&forward_proxy_listener);
|
||||||
|
if (IS_ACTIVE(MODULE_GCOAP_FORWARD_PROXY_THREAD)) {
|
||||||
|
gcoap_forward_proxy_thread_init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static client_ep_t *_allocate_client_ep(const sock_udp_ep_t *ep)
|
static client_ep_t *_allocate_client_ep(const sock_udp_ep_t *ep)
|
||||||
@ -99,6 +95,7 @@ static client_ep_t *_allocate_client_ep(const sock_udp_ep_t *ep)
|
|||||||
_cep_set_in_use(cep);
|
_cep_set_in_use(cep);
|
||||||
_cep_set_req_etag(cep, NULL, 0);
|
_cep_set_req_etag(cep, NULL, 0);
|
||||||
memcpy(&cep->ep, ep, sizeof(*ep));
|
memcpy(&cep->ep, ep, sizeof(*ep));
|
||||||
|
DEBUG("Client_ep is allocated %p\n", (void *)cep);
|
||||||
return cep;
|
return cep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,7 +105,9 @@ static client_ep_t *_allocate_client_ep(const sock_udp_ep_t *ep)
|
|||||||
static void _free_client_ep(client_ep_t *cep)
|
static void _free_client_ep(client_ep_t *cep)
|
||||||
{
|
{
|
||||||
ztimer_remove(ZTIMER_MSEC, &cep->empty_ack_timer);
|
ztimer_remove(ZTIMER_MSEC, &cep->empty_ack_timer);
|
||||||
memset(cep, 0, sizeof(*cep));
|
/* timer removed but event could be queued */
|
||||||
|
cep->flags = 0;
|
||||||
|
DEBUG("Client_ep is freed %p\n", (void *)cep);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _request_matcher_forward_proxy(gcoap_listener_t *listener,
|
static int _request_matcher_forward_proxy(gcoap_listener_t *listener,
|
||||||
@ -390,24 +389,34 @@ static int _gcoap_forward_proxy_copy_options(coap_pkt_t *pkt,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int gcoap_forward_proxy_req_send(client_ep_t *cep)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
if ((len = gcoap_req_send((uint8_t *)cep->pdu.hdr, coap_get_total_len(&cep->pdu),
|
||||||
|
&cep->server_ep, _forward_resp_handler, cep,
|
||||||
|
GCOAP_SOCKET_TYPE_UNDEF)) <= 0) {
|
||||||
|
DEBUG("gcoap_forward_proxy_req_send(): gcoap_req_send failed %d\n", len);
|
||||||
|
_free_client_ep(cep);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt,
|
static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt,
|
||||||
client_ep_t *client_ep,
|
client_ep_t *client_ep,
|
||||||
uri_parser_result_t *urip)
|
uri_parser_result_t *urip)
|
||||||
{
|
{
|
||||||
coap_pkt_t pkt;
|
|
||||||
sock_udp_ep_t origin_server_ep;
|
|
||||||
|
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
gcoap_request_memo_t *memo = NULL;
|
gcoap_request_memo_t *memo = NULL;
|
||||||
|
|
||||||
if (!_parse_endpoint(&origin_server_ep, urip)) {
|
if (!_parse_endpoint(&client_ep->server_ep, urip)) {
|
||||||
|
_free_client_ep(client_ep);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do not forward requests if they already exist, e.g., due to CON
|
/* do not forward requests if they already exist, e.g., due to CON
|
||||||
and retransmissions. In the future, the proxy should set an
|
and retransmissions. In the future, the proxy should set an
|
||||||
empty ACK message to stop the retransmissions of a client */
|
empty ACK message to stop the retransmissions of a client */
|
||||||
gcoap_forward_proxy_find_req_memo(&memo, client_pkt, &origin_server_ep);
|
gcoap_forward_proxy_find_req_memo(&memo, client_pkt, &client_ep->server_ep);
|
||||||
if (memo) {
|
if (memo) {
|
||||||
DEBUG("gcoap_forward_proxy: request already exists, ignore!\n");
|
DEBUG("gcoap_forward_proxy: request already exists, ignore!\n");
|
||||||
_free_client_ep(client_ep);
|
_free_client_ep(client_ep);
|
||||||
@ -424,28 +433,37 @@ static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt,
|
|||||||
|
|
||||||
unsigned token_len = coap_get_token_len(client_pkt);
|
unsigned token_len = coap_get_token_len(client_pkt);
|
||||||
|
|
||||||
coap_pkt_init(&pkt, proxy_req_buf, CONFIG_GCOAP_PDU_BUF_SIZE,
|
coap_pkt_init(&client_ep->pdu, proxy_req_buf, CONFIG_GCOAP_PDU_BUF_SIZE,
|
||||||
sizeof(coap_hdr_t) + token_len);
|
sizeof(coap_hdr_t) + token_len);
|
||||||
|
|
||||||
pkt.hdr->ver_t_tkl = client_pkt->hdr->ver_t_tkl;
|
client_ep->pdu.hdr->ver_t_tkl = client_pkt->hdr->ver_t_tkl;
|
||||||
pkt.hdr->code = client_pkt->hdr->code;
|
client_ep->pdu.hdr->code = client_pkt->hdr->code;
|
||||||
pkt.hdr->id = client_pkt->hdr->id;
|
client_ep->pdu.hdr->id = client_pkt->hdr->id;
|
||||||
|
|
||||||
if (token_len) {
|
if (token_len) {
|
||||||
memcpy(coap_get_token(&pkt), coap_get_token(client_pkt), token_len);
|
memcpy(coap_get_token(&client_ep->pdu), coap_get_token(client_pkt), token_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy all options from client_pkt to pkt */
|
/* copy all options from client_pkt to pkt */
|
||||||
len = _gcoap_forward_proxy_copy_options(&pkt, client_pkt, client_ep, urip);
|
len = _gcoap_forward_proxy_copy_options(&client_ep->pdu, client_pkt, client_ep, urip);
|
||||||
|
|
||||||
if (len == -EINVAL) {
|
if (len == -EINVAL) {
|
||||||
|
_free_client_ep(client_ep);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (IS_USED(MODULE_GCOAP_FORWARD_PROXY_THREAD)) {
|
||||||
|
/* WORKAROUND: DTLS communication is blocking the gcoap thread,
|
||||||
|
* therefore the communication should be handled in the proxy thread */
|
||||||
|
|
||||||
|
msg_t msg = { .type = GCOAP_FORWARD_PROXY_MSG_SEND,
|
||||||
|
.content.ptr = client_ep
|
||||||
|
};
|
||||||
|
msg_send(&msg, forward_proxy_pid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len = gcoap_forward_proxy_req_send(client_ep);
|
||||||
|
}
|
||||||
|
|
||||||
len = gcoap_req_send((uint8_t *)pkt.hdr, len,
|
|
||||||
&origin_server_ep,
|
|
||||||
_forward_resp_handler, (void *)client_ep,
|
|
||||||
GCOAP_SOCKET_TYPE_UNDEF);
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,10 +502,11 @@ int gcoap_forward_proxy_request_process(coap_pkt_t *pkt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* target is using CoAP */
|
/* target is using CoAP */
|
||||||
if (!strncmp("coap", urip.scheme, urip.scheme_len)) {
|
if (!strncmp("coap", urip.scheme, urip.scheme_len) ||
|
||||||
|
!strncmp("coaps", urip.scheme, urip.scheme_len)) {
|
||||||
|
/* client context ownership is passed to gcoap_forward_proxy_req_send() */
|
||||||
int res = _gcoap_forward_proxy_via_coap(pkt, cep, &urip);
|
int res = _gcoap_forward_proxy_via_coap(pkt, cep, &urip);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
_free_client_ep(cep);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
65
sys/net/application_layer/gcoap/forward_proxy_thread.c
Normal file
65
sys/net/application_layer/gcoap/forward_proxy_thread.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 ML!PA Consulting GmbH
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Forward Proxy Thread
|
||||||
|
*
|
||||||
|
* @author Mariem Charrada <mariem.charrada@ml-pa.com>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "msg.h"
|
||||||
|
#include "net/gcoap.h"
|
||||||
|
#include "net/gcoap/forward_proxy.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
|
#include "forward_proxy_internal.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG 0
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static char _forward_proxy_thread[GCOAP_PROXY_STACK_SIZE];
|
||||||
|
kernel_pid_t forward_proxy_pid = KERNEL_PID_UNDEF;
|
||||||
|
|
||||||
|
static void *_forward_proxy_thread_start(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
|
||||||
|
msg_t _forward_proxy_msg_queue[CONFIG_GCOAP_REQ_WAITING_MAX];
|
||||||
|
msg_init_queue(_forward_proxy_msg_queue, ARRAY_SIZE(_forward_proxy_msg_queue));
|
||||||
|
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
msg_receive(&msg);
|
||||||
|
client_ep_t *cep = (client_ep_t *)msg.content.ptr;
|
||||||
|
switch (msg.type) {
|
||||||
|
case GCOAP_FORWARD_PROXY_MSG_SEND: {
|
||||||
|
gcoap_forward_proxy_req_send(cep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DEBUG_PUTS("_forward_proxy_thread_start: unknown message type\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gcoap_forward_proxy_thread_init(void)
|
||||||
|
{
|
||||||
|
forward_proxy_pid = thread_create(_forward_proxy_thread, sizeof(_forward_proxy_thread),
|
||||||
|
THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST,
|
||||||
|
_forward_proxy_thread_start, NULL, "gcoap proxy");
|
||||||
|
if (forward_proxy_pid <= KERNEL_PID_UNDEF) {
|
||||||
|
DEBUG_PUTS("gcoap_forward_proxy_thread_init(): thread_create failed\n");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 ML!PA Consulting GmbH
|
||||||
|
*
|
||||||
|
* 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_gcoap_forward_proxy_thread GCoAP Forward Proxy Thread
|
||||||
|
* @ingroup net_gcoap
|
||||||
|
* @brief Forward proxy thread implementation for GCoAP
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Definitions for the GCoAP forward proxy internal communication
|
||||||
|
*
|
||||||
|
* @author Mariem Charrada <mariem.charrada@ml-pa.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FORWARD_PROXY_INTERNAL_H
|
||||||
|
#define FORWARD_PROXY_INTERNAL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "net/coap.h"
|
||||||
|
#include "net/gcoap.h"
|
||||||
|
#include "net/sock/udp.h"
|
||||||
|
#include "ztimer.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief client ep structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
coap_pkt_t pdu; /**< forward CoAP PDU */
|
||||||
|
sock_udp_ep_t server_ep; /**< forward Server endpoint */
|
||||||
|
sock_udp_ep_t ep; /**< client endpoint */
|
||||||
|
uint16_t mid; /**< message ID */
|
||||||
|
uint8_t flags; /**< client flags */
|
||||||
|
#if IS_USED(MODULE_NANOCOAP_CACHE)
|
||||||
|
uint8_t req_etag[COAP_ETAG_LENGTH_MAX]; /**< request ETag */
|
||||||
|
#endif
|
||||||
|
ztimer_t empty_ack_timer; /**< empty ACK timer */
|
||||||
|
event_t event; /**< client event */
|
||||||
|
} client_ep_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stack size for the forward proxy thread
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef GCOAP_PROXY_STACK_SIZE
|
||||||
|
#define GCOAP_PROXY_STACK_SIZE (THREAD_STACKSIZE_DEFAULT + DEBUG_EXTRA_STACKSIZE \
|
||||||
|
+ sizeof(coap_pkt_t) + GCOAP_DTLS_EXTRA_STACKSIZE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Definition of forward proxy thread msgs.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
GCOAP_FORWARD_PROXY_MSG_SEND,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the forward proxy thread
|
||||||
|
*/
|
||||||
|
void gcoap_forward_proxy_thread_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Forward the CoAP request to the server
|
||||||
|
* The client endpoint is passed as an argument
|
||||||
|
* and freed if the send failed.
|
||||||
|
*
|
||||||
|
* @param[in] cep client endpoint
|
||||||
|
* @return @ref gcoap_req_send
|
||||||
|
*/
|
||||||
|
int gcoap_forward_proxy_req_send(client_ep_t *cep);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* FORWARD_PROXY_INTERNAL_H */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user