mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
cord: add RD lookup client
This commit is contained in:
parent
88279904c5
commit
869052dcd8
29
Makefile.dep
29
Makefile.dep
@ -916,9 +916,22 @@ ifneq (,$(filter nimble_%,$(USEMODULE)))
|
||||
USEPKG += nimble
|
||||
endif
|
||||
|
||||
ifneq (,$(filter cord_common,$(USEMODULE)))
|
||||
USEMODULE += fmt
|
||||
USEMODULE += luid
|
||||
USEMODULE += gcoap
|
||||
endif
|
||||
|
||||
ifneq (,$(filter cord_lc cord_ep,$(USEMODULE)))
|
||||
USEMODULE += core_thread_flags
|
||||
USEMODULE += cord_common
|
||||
ifneq (,$(filter shell_commands,$(USEMODULE)))
|
||||
USEMODULE += sock_util
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter cord_epsim,$(USEMODULE)))
|
||||
USEMODULE += cord_common
|
||||
USEMODULE += gcoap
|
||||
endif
|
||||
|
||||
ifneq (,$(filter cord_ep_standalone,$(USEMODULE)))
|
||||
@ -926,18 +939,8 @@ ifneq (,$(filter cord_ep_standalone,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter cord_ep,$(USEMODULE)))
|
||||
USEMODULE += cord_common
|
||||
USEMODULE += core_thread_flags
|
||||
USEMODULE += gcoap
|
||||
ifneq (,$(filter shell_commands,$(USEMODULE)))
|
||||
USEMODULE += sock_util
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter cord_common,$(USEMODULE)))
|
||||
USEMODULE += fmt
|
||||
USEMODULE += luid
|
||||
ifneq (,$(filter cord_lc,$(USEMODULE)))
|
||||
USEMODULE += clif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter tlsf-malloc,$(USEMODULE)))
|
||||
|
@ -154,6 +154,9 @@ endif
|
||||
ifneq (,$(filter cord_ep,$(USEMODULE)))
|
||||
DIRS += net/application_layer/cord/ep
|
||||
endif
|
||||
ifneq (,$(filter cord_lc,$(USEMODULE)))
|
||||
DIRS += net/application_layer/cord/lc
|
||||
endif
|
||||
ifneq (,$(filter bluetil_%,$(USEMODULE)))
|
||||
DIRS += net/ble/bluetil
|
||||
endif
|
||||
|
246
sys/include/net/cord/lc.h
Normal file
246
sys/include/net/cord/lc.h
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2018 HAW Hamburg
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_cord_lc CoRE RD Lookup Client
|
||||
* @ingroup net_cord
|
||||
* @brief Library for using RIOT as CoRE Resource Directory (RD) lookup client
|
||||
*
|
||||
* This module implements a CoRE Resource Directory lookup client library, that
|
||||
* allows RIOT nodes to lookup resources, endpoints and groups with resource
|
||||
* directories.
|
||||
* It implements the standard lookup functionality as defined in
|
||||
* draft-ietf-core-resource-directory-23.
|
||||
* @see https://tools.ietf.org/html/draft-ietf-core-resource-directory-23
|
||||
*
|
||||
* ## Lookup modes
|
||||
*
|
||||
* The module defines two types of lookup for interacting with a RD server:
|
||||
*
|
||||
* - raw: result of the lookup is returned as is. No `page` or `count` filter
|
||||
* is applied by default. Use @ref cord_lc_raw() for this mode.
|
||||
* - pre-parsed: result of the lookup is parsed and returned in a
|
||||
* @ref cord_lc_res_t or @ref cord_lc_ep_t depending on the type of the
|
||||
* lookup. The default `count` filter is set to `1` and `page` filter is
|
||||
* incremented after each successful call and resets to `0` when lookup result
|
||||
* is empty. Use @ref cord_lc_res() or cord_lc_ep() for this mode.
|
||||
*
|
||||
* ## Limitations
|
||||
*
|
||||
* Currently, this module cannot do more than a single request concurrently
|
||||
* and the request is fully synchronous. The client can only connects to one
|
||||
* RD server at a time. The client will disconnect when a connection to a new
|
||||
* RD server is made, regardless of whether the connection attempt is successful
|
||||
* or not.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief CoRE Resource Directory lookup interface
|
||||
*
|
||||
* @author Aiman Ismail <muhammadaimanbin.ismail@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef NET_CORD_LC_H
|
||||
#define NET_CORD_LC_H
|
||||
|
||||
#include "net/sock/udp.h"
|
||||
#include "net/nanocoap.h"
|
||||
#include "clif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Return values and error codes used by this module
|
||||
*/
|
||||
enum {
|
||||
CORD_LC_OK = 0, /**< everything went as expected */
|
||||
CORD_LC_TIMEOUT = -1, /**< no response from the network */
|
||||
CORD_LC_ERR = -2, /**< internal error or invalid reply */
|
||||
CORD_LC_OVERFLOW = -3, /**< internal buffers can not handle input */
|
||||
CORD_LC_NORSC = -4, /**< lookup interface not found */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief RD lookup types
|
||||
*/
|
||||
enum {
|
||||
CORD_LC_RES, /**< Resource lookup type */
|
||||
CORD_LC_EP, /**< Endpoint lookup type */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Information about RD server and its lookup interface resources
|
||||
*/
|
||||
typedef struct {
|
||||
const sock_udp_ep_t *remote; /**< Remote endpoint of RD server */
|
||||
char *res_lookif; /**< Resource lookup interface */
|
||||
char *ep_lookif; /**< Endpoint lookup interface */
|
||||
unsigned res_last_page; /**< Page of last resource lookup */
|
||||
unsigned ep_last_page; /**< Page of last endpoint lookup */
|
||||
} cord_lc_rd_t;
|
||||
|
||||
/**
|
||||
* @brief Result of lookup
|
||||
*/
|
||||
struct cord_lc_result {
|
||||
clif_t link; /**< Resource link */
|
||||
clif_attr_t *attrs; /**< Array of Link Format parameters */
|
||||
size_t max_attrs; /**< Max parameters at @p params */
|
||||
};
|
||||
|
||||
typedef struct cord_lc_result cord_lc_res_t; /**< Resource typedef */
|
||||
typedef struct cord_lc_result cord_lc_ep_t; /**< Endpoint typedef */
|
||||
|
||||
/**
|
||||
* @brief Filters to use for a lookup
|
||||
*/
|
||||
typedef struct cord_lc_filter {
|
||||
clif_attr_t *array; /**< Array of filter(s) */
|
||||
size_t len; /**< No. of filters at @p array */
|
||||
struct cord_lc_filter *next; /**< Next set of filters */
|
||||
} cord_lc_filter_t;
|
||||
|
||||
/**
|
||||
* @brief Discover the lookup interfaces of a RD server
|
||||
*
|
||||
* @param[out] rd Information about RD server at @p remote
|
||||
* @param[out] buf Buffer to store found lookup interfaces
|
||||
* @param[in] maxlen Maximum memory available at @p lookif
|
||||
* @param[in] remote Remote endpoint of RD server
|
||||
*
|
||||
* @return bytes used on success
|
||||
* @return CORD_LC_TIMEOUT if the discovery request times out
|
||||
* @return CORD_LC_NORSC if no lookup interfaces found for all types
|
||||
* of lookups
|
||||
* @return CORD_LC_OVERFLOW if not enough memory available for result
|
||||
* @return CORD_LC_ERR on any other internal error
|
||||
*/
|
||||
int cord_lc_rd_init(cord_lc_rd_t *rd, void *buf, size_t maxlen,
|
||||
const sock_udp_ep_t *remote);
|
||||
|
||||
/**
|
||||
* @brief Raw lookup for registered resources/endpoints at a RD server
|
||||
*
|
||||
* To specify the number of resources/endpoints to search for,
|
||||
* `count` and `page` attributes can be used as the filter.
|
||||
* If the same filter used multiple times with different values,
|
||||
* only the last filter will be applied.
|
||||
*
|
||||
* Content format (e.g. link-format, coral) must be set through
|
||||
* filters. If none defined, link-format will be used.
|
||||
*
|
||||
* @param[in] rd RD server to query
|
||||
* @param[in] content_format Data format wanted from RD server
|
||||
* @param[in] lookup_type Lookup type to use
|
||||
* @param[in] filters Filters for the lookup. Can be NULL.
|
||||
* @param[out] result Buffer holding the raw response
|
||||
* @param[in] maxlen Max length of @p result
|
||||
*
|
||||
* @return bytes used on success
|
||||
* @return CORD_LC_NORSC if there is no lookup interface for @p lookup_type
|
||||
* at @p rd
|
||||
* @return CORD_LC_TIMEOUT if lookup timed out
|
||||
* @return CORD_LC_OVERFLOW if not enough memory available for result
|
||||
* @return CORD_LC_ERR on any other internal error
|
||||
*/
|
||||
ssize_t cord_lc_raw(const cord_lc_rd_t *rd, unsigned content_format,
|
||||
unsigned lookup_type, cord_lc_filter_t *filters,
|
||||
void *result, size_t maxlen);
|
||||
|
||||
/**
|
||||
* @brief Get one resource from RD server
|
||||
*
|
||||
* Gets only one resource from specified RD server each time called.
|
||||
* Can be called iteratively to get all the resources on the server.
|
||||
* If there is no more resource on the server, it will return
|
||||
* CORD_LC_NORSC.
|
||||
*
|
||||
* @param[in] rd RD server to query
|
||||
* @param[out] result Result link
|
||||
* @param[in] filters Filters for the lookup
|
||||
* @param[out] buf Result buffer
|
||||
* @param[in] maxlen Maximum memory available at @p buf
|
||||
* @param[in] type Type of resource to query either CORD_LC_EP or
|
||||
* CORD_LC_RES
|
||||
*
|
||||
* @return bytes used on success
|
||||
* @return CORD_LC_INVALIF if the resource lookup interface at @p rd is invalid
|
||||
* @return CORD_LC_NORSC if there is no resource (anymore) at @p rd
|
||||
* @return CORD_LC_TIMEOUT if lookup timed out
|
||||
* @return CORD_LC_OVERFLOW if not enough memory available for result
|
||||
* @return CORD_LC_ERR on any other internal error
|
||||
*/
|
||||
ssize_t _lookup_result(cord_lc_rd_t *rd, cord_lc_res_t *result,
|
||||
cord_lc_filter_t *filters, void *buf, size_t maxlen,
|
||||
unsigned type);
|
||||
|
||||
/**
|
||||
* @brief Get one resource from RD server
|
||||
*
|
||||
* Gets only one resource from specified RD server each time called.
|
||||
* Can be called iteratively to get all the resources on the server.
|
||||
* If there is no more resource on the server, it will return
|
||||
* CORD_LC_NORSC.
|
||||
*
|
||||
* @param[in] rd RD server to query
|
||||
* @param[out] resource Resource link
|
||||
* @param[in] filters Filters for the lookup
|
||||
* @param[out] buf Result buffer
|
||||
* @param[in] maxlen Maximum memory available at @p buf
|
||||
*
|
||||
* @return bytes used on success
|
||||
* @return CORD_LC_INVALIF if the resource lookup interface at @p rd is invalid
|
||||
* @return CORD_LC_NORSC if there is no resource (anymore) at @p rd
|
||||
* @return CORD_LC_TIMEOUT if lookup timed out
|
||||
* @return CORD_LC_OVERFLOW if not enough memory available for result
|
||||
* @return CORD_LC_ERR on any other internal error
|
||||
*/
|
||||
static inline ssize_t cord_lc_res(cord_lc_rd_t *rd, cord_lc_res_t *resource,
|
||||
cord_lc_filter_t *filters, void *buf,
|
||||
size_t maxlen)
|
||||
{
|
||||
return _lookup_result(rd, resource, filters, buf, maxlen, CORD_LC_RES);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get one endpoint from RD server
|
||||
*
|
||||
* Gets only one endpoint from specified RD server each time called.
|
||||
* Can be called iteratively to get all the endpoints on the server.
|
||||
* If there is no more endpoint on the server, it will return
|
||||
* CORD_LC_NORSC.
|
||||
*
|
||||
* @param[in] rd RD server to query
|
||||
* @param[out] endpoint Resource link
|
||||
* @param[in] filters Filters for the lookup
|
||||
* @param[out] buf Result buffer
|
||||
* @param[in] maxlen Maximum memory available at @p buf
|
||||
*
|
||||
* @return bytes used on success
|
||||
* @return CORD_LC_INVALIF if the endpoint lookup interface at @p rd is invalid
|
||||
* @return CORD_LC_NORSC if there is no endpoints (anymore) at @p rd
|
||||
* @return CORD_LC_TIMEOUT if lookup timed out
|
||||
* @return CORD_LC_OVERFLOW if not enough memory available for result
|
||||
* @return CORD_LC_ERR on any other internal error
|
||||
*/
|
||||
static inline ssize_t cord_lc_ep(cord_lc_rd_t *rd, cord_lc_ep_t *endpoint,
|
||||
cord_lc_filter_t *filters, void *buf,
|
||||
size_t maxlen)
|
||||
{
|
||||
return _lookup_result(rd, endpoint, filters, buf, maxlen, CORD_LC_EP);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_CORD_LC_H */
|
||||
/** @} */
|
5
sys/net/application_layer/cord/lc/Makefile
Normal file
5
sys/net/application_layer/cord/lc/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
MODULE = cord_lc
|
||||
|
||||
SRC = cord_lc.c
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
384
sys/net/application_layer/cord/lc/cord_lc.c
Normal file
384
sys/net/application_layer/cord/lc/cord_lc.c
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2018 HAW Hamburg
|
||||
*
|
||||
* 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_cord_lc
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief CoRE Resource Directory lookup implementation
|
||||
*
|
||||
* @author Aiman Ismail <muhammadaimanbin.ismail@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "mutex.h"
|
||||
#include "thread_flags.h"
|
||||
|
||||
#include "net/gcoap.h"
|
||||
#include "net/cord/lc.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
#define FLAG_SUCCESS (0x0001)
|
||||
#define FLAG_TIMEOUT (0x0002)
|
||||
#define FLAG_ERR (0x0004)
|
||||
#define FLAG_OVERFLOW (0x0008)
|
||||
#define FLAG_NORSC (0x0010)
|
||||
#define FLAG_MASK (0x00ff)
|
||||
|
||||
#define BUFSIZE (CONFIG_GCOAP_PDU_BUF_SIZE)
|
||||
#define MAX_EXPECTED_ATTRS (6)
|
||||
|
||||
/* Filter to limit number of link returned by RD server to 1 */
|
||||
#define SINGLE_COUNT_FILTER { \
|
||||
.key = "count", .key_len = strlen("count"), \
|
||||
.value = "1", .value_len = strlen("1") \
|
||||
}
|
||||
|
||||
/* Filter to continue request at page_str */
|
||||
#define PAGE_FILTER(page_str) { \
|
||||
.key = "page", .key_len = strlen("page"), \
|
||||
.value = page_str, .value_len = strlen(page_str) \
|
||||
}
|
||||
|
||||
/* Default filters that will be appended to existing filters for each request.
|
||||
* Consists of count=1 and page=last_page */
|
||||
#define DEFAULT_FILTERS(page_str) { SINGLE_COUNT_FILTER, PAGE_FILTER(page_str) }
|
||||
|
||||
static void _lock(void);
|
||||
static int _sync(void);
|
||||
/* callback for _lookup_raw() request */
|
||||
static void _on_lookup(const gcoap_request_memo_t *memo, coap_pkt_t *pdu,
|
||||
const sock_udp_ep_t *remote);
|
||||
/* callback for _send_rd_init_req() */
|
||||
static void _on_rd_init(const gcoap_request_memo_t *memo, coap_pkt_t *pdu,
|
||||
const sock_udp_ep_t *remote);
|
||||
static ssize_t _add_filters_to_lookup(coap_pkt_t *pkt, cord_lc_filter_t *filters);
|
||||
static int _send_rd_init_req(coap_pkt_t *pkt, const sock_udp_ep_t *remote,
|
||||
void *buf, size_t maxlen);
|
||||
/* do a lookup and returns payload of the response */
|
||||
static ssize_t _lookup_raw(const cord_lc_rd_t *rd, unsigned content_format,
|
||||
unsigned lookup_type, cord_lc_filter_t *filters,
|
||||
void *result, size_t maxlen);
|
||||
|
||||
static char *_result_buf;
|
||||
static size_t _result_buf_len;
|
||||
static uint8_t reqbuf[CONFIG_GCOAP_PDU_BUF_SIZE] = {0};
|
||||
|
||||
static mutex_t _mutex = MUTEX_INIT;
|
||||
static volatile thread_t *_waiter;
|
||||
|
||||
static void _lock(void)
|
||||
{
|
||||
mutex_lock(&_mutex);
|
||||
_waiter = sched_active_thread;
|
||||
}
|
||||
|
||||
static int _sync(void)
|
||||
{
|
||||
thread_flags_t flags = thread_flags_wait_any(FLAG_MASK);
|
||||
|
||||
if (flags & FLAG_ERR) {
|
||||
return CORD_LC_ERR;
|
||||
} else if (flags & FLAG_TIMEOUT) {
|
||||
return CORD_LC_TIMEOUT;
|
||||
} else if (flags & FLAG_OVERFLOW) {
|
||||
return CORD_LC_OVERFLOW;
|
||||
} else if (flags & FLAG_NORSC) {
|
||||
return CORD_LC_NORSC;
|
||||
} else {
|
||||
return CORD_LC_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static void _on_lookup(const gcoap_request_memo_t *memo, coap_pkt_t *pdu,
|
||||
const sock_udp_ep_t *remote)
|
||||
{
|
||||
(void)remote;
|
||||
|
||||
thread_flags_t flag = FLAG_ERR;
|
||||
|
||||
if (memo->state == GCOAP_MEMO_RESP) {
|
||||
unsigned ct = coap_get_content_type(pdu);
|
||||
if (ct != COAP_FORMAT_LINK) {
|
||||
DEBUG("cord_lc: unsupported content format: %u\n", ct);
|
||||
thread_flags_set((thread_t *)_waiter, flag);
|
||||
}
|
||||
if (pdu->payload_len == 0) {
|
||||
flag = FLAG_NORSC;
|
||||
thread_flags_set((thread_t *)_waiter, flag);
|
||||
}
|
||||
if (pdu->payload_len >= _result_buf_len) {
|
||||
flag = FLAG_OVERFLOW;
|
||||
thread_flags_set((thread_t *)_waiter, flag);
|
||||
}
|
||||
memcpy(_result_buf, pdu->payload, pdu->payload_len);
|
||||
memset(_result_buf + pdu->payload_len, 0,
|
||||
_result_buf_len - pdu->payload_len);
|
||||
_result_buf_len = pdu->payload_len;
|
||||
flag = FLAG_SUCCESS;
|
||||
} else if (memo->state == GCOAP_MEMO_TIMEOUT) {
|
||||
flag = FLAG_TIMEOUT;
|
||||
}
|
||||
|
||||
thread_flags_set((thread_t *)_waiter, flag);
|
||||
}
|
||||
|
||||
static ssize_t _add_filters_to_lookup(coap_pkt_t *pkt, cord_lc_filter_t *filters)
|
||||
{
|
||||
cord_lc_filter_t *f = filters;
|
||||
while (f) {
|
||||
for (unsigned i = 0; i < f->len; i++) {
|
||||
clif_attr_t *kv = &(f->array[i]);
|
||||
if (coap_opt_add_uri_query2(pkt, kv->key, kv->key_len, kv->value, kv->value_len) == -1) {
|
||||
return CORD_LC_OVERFLOW;
|
||||
}
|
||||
}
|
||||
f = f->next;
|
||||
}
|
||||
return CORD_LC_OK;
|
||||
}
|
||||
|
||||
static ssize_t _lookup_raw(const cord_lc_rd_t *rd, unsigned content_format,
|
||||
unsigned lookup_type, cord_lc_filter_t *filters,
|
||||
void *result, size_t maxlen)
|
||||
{
|
||||
assert(rd->remote);
|
||||
|
||||
int res;
|
||||
int retval;
|
||||
coap_pkt_t pkt;
|
||||
ssize_t pkt_len;
|
||||
|
||||
char *lookif = (lookup_type == CORD_LC_RES) ? rd->res_lookif : rd-> ep_lookif;
|
||||
res = gcoap_req_init(&pkt, reqbuf, sizeof(reqbuf), COAP_METHOD_GET, lookif);
|
||||
if (res < 0) {
|
||||
DEBUG("cord_lc: failed gcoap_req_init()\n");
|
||||
return CORD_LC_ERR;
|
||||
}
|
||||
|
||||
/* save pointer to result */
|
||||
_result_buf = result;
|
||||
_result_buf_len = maxlen;
|
||||
|
||||
/* add filters */
|
||||
res = _add_filters_to_lookup(&pkt, filters);
|
||||
if (res != CORD_LC_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* set packet options */
|
||||
if (content_format != COAP_FORMAT_LINK) {
|
||||
DEBUG("cord_lc: unsupported content format\n");
|
||||
return CORD_LC_ERR;
|
||||
}
|
||||
coap_hdr_set_type(pkt.hdr, COAP_TYPE_CON);
|
||||
coap_opt_add_uint(&pkt, COAP_OPT_ACCEPT, content_format);
|
||||
|
||||
pkt_len = gcoap_finish(&pkt, 0, COAP_FORMAT_NONE);
|
||||
if (pkt_len < 0) {
|
||||
return CORD_LC_ERR;
|
||||
}
|
||||
res = gcoap_req_send(reqbuf, pkt_len, rd->remote, _on_lookup, NULL);
|
||||
if (res < 0) {
|
||||
return CORD_LC_ERR;
|
||||
}
|
||||
retval = _sync();
|
||||
return (retval == CORD_LC_OK) ? (int)_result_buf_len : retval;
|
||||
}
|
||||
|
||||
static void _on_rd_init(const gcoap_request_memo_t *memo, coap_pkt_t *pdu,
|
||||
const sock_udp_ep_t *remote)
|
||||
{
|
||||
(void)remote;
|
||||
|
||||
thread_flags_t flag = FLAG_NORSC;
|
||||
|
||||
if (memo->state == GCOAP_MEMO_RESP) {
|
||||
unsigned ct = coap_get_content_type(pdu);
|
||||
if (ct != COAP_FORMAT_LINK) {
|
||||
DEBUG("cord_lc: error payload not in link format: %u\n", ct);
|
||||
goto end;
|
||||
}
|
||||
if (pdu->payload_len == 0) {
|
||||
DEBUG("cord_lc: error empty payload\n");
|
||||
goto end;
|
||||
}
|
||||
memcpy(_result_buf, pdu->payload, pdu->payload_len);
|
||||
_result_buf_len = pdu->payload_len;
|
||||
_result_buf[_result_buf_len] = '\0';
|
||||
flag = FLAG_SUCCESS;
|
||||
} else if (memo->state == GCOAP_MEMO_TIMEOUT) {
|
||||
flag = FLAG_TIMEOUT;
|
||||
}
|
||||
|
||||
end:
|
||||
if (flag != FLAG_SUCCESS) {
|
||||
_result_buf = NULL;
|
||||
_result_buf_len = 0;
|
||||
}
|
||||
thread_flags_set((thread_t *)_waiter, flag);
|
||||
}
|
||||
|
||||
static int _send_rd_init_req(coap_pkt_t *pkt, const sock_udp_ep_t *remote,
|
||||
void *buf, size_t maxlen)
|
||||
{
|
||||
|
||||
int res = gcoap_req_init(pkt, buf, maxlen, COAP_METHOD_GET, "/.well-known/core");
|
||||
if (res < 0) {
|
||||
DEBUG("cord_lc: error gcoap_req_init() %d\n", res);
|
||||
return CORD_LC_ERR;
|
||||
}
|
||||
|
||||
coap_hdr_set_type(pkt->hdr, COAP_TYPE_CON);
|
||||
coap_opt_add_uri_query(pkt, "rt", "core.rd-lookup-*");
|
||||
|
||||
ssize_t pkt_len = gcoap_finish(pkt, 0, COAP_FORMAT_NONE);
|
||||
if (pkt_len < 0) {
|
||||
DEBUG("cord_lc: error gcoap_finish() %zd\n", pkt_len);
|
||||
return CORD_LC_ERR;
|
||||
}
|
||||
|
||||
if (!gcoap_req_send(buf, pkt_len, remote, _on_rd_init, NULL)) {
|
||||
DEBUG("cord_lc: error gcoap_req_send()\n");
|
||||
return CORD_LC_ERR;
|
||||
}
|
||||
return _sync();
|
||||
}
|
||||
|
||||
int cord_lc_rd_init(cord_lc_rd_t *rd, void *buf, size_t maxlen,
|
||||
const sock_udp_ep_t *remote)
|
||||
{
|
||||
assert(remote);
|
||||
|
||||
coap_pkt_t pkt;
|
||||
rd->remote = remote;
|
||||
|
||||
_lock();
|
||||
memset(buf, '0', maxlen);
|
||||
_result_buf = buf;
|
||||
_result_buf_len = maxlen;
|
||||
|
||||
int retval = _send_rd_init_req(&pkt, remote, buf, maxlen);
|
||||
if (retval != CORD_LC_OK) {
|
||||
DEBUG("cord_lc: failed to send req %d\n", retval);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Parse the payload */
|
||||
clif_t lookif;
|
||||
clif_attr_t attrs[MAX_EXPECTED_ATTRS];
|
||||
unsigned attrs_used = 0;
|
||||
size_t parsed_len = 0;
|
||||
while ((!rd->res_lookif || !rd->ep_lookif) ||
|
||||
(parsed_len != _result_buf_len)) {
|
||||
|
||||
ssize_t ret = clif_decode_link(&lookif, attrs + attrs_used,
|
||||
ARRAY_SIZE(attrs) - attrs_used,
|
||||
_result_buf + parsed_len,
|
||||
_result_buf_len - parsed_len);
|
||||
if (ret < 0) {
|
||||
DEBUG("cord_lc: error decoding payload %zd\n", ret);
|
||||
retval = CORD_LC_ERR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
attrs_used += lookif.attrs_len;
|
||||
parsed_len += ret;
|
||||
|
||||
/* check if we found ep_lookif or res_lookif */
|
||||
for (unsigned i = 0; i < lookif.attrs_len; i++) {
|
||||
clif_attr_t *current_attr = (lookif.attrs + i);
|
||||
if (current_attr->value == NULL) {
|
||||
/* skip attributes that have no value */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strncmp(current_attr->value, "core.rd-lookup-res",
|
||||
current_attr->value_len)) {
|
||||
rd->res_lookif = lookif.target;
|
||||
rd->res_lookif[lookif.target_len] = '\0';
|
||||
} else if (!strncmp(current_attr->value, "core.rd-lookup-ep",
|
||||
current_attr->value_len)) {
|
||||
rd->ep_lookif = lookif.target;
|
||||
rd->ep_lookif[lookif.target_len] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rd->res_lookif && !rd->ep_lookif) {
|
||||
DEBUG("cord_lc: no lookup interfaces found\n");
|
||||
retval = CORD_LC_NORSC;
|
||||
} else {
|
||||
retval = parsed_len;
|
||||
}
|
||||
end:
|
||||
mutex_unlock(&_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
ssize_t cord_lc_raw(const cord_lc_rd_t *rd, unsigned content_format,
|
||||
unsigned lookup_type, cord_lc_filter_t *filters,
|
||||
void *result, size_t maxlen)
|
||||
{
|
||||
_lock();
|
||||
ssize_t retval = _lookup_raw(rd, content_format, lookup_type, filters,
|
||||
result, maxlen);
|
||||
mutex_unlock(&_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
ssize_t _lookup_result(cord_lc_rd_t *rd, cord_lc_res_t *result,
|
||||
cord_lc_filter_t *filters, void *buf, size_t maxlen,
|
||||
unsigned type)
|
||||
{
|
||||
int retval;
|
||||
|
||||
_lock();
|
||||
unsigned *page_ptr = (type == CORD_LC_EP)
|
||||
? &rd->ep_last_page : &rd->res_last_page;
|
||||
/* int will always fit in an 12-char array */
|
||||
char page_str[12];
|
||||
snprintf(page_str, sizeof(page_str), "%u", (*page_ptr)++);
|
||||
|
||||
/* Append given filters to default filters (page, count).
|
||||
* If same filter are also specified by filters, assume the RD server will
|
||||
* use the value from last filter in the filter list */
|
||||
clif_attr_t default_attrs[] = DEFAULT_FILTERS(page_str);
|
||||
cord_lc_filter_t *all_filters = &(cord_lc_filter_t) {
|
||||
.array = default_attrs,
|
||||
.len = ARRAY_SIZE(default_attrs),
|
||||
.next = filters,
|
||||
};
|
||||
|
||||
retval = _lookup_raw(rd, COAP_FORMAT_LINK, type, all_filters, buf, maxlen);
|
||||
if (retval < 0) {
|
||||
if (retval == CORD_LC_NORSC) {
|
||||
*page_ptr = 0;
|
||||
}
|
||||
DEBUG("cord_lc: error ep lookup failed\n");
|
||||
mutex_unlock(&_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* parse the result */
|
||||
retval = clif_decode_link(&result->link, result->attrs, result->max_attrs,
|
||||
buf, retval);
|
||||
if (retval < 0) {
|
||||
DEBUG("cord_lc: no endpoint link found\n");
|
||||
retval = CORD_LC_ERR;
|
||||
}
|
||||
mutex_unlock(&_mutex);
|
||||
return retval;
|
||||
}
|
Loading…
Reference in New Issue
Block a user