From 7cda842a007d3ace73ce46bdd239a8b0753c362d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cenk=20G=C3=BCndo=C4=9Fan?= Date: Sun, 15 Mar 2020 23:00:25 +0100 Subject: [PATCH] examples/gcoap: add handling of proxied requests --- examples/gcoap/gcoap_cli.c | 133 ++++++++++++++++++++++++++++++------- 1 file changed, 108 insertions(+), 25 deletions(-) diff --git a/examples/gcoap/gcoap_cli.c b/examples/gcoap/gcoap_cli.c index c982252f4d..308d445387 100644 --- a/examples/gcoap/gcoap_cli.c +++ b/examples/gcoap/gcoap_cli.c @@ -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 [%%iface] \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 \n", argv[0]); + printf("usage: %s \n", argv[0]); return 1; }