diff --git a/sys/Makefile.dep b/sys/Makefile.dep index 5bcf39eff9..4ae9d6ae4e 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -724,6 +724,10 @@ ifneq (,$(filter nanocoap_cache,$(USEMODULE))) USEMODULE += hashes endif +ifneq (,$(filter nanocoap_link_format,$(USEMODULE))) + USEMODULE += fmt +endif + ifneq (,$(filter nanocoap_vfs,$(USEMODULE))) USEMODULE += nanocoap_sock USEMODULE += vfs diff --git a/sys/include/net/nanocoap/link_format.h b/sys/include/net/nanocoap/link_format.h new file mode 100644 index 0000000000..e0ea047d32 --- /dev/null +++ b/sys/include/net/nanocoap/link_format.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2022 ML!PA Consulting GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_nanosock + * @brief NanoCoAP Link Format helper functions + * + * @{ + * + * @file + * @brief NanoCoAP Link Format ([RFC 6690](https://www.rfc-editor.org/rfc/rfc6690.html)) + * helper functions + * + * @author Benjamin Valentin + */ +#ifndef NET_NANOCOAP_LINK_FORMAT_H +#define NET_NANOCOAP_LINK_FORMAT_H + +#include "net/nanocoap_sock.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Callback function called for each resource on the directory + * + * @param[in] entry Resource entry from the server + * @param[in] ctx Optional function context + * + * @returns 0 on success + * @returns <0 on error + */ +typedef int (*coap_link_format_handler_t)(char *entry, void *ctx); + +/** + * @brief Downloads the resource behind @p path via blockwise GET + * + * @param[in] sock Connection to the server + * @param[in] path path of the resource + * @param[in] cb Callback to execute for each resource entry + * @param[in] arg Optional callback argument + * + * @returns 0 on success + * @returns <0 on error + */ +int nanocoap_link_format_get(nanocoap_sock_t *sock, const char *path, + coap_link_format_handler_t cb, void *arg); + +/** + * @brief Downloads the resource behind @p url via blockwise GET + * + * @param[in] url URL to the resource + * @param[in] cb Callback to execute for each resource entry + * @param[in] arg Optional callback argument + * + * @returns 0 on success + * @returns <0 on error + */ +int nanocoap_link_format_get_url(const char *url, + coap_link_format_handler_t cb, void *arg); + +#ifdef __cplusplus +} +#endif +#endif /* NET_NANOCOAP_LINK_FORMAT_H */ +/** @} */ diff --git a/sys/include/net/nanocoap_sock.h b/sys/include/net/nanocoap_sock.h index 8e8238c651..27439a2db1 100644 --- a/sys/include/net/nanocoap_sock.h +++ b/sys/include/net/nanocoap_sock.h @@ -327,6 +327,27 @@ ssize_t nanocoap_sock_post_url(const char *url, const void *request, size_t len, void *response, size_t len_max); +/** + * @brief Simple synchronous CoAP (confirmable) DELETE + * + * @param[in] sock socket to use for the request + * @param[in] path remote path to delete + * + * @returns 0 on success + * @returns <0 on error + */ +ssize_t nanocoap_sock_delete(nanocoap_sock_t *sock, const char *path); + +/** + * @brief Simple synchronous CoAP (confirmable) DELETE for URL + * + * @param[in] url URL of the resource that should be deleted + * + * @returns 0 on success + * @returns <0 on error + */ +ssize_t nanocoap_sock_delete_url(const char *url); + /** * @brief Performs a blockwise coap get request on a socket. * diff --git a/sys/net/application_layer/nanocoap/link_format.c b/sys/net/application_layer/nanocoap/link_format.c new file mode 100644 index 0000000000..c80db58dd9 --- /dev/null +++ b/sys/net/application_layer/nanocoap/link_format.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2022 ML!PA Consulting GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_nanocoap + * @{ + * + * @file + * @brief NanoCoAP Link Format parser + * + * @author Benjamin Valentin + * + * @} + */ + +#include "fmt.h" +#include "net/nanocoap/link_format.h" +#include "net/nanocoap_sock.h" +#include "net/sock/util.h" + +struct dir_list_ctx { + char *buf; + char *cur; + char *end; + coap_link_format_handler_t cb; + void *ctx; + char esc_buf[2]; + uint8_t esc_idx; +}; + +static int _dirlist_cb(void *arg, size_t offset, uint8_t *buf, size_t len, int more) +{ + (void)offset; + + struct dir_list_ctx *ctx = arg; + + char *end = (char *)buf + len; + for (char *c = (char *)buf; c != end; ++c) { + + /* start of escape sequence */ + if (*c == '%') { + ctx->esc_idx = 1; + continue; + } + if (ctx->esc_idx) { + /* fill escape buffer */ + ctx->esc_buf[ctx->esc_idx - 1] = *c; + if (++ctx->esc_idx == 3) { + ctx->esc_idx = 0; + *c = scn_u32_hex(ctx->esc_buf, 2); + } else { + continue; + } + } + + if (*c == ',' || ctx->cur == ctx->end) { + int res; + *ctx->cur = 0; + res = ctx->cb(ctx->buf, ctx->ctx); + ctx->cur = ctx->buf; + if (res < 0) { + return res; + } + } else { + *ctx->cur++ = *c; + } + } + + if (!more) { + *ctx->cur = 0; + return ctx->cb(ctx->buf, ctx->ctx); + } + + return 0; +} + +int nanocoap_link_format_get(nanocoap_sock_t *sock, const char *path, + coap_link_format_handler_t cb, void *arg) +{ + char buffer[CONFIG_NANOCOAP_QS_MAX]; + struct dir_list_ctx ctx = { + .buf = buffer, + .end = buffer + sizeof(buffer), + .cur = buffer, + .cb = cb, + .ctx = arg, + }; + return nanocoap_sock_get_blockwise(sock, path, CONFIG_NANOCOAP_BLOCKSIZE_DEFAULT, + _dirlist_cb, &ctx); +} + +int nanocoap_link_format_get_url(const char *url, coap_link_format_handler_t cb, void *arg) +{ + nanocoap_sock_t sock; + int res = nanocoap_sock_url_connect(url, &sock); + if (res) { + return res; + } + + res = nanocoap_link_format_get(&sock, sock_urlpath(url), cb, arg); + nanocoap_sock_close(&sock); + + return res; +} diff --git a/sys/net/application_layer/nanocoap/sock.c b/sys/net/application_layer/nanocoap/sock.c index 40f23283e5..a9ad2b9910 100644 --- a/sys/net/application_layer/nanocoap/sock.c +++ b/sys/net/application_layer/nanocoap/sock.c @@ -425,6 +425,38 @@ ssize_t nanocoap_sock_post_url(const char *url, return _sock_put_post_url(url, COAP_METHOD_POST, request, len, response, len_max); } +ssize_t nanocoap_sock_delete(nanocoap_sock_t *sock, const char *path) +{ + /* buffer for CoAP header */ + uint8_t buffer[CONFIG_NANOCOAP_BLOCK_HEADER_MAX]; + uint8_t *pktpos = buffer; + + coap_pkt_t pkt = { + .hdr = (void *)pktpos, + }; + + pktpos += coap_build_hdr(pkt.hdr, COAP_TYPE_CON, NULL, 0, COAP_METHOD_DELETE, _get_id()); + pktpos += coap_opt_put_uri_path(pktpos, 0, path); + + pkt.payload = pktpos; + + return nanocoap_sock_request_cb(sock, &pkt, NULL, NULL); +} + +ssize_t nanocoap_sock_delete_url(const char *url) +{ + nanocoap_sock_t sock; + int res = nanocoap_sock_url_connect(url, &sock); + if (res) { + return res; + } + + res = nanocoap_sock_delete(&sock, sock_urlpath(url)); + nanocoap_sock_close(&sock); + + return res; +} + ssize_t nanocoap_request(coap_pkt_t *pkt, const sock_udp_ep_t *local, const sock_udp_ep_t *remote, size_t len) { diff --git a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h index 135034b5e3..ab69e40d4f 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h +++ b/sys/net/gnrc/network_layer/ipv6/nib/_nib-arsm.h @@ -249,7 +249,7 @@ bool _is_reachable(_nib_onl_entry_t *entry); #define _set_reachable(netif, nce) (void)netif; (void)nce #define _get_nud_state(nbr) (GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNMANAGED) -#define _set_nud_state(netif, nce, state) (void)netif; (void)nbr; (void)state +#define _set_nud_state(netif, nce, state) (void)netif; (void)nce; (void)state #define _is_reachable(entry) (true) #endif /* CONFIG_GNRC_IPV6_NIB_ARSM || defined(DOXYGEN) */ diff --git a/sys/net/gnrc/network_layer/ipv6/nib/nib.c b/sys/net/gnrc/network_layer/ipv6/nib/nib.c index 3d4cd0cad6..766da7137b 100644 --- a/sys/net/gnrc/network_layer/ipv6/nib/nib.c +++ b/sys/net/gnrc/network_layer/ipv6/nib/nib.c @@ -1251,25 +1251,88 @@ static void _handle_nbr_adv(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, } } -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) static gnrc_pktqueue_t *_alloc_queue_entry(gnrc_pktsnip_t *pkt) { +#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) for (int i = 0; i < CONFIG_GNRC_IPV6_NIB_NUMOF; i++) { if (_queue_pool[i].pkt == NULL) { _queue_pool[i].pkt = pkt; return &_queue_pool[i]; } } +#else + (void)pkt; +#endif /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ return NULL; } -#endif /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ + +static bool _resolve_addr_from_nc(_nib_onl_entry_t *entry, gnrc_netif_t *netif, + gnrc_ipv6_nib_nc_t *nce) +{ + if (entry == NULL) { + return false; + } + + if (IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM)) { + if (!_is_reachable(entry)) { + return false; + } + + if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE) { + _set_nud_state(netif, entry, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY); + _evtimer_add(entry, GNRC_IPV6_NIB_DELAY_TIMEOUT, + &entry->nud_timeout, NDP_DELAY_FIRST_PROBE_MS); + } + } + + _nib_nc_get(entry, nce); + return true; +} + +static bool _enqueue_for_resolve(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt, + _nib_onl_entry_t *entry) +{ + if (!IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) || + _get_nud_state(entry) != GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE) { + gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, pkt); + gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); + return true; + } + + gnrc_pktqueue_t *queue_entry = _alloc_queue_entry(pkt); + + if (queue_entry == NULL) { + DEBUG("nib: can't allocate entry for packet queue " + "dropping packet\n"); + gnrc_pktbuf_release(pkt); + return false; + } + + if (netif != NULL) { + gnrc_pktsnip_t *netif_hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0); + + if (netif_hdr == NULL) { + DEBUG("nib: can't allocate netif header for queue\n"); + gnrc_pktbuf_release(pkt); + queue_entry->pkt = NULL; + return false; + } + gnrc_netif_hdr_set_netif(netif_hdr->data, netif); + queue_entry->pkt = gnrc_pkt_prepend(queue_entry->pkt, netif_hdr); + } + +#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) + gnrc_pktqueue_add(&entry->pktqueue, queue_entry); +#else + (void)entry; +#endif + return true; +} static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif_t *netif, gnrc_pktsnip_t *pkt, gnrc_ipv6_nib_nc_t *nce, _nib_onl_entry_t *entry) { - bool res = false; - if ((netif != NULL) && (netif->device_type == NETDEV_TYPE_SLIP)) { /* XXX: Linux doesn't do neighbor discovery for SLIP so no use sending * NS and since SLIP doesn't have link-layer addresses anyway, we can @@ -1279,107 +1342,57 @@ static bool _resolve_addr(const ipv6_addr_t *dst, gnrc_netif_t *netif, nce->l2addr_len = 0; return true; } -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) - if ((entry != NULL) && _is_reachable(entry)) { - if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_STALE) { - _set_nud_state(netif, entry, GNRC_IPV6_NIB_NC_INFO_NUD_STATE_DELAY); - _evtimer_add(entry, GNRC_IPV6_NIB_DELAY_TIMEOUT, - &entry->nud_timeout, NDP_DELAY_FIRST_PROBE_MS); - } - DEBUG("nib: resolve address %s%%%u from neighbor cache\n", - ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), - _nib_onl_get_if(entry)); - _nib_nc_get(entry, nce); - res = true; - } -#else /* CONFIG_GNRC_IPV6_NIB_ARSM */ - if (entry != NULL) { - DEBUG("nib: resolve address %s%%%u from neighbor cache\n", - ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), - _nib_onl_get_if(entry)); - _nib_nc_get(entry, nce); - res = true; - } -#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ - else if (!(res = _resolve_addr_from_ipv6(dst, netif, nce))) { -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) - bool reset = false; -#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ - DEBUG("nib: resolve address %s by probing neighbors\n", - ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); + /* first check if address is cached */ + if (_resolve_addr_from_nc(entry, netif, nce)) { + DEBUG("nib: resolve address %s%%%u from neighbor cache\n", + ipv6_addr_to_str(addr_str, &entry->ipv6, sizeof(addr_str)), + _nib_onl_get_if(entry)); + return true; + } + + /* directly resolve address if it uses 6lo addressing mode */ + if (_resolve_addr_from_ipv6(dst, netif, nce)) { + DEBUG("nib: resolve l2 address from IPv6 address\n"); + return true; + } + + bool reset = false; + DEBUG("nib: resolve address %s by probing neighbors\n", + ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); + if (entry == NULL) { + entry = _nib_nc_add(dst, netif ? netif->pid : 0, + GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); if (entry == NULL) { - entry = _nib_nc_add(dst, (netif != NULL) ? netif->pid : 0, - GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); - if (entry == NULL) { - DEBUG("nib: can't resolve address, neighbor cache full\n"); - gnrc_pktbuf_release(pkt); - return false; - } -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ROUTER) - if (netif != NULL) { - _call_route_info_cb(netif, - GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, - dst, - (void *)GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); - } -#endif /* CONFIG_GNRC_IPV6_NIB_ROUTER */ -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) - reset = true; -#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ + DEBUG("nib: can't resolve address, neighbor cache full\n"); + gnrc_pktbuf_release(pkt); + return false; } -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) - else if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE) { - /* reduce back-off to possibly resolve neighbor sooner again */ - entry->ns_sent = 3; + if (IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ROUTER) && netif != NULL) { + _call_route_info_cb(netif, + GNRC_IPV6_NIB_ROUTE_INFO_TYPE_NSC, + dst, + (void *)GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE); } -#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ - if (pkt != NULL) { -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_QUEUE_PKT) - if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_INCOMPLETE) { - gnrc_pktqueue_t *queue_entry = _alloc_queue_entry(pkt); - - if (queue_entry != NULL) { - if (netif != NULL) { - gnrc_pktsnip_t *netif_hdr = gnrc_netif_hdr_build( - NULL, 0, NULL, 0 - ); - if (netif_hdr == NULL) { - DEBUG("nib: can't allocate netif header for queue\n"); - gnrc_pktbuf_release(pkt); - queue_entry->pkt = NULL; - return false; - } - gnrc_netif_hdr_set_netif(netif_hdr->data, netif); - queue_entry->pkt = gnrc_pkt_prepend(queue_entry->pkt, - netif_hdr); - } - gnrc_pktqueue_add(&entry->pktqueue, queue_entry); - } - else { - DEBUG("nib: can't allocate entry for packet queue " - "dropping packet\n"); - gnrc_pktbuf_release(pkt); - return false; - } - } - /* pkt != NULL already checked above */ - else { - gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, - pkt); - gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); - } -#else /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ - gnrc_icmpv6_error_dst_unr_send(ICMPV6_ERROR_DST_UNR_ADDR, - pkt); - gnrc_pktbuf_release_error(pkt, EHOSTUNREACH); -#endif /* CONFIG_GNRC_IPV6_NIB_QUEUE_PKT */ - } -#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) - _probe_nbr(entry, reset); -#endif /* CONFIG_GNRC_IPV6_NIB_ARSM */ + reset = true; } - return res; +#if IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM) + else if (_get_nud_state(entry) == GNRC_IPV6_NIB_NC_INFO_NUD_STATE_UNREACHABLE) { + /* reduce back-off to possibly resolve neighbor sooner again */ + entry->ns_sent = 3; + } +#endif + + /* queue packet as we have to do address resolution first */ + if (pkt != NULL && !_enqueue_for_resolve(netif, pkt, entry)) { + return false; + } + + if (IS_ACTIVE(CONFIG_GNRC_IPV6_NIB_ARSM)) { + _probe_nbr(entry, reset); + } + + return false; } static void _handle_snd_na(gnrc_pktsnip_t *pkt) diff --git a/sys/shell/Makefile.dep b/sys/shell/Makefile.dep index a36517319c..6cc8eaaff9 100644 --- a/sys/shell/Makefile.dep +++ b/sys/shell/Makefile.dep @@ -225,6 +225,7 @@ endif ifneq (,$(filter shell_cmd_nanocoap_vfs,$(USEMODULE))) USEMODULE += nanocoap_vfs USEMODULE += vfs_util + USEMODULE += nanocoap_link_format endif ifneq (,$(filter shell_cmd_netstats_neighbor,$(USEMODULE))) USEMODULE += netstats_neighbor diff --git a/sys/shell/cmds/nanocoap_vfs.c b/sys/shell/cmds/nanocoap_vfs.c index d8c754ae11..b35588a55c 100644 --- a/sys/shell/cmds/nanocoap_vfs.c +++ b/sys/shell/cmds/nanocoap_vfs.c @@ -23,8 +23,10 @@ #include #include +#include "net/nanocoap/link_format.h" #include "net/nanocoap_sock.h" #include "net/nanocoap_vfs.h" + #include "shell.h" #include "vfs_default.h" #include "vfs_util.h" @@ -48,6 +50,21 @@ static bool _is_dir(const char *url) return url[len - 1] == '/'; } +static int _resource_cb(char *entry, void *ctx) +{ + (void)ctx; + + char *start = strchr(entry, '<'); + if (start) { + char *end = strchr(entry, '>'); + *end = '\0'; + entry = start + 1; + } + + puts(entry); + return 0; +} + static int _print_cb(void *arg, size_t offset, uint8_t *buf, size_t len, int more) { (void)arg; @@ -61,41 +78,6 @@ static int _print_cb(void *arg, size_t offset, uint8_t *buf, size_t len, int mor return 0; } -static int _print_dir_cb(void *arg, size_t offset, uint8_t *buf, size_t len, int more) -{ - (void)offset; - (void)more; - - struct dir_list_ctx *ctx = arg; - - char *end = (char *)buf + len; - for (char *c = (char *)buf; c < end; ++c) { - if (ctx->cur) { - if (*c == '>' || ctx->cur == ctx->end) { - *ctx->cur = 0; - puts(ctx->buf); - ctx->cur = NULL; - } else { - *ctx->cur++ = *c; - } - } else if (*c == '<') { - ctx->cur = ctx->buf; - } - } - - return 0; -} - -static int _print_dir(const char *url, char *buf, size_t len) -{ - struct dir_list_ctx ctx = { - .buf = buf, - .end = buf + len, - }; - return nanocoap_get_blockwise_url(url, CONFIG_NANOCOAP_BLOCKSIZE_DEFAULT, - _print_dir_cb, &ctx); -} - static int _nanocoap_get_handler(int argc, char **argv) { int res; @@ -109,7 +91,7 @@ static int _nanocoap_get_handler(int argc, char **argv) } if (_is_dir(url) && argc < 3) { - res = _print_dir(url, buffer, sizeof(buffer)); + res = nanocoap_link_format_get_url(url, _resource_cb, NULL); if (res) { printf("Request failed: %s\n", strerror(-res)); } diff --git a/sys/ztimer/mock.c b/sys/ztimer/mock.c index e757054bfb..f1cbe74b36 100644 --- a/sys/ztimer/mock.c +++ b/sys/ztimer/mock.c @@ -119,6 +119,7 @@ static void ztimer_mock_op_cancel(ztimer_clock_t *clock) self->armed = 0; } +#if MODULE_ZTIMER_ONDEMAND static void ztimer_mock_op_start(ztimer_clock_t *clock) { ztimer_mock_t *self = (ztimer_mock_t *)clock; @@ -138,6 +139,7 @@ static void ztimer_mock_op_stop(ztimer_clock_t *clock) DEBUG("zmock_stop: %3u\n", self->calls.stop); self->running = 0; } +#endif static const ztimer_ops_t ztimer_mock_ops = { .set = ztimer_mock_op_set, diff --git a/tests/nanocoap_cli/nanocli_client.c b/tests/nanocoap_cli/nanocli_client.c index b406d8e3d2..b8c8d45e23 100644 --- a/tests/nanocoap_cli/nanocli_client.c +++ b/tests/nanocoap_cli/nanocli_client.c @@ -183,7 +183,7 @@ static int _blockwise_cb(void *arg, size_t offset, uint8_t *buf, size_t len, int int nanotest_client_url_cmd(int argc, char **argv) { /* Ordered like the RFC method code numbers, but off by 1. GET is code 0. */ - const char *method_codes[] = {"get", "post", "put"}; + const char *method_codes[] = { "get", "post", "put", "delete" }; int res; if (argc < 3) { @@ -202,11 +202,12 @@ int nanotest_client_url_cmd(int argc, char **argv) } switch (code_pos) { - case 0: - return nanocoap_get_blockwise_url(argv[2], COAP_BLOCKSIZE_32, - _blockwise_cb, NULL); - case 1: - case 2: + case COAP_METHOD_GET - 1: + res = nanocoap_get_blockwise_url(argv[2], COAP_BLOCKSIZE_32, + _blockwise_cb, NULL); + break; + case COAP_METHOD_POST - 1: + case COAP_METHOD_PUT - 1: ; char response[32]; nanocoap_sock_t sock; @@ -229,6 +230,9 @@ int nanotest_client_url_cmd(int argc, char **argv) printf("response: %s\n", response); } break; + case COAP_METHOD_DELETE - 1: + res = nanocoap_sock_delete_url(argv[2]); + break; default: printf("TODO: implement %s request\n", method_codes[code_pos]); return -1; @@ -240,7 +244,7 @@ int nanotest_client_url_cmd(int argc, char **argv) return res; error: - printf("usage: %s [data]\n", argv[0]); + printf("usage: %s [data]\n", argv[0]); return -1; }