1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #7406 from haukepetersen/add_rdcli_simple

net: added CoAP RD client for simple node registration
This commit is contained in:
Koen Zandberg 2018-04-09 13:25:50 +02:00 committed by GitHub
commit 4b210bb1e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 604 additions and 0 deletions

View File

@ -707,6 +707,23 @@ ifneq (,$(filter skald,$(USEMODULE)))
USEMODULE += xtimer
USEMODULE += random
endif
ifneq (,$(filter rdcli_simple_standalone,$(USEMODULE)))
USEMODULE += rdcli_simple
USEMODULE += xtimer
endif
ifneq (,$(filter rdcli_simple,$(USEMODULE)))
USEMODULE += rdcli_common
USEMODULE += fmt
endif
ifneq (,$(filter rdcli_common,$(USEMODULE)))
USEMODULE += fmt
USEMODULE += gcoap
USEMODULE += luid
endif
# always select gpio (until explicit dependencies are sorted out)
FEATURES_OPTIONAL += periph_gpio

View File

@ -0,0 +1,43 @@
# name of your application
APPLICATION = rdcli_simple
# If no BOARD is found in the environment, use this default:
BOARD ?= native
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/../..
BOARD_INSUFFICIENT_MEMORY := chronos msb-430 msb-430h nucleo-f030 nucleo-l053 \
nucleo32-f031 nucleo32-f042 nucleo32-l031 \
stm32f0discovery telosb wsn430-v1_3b wsn430-v1_4 \
z1
# Enable GNRC networking
USEMODULE += gnrc_netdev_default
USEMODULE += auto_init_gnrc_netif
USEMODULE += gnrc_ipv6_default
# Run the simple CoRE resource directory
USEMODULE += rdcli_simple_standalone
# Include the shell for testing purposes
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += ps
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
CFLAGS += -DDEVELHELP
# For debugging and demonstration purposes, we limit the lifetime to the minimal
# allowed value of 60s (see draft-ietf-core-resource-directory-11, Table 2)
RD_LT ?= 60
# Override this variable to set the RD server address (default is the all nodes
# multicast address)
RD_SERVER ?= IPV6_ADDR_ALL_NODES_LINK_LOCAL
CFLAGS += -DRDCLI_LT=$(RD_LT)
CFLAGS += -DRDCLI_SERVER_ADDR=$(RD_SERVER)
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,20 @@
CoRE Resource Directory: Simple Registration Example
====================================================
This example shows how a node can register with a CoRE resource directory using
the simple registration process as described in
draft-ietf-core-resource-directory-11, section 5.3.2.
The registration process needs an endpoint name as well as a lifetime for the
registry entry. You can edit these values by overriding `RDCLI_EP` and
`RDCLI_LT`:
```
CFLAGS="-DRDCLI_LT=\"7200\" -DRDCLI_EP=\"MyNode\"" make all
```
Per default, the node is looking for the CoRE RD at the all nodes link-local
multicast address [FF02::1]:5683. To change the target address or port, simply
redefine `RDCLI_SERVER_ADDR` and `RDCLI_SERVER_PORT`, e.g.:
```
CFLAGS="-DRDCLI_SERVER_ADDR=IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL" make all
```

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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 examples
* @{
*
* @file
* @brief Test application demonstrating the simple registration
* process to a CoRE RD using gcoap
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <stdio.h>
#include "shell.h"
#include "net/gcoap.h"
#include "net/rdcli_common.h"
#define BUFSIZE (64U)
static char riot_info[BUFSIZE];
/* define some dummy CoAP resources */
static ssize_t text_resp(coap_pkt_t *pdu, uint8_t *buf, size_t len,
const char *text, unsigned format)
{
gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
size_t slen = strlen(text);
memcpy(pdu->payload, text, slen);
return gcoap_finish(pdu, slen, format);
}
static ssize_t handler_info(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx)
{
(void)ctx;
return text_resp(pdu, buf, len, riot_info, COAP_FORMAT_JSON);
}
static ssize_t handler_text(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx)
{
return text_resp(pdu, buf, len, (char *)ctx, COAP_FORMAT_TEXT);
}
static const coap_resource_t resources[] = {
{ "/riot/bar", COAP_GET, handler_text, "foo" },
{ "/riot/foo", COAP_GET, handler_text, "bar" },
{ "/riot/info", COAP_GET, handler_info, NULL }
};
static gcoap_listener_t listener = {
.resources = (coap_resource_t *)&resources[0],
.resources_len = sizeof(resources) / sizeof(resources[0]),
.next = NULL
};
int main(void)
{
puts("CoAP simplified RD registration example!\n");
/* fill riot info */
sprintf(riot_info, "{\"ep\":\"%s\",\"lt\":%u}",
rdcli_common_get_ep(), RDCLI_LT);
/* register resource handlers with gcoap */
gcoap_register_listener(&listener);
/* print RD client information */
puts("RD client information:");
printf(" ep: %s\n", rdcli_common_get_ep());
printf(" lt: %is\n", (int)RDCLI_LT);
/* run the shell */
char line_buf[SHELL_DEFAULT_BUFSIZE];
shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);
return 0;
}

