mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
18134: nanocoap_link_format: add helper function to parse Link Format r=kaspar030 a=benpicco 18738: nanocoap_sock: implement nanocoap_sock_delete() r=maribu a=benpicco 18939: gnrc_ipv6_nib: clean up _resolve_addr() r=maribu a=benpicco 19118: sys/ztimer: ztimer_mock: guard ztimer_ondemand static functions r=kaspar030 a=kaspar030 Co-authored-by: Benjamin Valentin <benpicco@beuth-hochschule.de> Co-authored-by: Benjamin Valentin <benjamin.valentin@ml-pa.com> Co-authored-by: Benjamin Valentin <benjamin.valentin@bht-berlin.de> Co-authored-by: Kaspar Schleiser <kaspar@schleiser.de>
This commit is contained in:
commit
53176f7b9e
@ -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
|
||||
|
72
sys/include/net/nanocoap/link_format.h
Normal file
72
sys/include/net/nanocoap/link_format.h
Normal file
@ -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 <benjamin.valentin@ml-pa.com>
|
||||
*/
|
||||
#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 */
|
||||
/** @} */
|
@ -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.
|
||||
*
|
||||
|
109
sys/net/application_layer/nanocoap/link_format.c
Normal file
109
sys/net/application_layer/nanocoap/link_format.c
Normal file
@ -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 <benjamin.valentin@ml-pa.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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) */
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -23,8 +23,10 @@
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#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));
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 <get|post|put> <url> [data]\n", argv[0]);
|
||||
printf("usage: %s <get|post|put|delete> <url> [data]\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user