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)
#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,
size_t maxlen, coap_link_encoder_ctx_t *context);
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
* start a new request (with a new path) until any blockwise transfer
* 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];
/* Counts requests sent by CLI. */
@ -137,13 +141,25 @@ static void _resp_handler(const gcoap_request_memo_t *memo, coap_pkt_t* pdu,
return;
}
gcoap_req_init(pdu, (uint8_t *)pdu->hdr, CONFIG_GCOAP_PDU_BUF_SIZE,
COAP_METHOD_GET, _last_req_path);
if (_proxied) {
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) {
coap_hdr_set_type(pdu->hdr, COAP_TYPE_CON);
}
block.blknum++;
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);
gcoap_req_send((uint8_t *)pdu->hdr, len, remote,
_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;
size_t bytes_sent;
sock_udp_ep_t remote;
remote.family = AF_INET6;
remote->family = AF_INET6;
/* parse for interface */
char *iface = ipv6_addr_split_iface(addr_str);
if (!iface) {
if (gnrc_netif_numof() == 1) {
/* 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 {
remote.netif = SOCK_ADDR_ANY_NETIF;
remote->netif = SOCK_ADDR_ANY_NETIF;
}
}
else {
int pid = atoi(iface);
if (gnrc_netif_get_by_pid(pid) == NULL) {
puts("gcoap_cli: interface not valid");
return 0;
return false;
}
remote.netif = pid;
remote->netif = pid;
}
/* parse destination address */
if (ipv6_addr_from_str(&addr, addr_str) == NULL) {
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");
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 */
remote.port = atoi(port_str);
if (remote.port == 0) {
remote->port = atoi(port_str);
if (remote->port == 0) {
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) {
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(" CLI requests sent: %u\n", req_count);
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;
}
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;
for (size_t i = 0; i < ARRAY_SIZE(method_codes); i++) {
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)) ||
((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);
memset(_last_req_path, 0, _LAST_REQ_PATH_MAX);
if (strlen(argv[apos+2]) < _LAST_REQ_PATH_MAX) {
memcpy(_last_req_path, argv[apos+2], strlen(argv[apos+2]));
if (uri_len < _LAST_REQ_PATH_MAX) {
memcpy(_last_req_path, uri, uri_len);
}
size_t paylen = (argc == apos + 4) ? strlen(argv[apos+3]) : 0;
if (paylen) {
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);
if (pdu.payload_len >= paylen) {
memcpy(pdu.payload, argv[apos+3], paylen);
@ -374,7 +457,7 @@ int gcoap_cli_cmd(int argc, char **argv)
}
end:
printf("usage: %s <get|post|put|info>\n", argv[0]);
printf("usage: %s <get|post|put|proxy|info>\n", argv[0]);
return 1;
}