View File

@ -64,6 +64,7 @@ PSEUDOMODULES += pktqueue
PSEUDOMODULES += printf_float
PSEUDOMODULES += prng
PSEUDOMODULES += prng_%
PSEUDOMODULES += rdcli_simple_standalone
PSEUDOMODULES += saul_adc
PSEUDOMODULES += saul_default
PSEUDOMODULES += saul_gpio

View File

@ -127,6 +127,12 @@ endif
ifneq (,$(filter skald,$(USEMODULE)))
DIRS += net/skald
endif
ifneq (,$(filter rdcli_common,$(USEMODULE)))
DIRS += net/application_layer/rdcli_common
endif
ifneq (,$(filter rdcli_simple,$(USEMODULE)))
DIRS += net/application_layer/rdcli_simple
endif
DIRS += $(dir $(wildcard $(addsuffix /Makefile, $(USEMODULE))))

View File

@ -159,6 +159,16 @@ void auto_init(void)
DEBUG("Auto init Skald\n");
skald_init();
#endif
#ifdef MODULE_RDCLI_COMMON
DEBUG("Auto init rdcli_common module\n");
extern void rdcli_common_init(void);
rdcli_common_init();
#endif
#ifdef MODULE_RDCLI_SIMPLE_STANDALONE
DEBUG("Auto init rdcli_simple module\n");
extern void rdcli_simple_run(void);
rdcli_simple_run();
#endif
/* initialize network devices */
#ifdef MODULE_AUTO_INIT_GNRC_NETIF

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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_rdcli_common Shared Functions for CoRE RD Clients
* @ingroup net_rdcli
* @{
*
* @file
* @brief Shared CoRE RD client functions
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NET_RDCLI_COMMON_H
#define NET_RDCLI_COMMON_H
#include "net/rdcli_config.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Export the local endpoint identifier
*
* @note Use rdcli_common_get_ep() for accessing the endpoint identifier
*/
extern char rdcli_ep[];
/**
* @brief Generate unique endpoint identifier (ep)
*/
void rdcli_common_init(void);
/**
* @brief Get the local endpoint identifier
*/
static inline const char *rdcli_common_get_ep(void)
{
return (const char *)rdcli_ep;
}
/**
* @brief Add selected query string options to a gcoap request
*
* This function adds:
* - `ep` -> as extracted by rdcli_commont_get_ep()
* - [optional] `lt` -> if defined by RDCLI_LT
* - [optional] 'd' -> if defined by RDCLI_D
*
* @return 0 on success
* @return <0 on error
*/
int rdcli_common_add_qstring(coap_pkt_t *pkt);
#ifdef __cplusplus
}
#endif
#endif /* NET_RDCLI_COMMON_H */
/** @} */

