Skip to content

Commit 50ee56b

Browse files
committed
examples/nanocoap_reverse_proxy: Example reverse proxy
1 parent 23427df commit 50ee56b

File tree

5 files changed

+232
-3
lines changed

5 files changed

+232
-3
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# name of your application
2+
APPLICATION = nanocoap_reverse_proxy
3+
4+
# If no BOARD is found in the environment, use this default:
5+
BOARD ?= native
6+
7+
# This has to be the absolute path to the RIOT base directory:
8+
RIOTBASE ?= $(CURDIR)/../..
9+
10+
NETWORK_STACK ?= gnrc
11+
12+
# Include packages that pull up and auto-init the link layer.
13+
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
14+
USEMODULE += netdev_default
15+
USEMODULE += sock_udp
16+
USEMODULE += ipv6_addr
17+
18+
ifeq ($(NETWORK_STACK),gnrc)
19+
USEMODULE += auto_init_gnrc_netif
20+
# Specify the mandatory networking modules for IPv6
21+
USEMODULE += gnrc_ipv6_default
22+
# Additional networking modules that can be dropped if not needed
23+
USEMODULE += gnrc_icmpv6_echo
24+
endif
25+
ifeq ($(NETWORK_STACK),lwip)
26+
USEMODULE += auto_init_lwip_netif
27+
USEMODULE += lwip_ipv6 lwip_ipv6_autoconfig
28+
endif
29+
30+
# Comment this out to enable code in RIOT that does safety checking
31+
# which is not needed in a production environment but helps in the
32+
# development process:
33+
#DEVELHELP = 1
34+
35+
# Enable fileserver and TCP for boards with plenty of memory
36+
HIGH_MEMORY_BOARDS := native native64 same54-xpro mcb2388
37+
38+
USEMODULE += event_thread
39+
USEMODULE += nanocoap_proxy
40+
USEMODULE += nanocoap_server_ws
41+
USEMODULE += nanocoap_ws_udp_yolo
42+
USEMODULE += ztimer_usec
43+
44+
# async TCP is not supported on GNRC yet
45+
ifeq ($(NETWORK_STACK),lwip)
46+
USEMODULE += nanocoap_server_tcp
47+
endif
48+
49+
# if nanocaop_server_tcp is used: This app makes use of event_thread
50+
# to run the TCP server
51+
ifneq (,$(filter nanocoap_server_tcp,$(USEMODULE)))
52+
USEMODULE += event_thread
53+
endif
54+
55+
# Change this to 0 show compiler invocation lines by default:
56+
QUIET ?= 1
57+
58+
include $(RIOTBASE)/Makefile.include
59+
60+
# Set a custom channel if needed
61+
include $(RIOTMAKE)/default-radio-settings.inc.mk
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
BOARD_INSUFFICIENT_MEMORY := \
2+
arduino-duemilanove \
3+
arduino-leonardo \
4+
arduino-mega2560 \
5+
arduino-nano \
6+
arduino-uno \
7+
atmega328p \
8+
atmega328p-xplained-mini \
9+
atmega8 \
10+
bluepill-stm32f030c8 \
11+
i-nucleo-lrwan1 \
12+
msb-430 \
13+
msb-430h \
14+
nucleo-c031c6 \
15+
nucleo-f030r8 \
16+
nucleo-f031k6 \
17+
nucleo-f042k6 \
18+
nucleo-f303k8 \
19+
nucleo-f334r8 \
20+
nucleo-l011k4 \
21+
nucleo-l031k6 \
22+
nucleo-l053r8 \
23+
olimex-msp430-h1611 \
24+
olimex-msp430-h2618 \
25+
samd10-xmini \
26+
slstk3400a \
27+
stk3200 \
28+
stm32f030f4-demo \
29+
stm32f0discovery \
30+
stm32g0316-disco \
31+
stm32l0538-disco \
32+
telosb \
33+
weact-g030f6 \
34+
z1 \
35+
#
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (C) 2016 Kaspar Schleiser <[email protected]>
3+
*
4+
* This file is subject to the terms and conditions of the GNU Lesser
5+
* General Public License v2.1. See the file LICENSE in the top level
6+
* directory for more details.
7+
*/
8+
9+
/**
10+
* @ingroup examples
11+
* @{
12+
*
13+
* @file
14+
* @brief CoAP example server application (using nanocoap)
15+
*
16+
* @author Kaspar Schleiser <[email protected]>
17+
* @}
18+
*/
19+
20+
#include <stdio.h>
21+
22+
#include "net/nanocoap_sock.h"
23+
#include "time_units.h"
24+
#include "ztimer.h"
25+
26+
#if MODULE_NANOCOAP_SERVER_TCP
27+
# include "event/thread.h"
28+
#endif
29+
30+
#define COAP_INBUF_SIZE (256U)
31+
32+
#define MAIN_QUEUE_SIZE (8)
33+
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
34+
35+
#if MODULE_NANOCOAP_SERVER_TCP
36+
static nanocoap_tcp_server_ctx_t tcp_ctx;
37+
#endif
38+
39+
#if MODULE_NANOCOAP_SERVER_WS && MODULE_NANOCOAP_WS_UDP_YOLO
40+
static coap_ws_over_udp_yolo_init_arg_t _ws_ctx;
41+
#endif
42+
43+
int main(void)
44+
{
45+
puts("RIOT nanocoap example application");
46+
47+
/* nanocoap_server uses gnrc sock which uses gnrc which needs a msg queue */
48+
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
49+
50+
puts("Waiting for address autoconfiguration...");
51+
ztimer_sleep(ZTIMER_USEC, 3 * US_PER_SEC);
52+
53+
/* print network addresses */
54+
printf("{\"IPv6 addresses\": [\"");
55+
netifs_print_ipv6("\", \"");
56+
puts("\"]}");
57+
58+
#if MODULE_NANOCOAP_SERVER_TCP
59+
nanocoap_server_tcp(&tcp_ctx, EVENT_PRIO_MEDIUM, NULL);
60+
printf("CoAP+TCP on PORT %u\n", (unsigned)tcp_ctx.local.port);
61+
#endif
62+
63+
#if MODULE_NANOCOAP_SERVER_WS && MODULE_NANOCOAP_WS_UDP_YOLO
64+
sock_udp_ep_t local_ws = { .port = 1337, .family = AF_INET6 };
65+
nanocoap_server_ws(&coap_ws_over_udp_yolo, &_ws_ctx, &local_ws, sizeof(local_ws));
66+
printf("CoAP+YOLO on PORT %u\n", (unsigned)local_ws.port);
67+
#endif
68+
69+
#if MODULE_NANOCOAP_UDP
70+
/* initialize nanocoap server instance */
71+
uint8_t buf[COAP_INBUF_SIZE];
72+
sock_udp_ep_t local = { .port=COAP_PORT, .family=AF_INET6 };
73+
printf("CoAP (UDP) on PORT %u\n", (unsigned)local.port);
74+
nanocoap_server_udp(&local, buf, sizeof(buf));
75+
#endif
76+
77+
/* should be never reached */
78+
return 0;
79+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (C) 2025 ML!PA Consulting GmbH
3+
*
4+
* This file is subject to the terms and conditions of the GNU Lesser
5+
* General Public License v2.1. See the file LICENSE in the top level
6+
* directory for more details.
7+
*/
8+
9+
#include "event/thread.h"
10+
#include "net/nanocoap.h"
11+
#include "net/nanocoap_proxy.h"
12+
13+
/* set up reverse proxies per supported transport */
14+
#if MODULE_NANOCOAP_WS_UDP_YOLO
15+
static nanocoap_rproxy_ctx_t _yolo_proxy = {
16+
.evq = EVENT_PRIO_MEDIUM,
17+
.scheme = "coap+yolo://"
18+
};
19+
20+
NANOCOAP_RESOURCE(yolo_proxy) {
21+
.path = "/yolo",
22+
.methods = COAP_GET | COAP_PUT | COAP_POST | COAP_DELETE | COAP_MATCH_SUBTREE,
23+
.handler= nanocoap_rproxy_handler,
24+
.context = &_yolo_proxy,
25+
};
26+
#endif
27+
28+
#if MODULE_NANOCOAP_UDP
29+
static nanocoap_rproxy_ctx_t _udp_proxy = {
30+
.evq = EVENT_PRIO_MEDIUM,
31+
.scheme = "coap://"
32+
};
33+
34+
NANOCOAP_RESOURCE(udp_proxy) {
35+
.path = "/udp",
36+
.methods = COAP_GET | COAP_PUT | COAP_POST | COAP_DELETE | COAP_MATCH_SUBTREE,
37+
.handler= nanocoap_rproxy_handler,
38+
.context = &_udp_proxy,
39+
};
40+
#endif
41+
42+
#if MODULE_NANOCOAP_TCP
43+
static nanocoap_rproxy_ctx_t _tcp_proxy = {
44+
.evq = EVENT_PRIO_MEDIUM,
45+
.scheme = "coap://"
46+
};
47+
48+
NANOCOAP_RESOURCE(tcp_proxy) {
49+
.path = "/tcp",
50+
.methods = COAP_GET | COAP_PUT | COAP_POST | COAP_DELETE | COAP_MATCH_SUBTREE,
51+
.handler= _proxy_resource_handler,
52+
.context = &_tcp_proxy,
53+
};
54+
#endif

sys/net/application_layer/nanocoap/proxy.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ static void _forward_request_handler(event_t *ev)
7676
_disconnect(conn);
7777
}
7878

