examples/gcoap: add handling of proxied requests
This commit is contained in:
parent
50900a1fbe
commit
7cda842a00
@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user