View File

@ -0,0 +1,95 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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_rdcli_config CoAP Resource Directory Client Configuration
* @ingroup net_rdcli
* @{
*
* @file
* @brief
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NET_RDCLI_CONFIG_H
#define NET_RDCLI_CONFIG_H
#include "net/ipv6/addr.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Default lifetime in seconds (the default is 1 day)
*/
#ifndef RDCLI_LT
#define RDCLI_LT (86400UL)
#endif
/**
* @brief Delay until the RD client starts to try registering (in seconds)
*/
#ifndef RDCLI_STARTUP_DELAY
#define RDCLI_STARTUP_DELAY (3U)
#endif
/**
* @brief Default client update interval (default is half the lifetime)
*/
#ifndef RDCLI_UPDATE_INTERVAL
#define RDCLI_UPDATE_INTERVAL (RDCLI_LT / 2)
#endif
/**
* @name Endpoint ID definition
*
* Per default, the endpoint ID (ep) is generated by concatenation of a user
* defined prefix (RDCLI_EP_PREFIX) and a locally unique ID (luid) encoded in
* hexadecimal formatting with the given length of characters
* (RDCLI_EP_SUFFIX_LEN).
*
* Alternatively, the endpoint ID value can be defined at compile time by
* assigning a string value to the RDCLI_ED macro.
*
* @{
*/
#ifndef RDCLI_EP
/**
* @brief Number of generated hexadecimal characters added to the ep
*/
#define RDCLI_EP_SUFFIX_LEN (16)
/**
* @brief Default static prefix used for the generated ep
*/
#define RDCLI_EP_PREFIX "RIOT-"
#endif
/** @} */
/**
* @brief Default IPv6 address to use when looking for RDs
*/
#ifndef RDCLI_SERVER_ADDR
#define RDCLI_SERVER_ADDR IPV6_ADDR_ALL_NODES_LINK_LOCAL
#endif
/**
* @brief Default Port to use when looking for RDs
*/
#ifndef RDCLI_SERVER_PORT
#define RDCLI_SERVER_PORT COAP_PORT
#endif
#ifdef __cplusplus
}
#endif
#endif /* NET_RDCLI_CONFIG_H */
/** @} */

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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_rdcli_simple Simple CoRE Resource Directory Registration
* @ingroup net_rdcli
* @brief CoAP-based CoRE Resource Directory client supporting the simple
* registration only
* @{
*
* @file
* @brief Interface for a simple CoRE RD registration
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NET_RDCLI_SIMPLE_H
#define NET_RDCLI_SIMPLE_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initiate the node registration by sending an empty CoAP POST message
* to the RD server's /.well-known/core resource
*/
int rdcli_simple_register(void);
/**
* @brief Spawn a new thread that registers the node and updates the
* registration with all responding RDs using the simple registration
* process
*/
void rdcli_simple_run(void);
#ifdef __cplusplus
}
#endif
#endif /* NET_RDCLI_SIMPLE_H */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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_rdcli_common
* @{
*
* @file
* @brief Implementation of common functions for CoRE RD clients
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "fmt.h"
#include "luid.h"
#include "net/gcoap.h"
#include "net/rdcli_common.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#ifdef RDCLI_EP
#define EP_LEN (sizeof(RDCLI_EP))
#define BUFSIZE (EP_LEN + 1)
#else
#define PREFIX_LEN (sizeof(RDCLI_EP_PREFIX))
#define BUFSIZE (PREFIX_LEN + RDCLI_EP_SUFFIX_LEN + 1)
#endif
char rdcli_ep[BUFSIZE];
void rdcli_common_init(void)
{
size_t pos = 0;
#ifdef RDCLI_EP
memcpy(rdcli_ep, RDCLI_EP, EP_LEN);
pos += EP_LEN;
#else
uint8_t luid[RDCLI_EP_SUFFIX_LEN / 2];
if (PREFIX_LEN) {
memcpy(rdcli_ep, RDCLI_EP_PREFIX, PREFIX_LEN);
pos += PREFIX_LEN - 1;
}
luid_get(luid, sizeof(luid));
fmt_bytes_hex(&rdcli_ep[pos], luid, sizeof(luid));
#endif
rdcli_ep[pos] = '\0';
}
int rdcli_common_add_qstring(coap_pkt_t *pkt)
{
/* extend the url with some query string options */
int res = gcoap_add_qstring(pkt, "ep", rdcli_ep);
if (res < 0) {
return res;
}
/* [optional] set the lifetime parameter */
#if RDCLI_LT
char lt[11];
lt[fmt_u32_dec(lt, RDCLI_LT)] = '\0';
res = gcoap_add_qstring(pkt, "lt", lt);
if (res < 0) {
return res;
}
#endif
/* [optional] set the domain parameter */
#ifdef RDCLI_D
res = gcoap_add_qstring(pkt, "d", RDCLI_D);
if (res < 0) {
return res;
}
#endif
return 0;
}

View File

@ -0,0 +1,7 @@
SRC = rdcli_simple.c
ifneq (,$(filter rdcli_simple_standalone,$(USEMODULE)))
SRC += rdcli_simple_standalone.c
endif
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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_rdcli_simple
* @{
*
* @file
* @brief Simplified CoAP resource directory client implementation
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <string.h>
#include "fmt.h"
#include "net/gcoap.h"
#include "net/rdcli_config.h"
#include "net/rdcli_common.h"
#include "net/rdcli_simple.h"
#define BUFSIZE (128U)
static coap_pkt_t pkt;
static uint8_t buf[BUFSIZE];
/* allocate an UDP endpoint to the RD server */
static const sock_udp_ep_t remote = {
.family = AF_INET6,
.netif = SOCK_ADDR_ANY_NETIF,
.addr = RDCLI_SERVER_ADDR ,
.port = RDCLI_SERVER_PORT
};
int rdcli_simple_register(void)
{
/* build the initial CON packet */
int res = gcoap_req_init(&pkt, buf, sizeof(buf), COAP_METHOD_POST,
"/.well-known/core");
if (res < 0) {
return res;
}
/* make packet confirmable */
coap_hdr_set_type(pkt.hdr, COAP_TYPE_CON);
/* add Uri-Query options */
res = rdcli_common_add_qstring(&pkt);
if (res < 0) {
return res;
}
/* finish, we don't have any payload */
ssize_t len = gcoap_finish(&pkt, 0, COAP_FORMAT_LINK);
return (int)gcoap_req_send2(buf, len, &remote, NULL);
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2017 Freie Universität Berlin
*
* 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_rdcli_simple
* @{
*
* @file
* @brief Standalone extension for the simple RD registration client
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include "log.h"
#include "thread.h"
#include "xtimer.h"
#include "net/rdcli_config.h"
#include "net/rdcli_simple.h"
#define STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#define PRIO (THREAD_PRIORITY_MAIN - 1)
#define TNAME "rdcli_simple"
static char _stack[STACKSIZE];
static void *reg_runner(void *arg)
{
(void)arg;
/* wait some seconds to give the address configuration some time to settle */
xtimer_sleep(RDCLI_STARTUP_DELAY);
while (1) {
int res = rdcli_simple_register();
if (res < 0) {
LOG_ERROR("[rdcli_simple] error: unable to trigger registration\n");
}
xtimer_sleep(RDCLI_UPDATE_INTERVAL);
}
return NULL; /* should never be reached */
}
void rdcli_simple_run(void)
{
thread_create(_stack, sizeof(_stack), PRIO, 0, reg_runner, NULL, TNAME);
}