79-
static bool _is_duplicate(nanocoap_rproxy_ctx_t *ctx, coap_pkt_t *pkt, const coap_request_ctx_t *req)
79+
static bool _is_duplicate(nanocoap_rproxy_ctx_t *ctx, const coap_request_ctx_t *req)
8080
{
8181
for (unsigned i = 0; i < CONFIG_NANOCOAP_RPROXY_PARALLEL_FORWARDS; i++) {
8282
if (bf_isset(ctx->forwards_used, i)) {
83-
if (nanocoap_is_duplicate_in_separate_ctx(&ctx->forwards[i].response_ctx, pkt, req)) {
83+
if (nanocoap_server_is_remote_in_response_ctx(&ctx->forwards[i].response_ctx, req)) {
8484
return true;
8585
}
8686
}
@@ -145,7 +145,7 @@ ssize_t nanocoap_rproxy_handler(coap_pkt_t *pkt, uint8_t *buf, size_t len,
145145
{
146146
nanocoap_rproxy_ctx_t *proxy = coap_request_ctx_get_context(ctx);
147147

148-
if (_is_duplicate(proxy, pkt, ctx)) {
148+
if (_is_duplicate(proxy, ctx)) {
149149
DEBUG_PUTS("[reverse proxy] Got duplicate --> empty ACK (if needed)");
150150
return coap_reply_empty_ack(pkt, buf, len);
151151
}

0 commit comments

Comments
 (0)