examples/gcoap: add handling of proxied requests

This commit is contained in:
Cenk Gündoğan 2020-03-15 23:00:25 +01:00
parent 50900a1fbe
commit 7cda842a00

View File

@ -30,6 +30,10 @@
#define ENABLE_DEBUG (0) #define ENABLE_DEBUG (0)
#include "debug.h" #include "debug.h"
static bool _proxied = false;
static sock_udp_ep_t _proxy_remote;
static char proxy_uri[64];
static ssize_t _encode_link(const coap_resource_t *resource, char *buf, static ssize_t _encode_link(const coap_resource_t *resource, char *buf,
size_t maxlen, coap_link_encoder_ctx_t *context); size_t maxlen, coap_link_encoder_ctx_t *context);
static void _resp_handler(const gcoap_request_memo_t *memo, coap_pkt_t* pdu, static void _resp_handler(const gcoap_request_memo_t *memo, coap_pkt_t* pdu,
@ -58,7 +62,7 @@ static gcoap_listener_t _listener = {
/* Retain request path to re-request if response includes block. User must not /* Retain request path to re-request if response includes block. User must not
* start a new request (with a new path) until any blockwise transfer * start a new request (with a new path) until any blockwise transfer
* completes or times out. */ * completes or times out. */
#define _LAST_REQ_PATH_MAX (32) #define _LAST_REQ_PATH_MAX (64)
static char _last_req_path[_LAST_REQ_PATH_MAX]; static char _last_req_path[_LAST_REQ_PATH_MAX];
/* Counts requests sent by CLI. */ /* Counts requests sent by CLI. */
@ -137,13 +141,25 @@ static void _resp_handler(const gcoap_request_memo_t *memo, coap_pkt_t* pdu,
return; return;
} }
gcoap_req_init(pdu, (uint8_t *)pdu->hdr, CONFIG_GCOAP_PDU_BUF_SIZE, if (_proxied) {
COAP_METHOD_GET, _last_req_path); gcoap_req_init(pdu, (uint8_t *)pdu->hdr, CONFIG_GCOAP_PDU_BUF_SIZE,
COAP_METHOD_GET, NULL);
}
else {
gcoap_req_init(pdu, (uint8_t *)pdu->hdr, CONFIG_GCOAP_PDU_BUF_SIZE,
COAP_METHOD_GET, _last_req_path);
}
if (msg_type == COAP_TYPE_ACK) { if (msg_type == COAP_TYPE_ACK) {
coap_hdr_set_type(pdu->hdr, COAP_TYPE_CON); coap_hdr_set_type(pdu->hdr, COAP_TYPE_CON);
} }
block.blknum++; block.blknum++;
coap_opt_add_block2_control(pdu, &block); coap_opt_add_block2_control(pdu, &block);
if (_proxied) {
coap_opt_add_proxy_uri(pdu, _last_req_path);
}
int len = coap_opt_finish(pdu, COAP_OPT_FINISH_NONE); int len = coap_opt_finish(pdu, COAP_OPT_FINISH_NONE);
gcoap_req_send((uint8_t *)pdu->hdr, len, remote, gcoap_req_send((uint8_t *)pdu->hdr, len, remote,
_resp_handler, memo->context); _resp_handler, memo->context);
@ -214,52 +230,70 @@ static ssize_t _riot_board_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, vo
} }
} }
static size_t _send(uint8_t *buf, size_t len, char *addr_str, char *port_str) static bool _parse_endpoint(sock_udp_ep_t *remote,
char *addr_str, char *port_str)
{ {
ipv6_addr_t addr; ipv6_addr_t addr;
size_t bytes_sent; remote->family = AF_INET6;
sock_udp_ep_t remote;
remote.family = AF_INET6;
/* parse for interface */ /* parse for interface */
char *iface = ipv6_addr_split_iface(addr_str); char *iface = ipv6_addr_split_iface(addr_str);
if (!iface) { if (!iface) {
if (gnrc_netif_numof() == 1) { if (gnrc_netif_numof() == 1) {
/* assign the single interface found in gnrc_netif_numof() */ /* assign the single interface found in gnrc_netif_numof() */
remote.netif = (uint16_t)gnrc_netif_iter(NULL)->pid; remote->netif = (uint16_t)gnrc_netif_iter(NULL)->pid;
} }
else { else {
remote.netif = SOCK_ADDR_ANY_NETIF; remote->netif = SOCK_ADDR_ANY_NETIF;
} }
} }
else { else {
int pid = atoi(iface); int pid = atoi(iface);
if (gnrc_netif_get_by_pid(pid) == NULL) { if (gnrc_netif_get_by_pid(pid) == NULL) {
puts("gcoap_cli: interface not valid"); puts("gcoap_cli: interface not valid");
return 0; return false;
} }
remote.netif = pid; remote->netif = pid;
} }
/* parse destination address */ /* parse destination address */
if (ipv6_addr_from_str(&addr, addr_str) == NULL) { if (ipv6_addr_from_str(&addr, addr_str) == NULL) {
puts("gcoap_cli: unable to parse destination address"); puts("gcoap_cli: unable to parse destination address");
return 0; return false;
} }
if ((remote.netif == SOCK_ADDR_ANY_NETIF) && ipv6_addr_is_link_local(&addr)) { if ((remote->netif == SOCK_ADDR_ANY_NETIF) && ipv6_addr_is_link_local(&addr)) {
puts("gcoap_cli: must specify interface for link local target"); puts("gcoap_cli: must specify interface for link local target");
return 0; return false;
} }
memcpy(&remote.addr.ipv6[0], &addr.u8[0], sizeof(addr.u8)); memcpy(&remote->addr.ipv6[0], &addr.u8[0], sizeof(addr.u8));
/* parse port */ /* parse port */
remote.port = atoi(port_str); remote->port = atoi(port_str);
if (remote.port == 0) { if (remote->port == 0) {
puts("gcoap_cli: unable to parse destination port"); puts("gcoap_cli: unable to parse destination port");
return 0; return false;
} }
bytes_sent = gcoap_req_send(buf, len, &remote, _resp_handler, NULL); return true;
}
static size_t _send(uint8_t *buf, size_t len, char *addr_str, char *port_str)
{
size_t bytes_sent;
sock_udp_ep_t *remote;
if (_proxied) {
remote = &_proxy_remote;
}
else {
sock_udp_ep_t new_remote;
if (!_parse_endpoint(&new_remote, addr_str, port_str)) {
return 0;
}
remote = &new_remote;
}
bytes_sent = gcoap_req_send(buf, len, remote, _resp_handler, NULL);
if (bytes_sent > 0) { if (bytes_sent > 0) {
req_count++; req_count++;
} }
@ -285,10 +319,40 @@ int gcoap_cli_cmd(int argc, char **argv)
printf("CoAP server is listening on port %u\n", CONFIG_GCOAP_PORT); printf("CoAP server is listening on port %u\n", CONFIG_GCOAP_PORT);
printf(" CLI requests sent: %u\n", req_count); printf(" CLI requests sent: %u\n", req_count);
printf("CoAP open requests: %u\n", open_reqs); printf("CoAP open requests: %u\n", open_reqs);
printf("Configured Proxy: ");
if (_proxied) {
char addrstr[IPV6_ADDR_MAX_STR_LEN];
printf("[%s]:%u\n",
ipv6_addr_to_str(addrstr,
(ipv6_addr_t *) &_proxy_remote.addr.ipv6,
sizeof(addrstr)),
_proxy_remote.port);
}
else {
puts("None");
}
return 0; return 0;
} }
else if (strcmp(argv[1], "proxy") == 0) {
if ((argc == 5) && (strcmp(argv[2], "set") == 0)) {
if (!_parse_endpoint(&_proxy_remote, argv[3], argv[4])) {
puts("Could not set proxy");
return 1;
}
_proxied = true;
return 0;
}
if ((argc == 3) && (strcmp(argv[2], "unset") == 0)) {
memset(&_proxy_remote, 0, sizeof(_proxy_remote));
_proxied = false;
return 0;
}
printf("usage: %s proxy set <addr>[%%iface] <port>\n", argv[0]);
printf(" %s proxy unset\n", argv[0]);
return 1;
}
/* if not 'info', must be a method code */ /* if not 'info' and 'proxy', must be a method code */
int code_pos = -1; int code_pos = -1;
for (size_t i = 0; i < ARRAY_SIZE(method_codes); i++) { for (size_t i = 0; i < ARRAY_SIZE(method_codes); i++) {
if (strcmp(argv[1], method_codes[i]) == 0) { if (strcmp(argv[1], method_codes[i]) == 0) {
@ -314,17 +378,36 @@ int gcoap_cli_cmd(int argc, char **argv)
*/ */
if (((argc == apos + 3) && (code_pos == 0)) || if (((argc == apos + 3) && (code_pos == 0)) ||
((argc == apos + 4) && (code_pos != 0))) { ((argc == apos + 4) && (code_pos != 0))) {
gcoap_req_init(&pdu, &buf[0], CONFIG_GCOAP_PDU_BUF_SIZE, code_pos+1, argv[apos+2]);
char *uri = argv[apos+2];
int uri_len = strlen(argv[apos+2]);
if (_proxied) {
uri_len = snprintf(proxy_uri, 64, "coap://[%s]:%s%s", argv[apos], argv[apos+1], uri);
uri = proxy_uri;
gcoap_req_init(&pdu, &buf[0], CONFIG_GCOAP_PDU_BUF_SIZE, code_pos+1, NULL);
}
else{
gcoap_req_init(&pdu, &buf[0], CONFIG_GCOAP_PDU_BUF_SIZE, code_pos+1, uri);
}
coap_hdr_set_type(pdu.hdr, msg_type); coap_hdr_set_type(pdu.hdr, msg_type);
memset(_last_req_path, 0, _LAST_REQ_PATH_MAX); memset(_last_req_path, 0, _LAST_REQ_PATH_MAX);
if (strlen(argv[apos+2]) < _LAST_REQ_PATH_MAX) { if (uri_len < _LAST_REQ_PATH_MAX) {
memcpy(_last_req_path, argv[apos+2], strlen(argv[apos+2])); memcpy(_last_req_path, uri, uri_len);
} }
size_t paylen = (argc == apos + 4) ? strlen(argv[apos+3]) : 0; size_t paylen = (argc == apos + 4) ? strlen(argv[apos+3]) : 0;
if (paylen) { if (paylen) {
coap_opt_add_format(&pdu, COAP_FORMAT_TEXT); coap_opt_add_format(&pdu, COAP_FORMAT_TEXT);
}
if (_proxied) {
coap_opt_add_proxy_uri(&pdu, uri);
}
if (paylen) {
len = coap_opt_finish(&pdu, COAP_OPT_FINISH_PAYLOAD); len = coap_opt_finish(&pdu, COAP_OPT_FINISH_PAYLOAD);
if (pdu.payload_len >= paylen) { if (pdu.payload_len >= paylen) {
memcpy(pdu.payload, argv[apos+3], paylen); memcpy(pdu.payload, argv[apos+3], paylen);
@ -374,7 +457,7 @@ int gcoap_cli_cmd(int argc, char **argv)
} }
end: end:
printf("usage: %s <get|post|put|info>\n", argv[0]); printf("usage: %s <get|post|put|proxy|info>\n", argv[0]);
return 1; return 1;
} }