mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
pkg/libcoap: Add in libcoap CoAP library support
libcoap version 4.3.5rc3. Using Sock interface. Includes a CoAP client and CoAP server example. tests/pkg/libcoap: Simple CoAP over DTLS loopback test.
This commit is contained in:
parent
821a7e8c9f
commit
84938e4ebb
20
examples/libcoap-client/Kconfig
Normal file
20
examples/libcoap-client/Kconfig
Normal file
@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
#
|
||||
menu "libcoap-client"
|
||||
depends on USEPKG_LIBCOAP
|
||||
|
||||
config LIBCOAP_CLIENT_URI
|
||||
string "CoAP URI to connect to"
|
||||
default "coap://[fe80::405:5aff:fe15:9b7f]/.well-known/core"
|
||||
config LIBCOAP_USE_PSK
|
||||
string "Secret to use for PSK communications"
|
||||
default "secretPSK"
|
||||
depends on USEMODULE_TINYDTLS
|
||||
config LIBCOAP_USE_PSK_ID
|
||||
string "User ID to use for PSK communications"
|
||||
default "user_abc"
|
||||
depends on USEMODULE_TINYDTLS
|
||||
|
||||
endmenu # libcoap-client
|
69
examples/libcoap-client/Makefile
Normal file
69
examples/libcoap-client/Makefile
Normal file
@ -0,0 +1,69 @@
|
||||
# name of your application
|
||||
APPLICATION = libcoap-client
|
||||
|
||||
# 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)/../..
|
||||
|
||||
# Include packages that pull up and auto-init the link layer.
|
||||
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
|
||||
USEMODULE += netdev_default
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
|
||||
# Activate ICMPv6 error messages
|
||||
USEMODULE += gnrc_icmpv6_error
|
||||
|
||||
# Specify the mandatory networking module for a IPv6 routing node
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
|
||||
# Add a routing protocol
|
||||
USEMODULE += gnrc_rpl
|
||||
USEMODULE += auto_init_gnrc_rpl
|
||||
|
||||
# Additional networking modules that can be dropped if not needed
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
|
||||
# Specify the mandatory networking modules for IPv6 and UDP
|
||||
USEMODULE += gnrc_ipv6_default
|
||||
USEMODULE += memarray
|
||||
USEMODULE += ipv4_addr
|
||||
|
||||
# a cryptographically secure implementation of PRNG is needed for tinydtls
|
||||
# Uncomment the following 3 lines for tinydtls support
|
||||
CFLAGS += -DWITH_RIOT_SOCK
|
||||
USEPKG += tinydtls
|
||||
USEMODULE += prng_sha1prng
|
||||
|
||||
# libcoap support
|
||||
USEPKG += libcoap
|
||||
# Uncomment to enable libcoap OSCORE support
|
||||
# USEMODULE += libcoap_oscore
|
||||
|
||||
# Configure if DNS is required
|
||||
# USEMODULE += sock_dns
|
||||
|
||||
# Support 64 bit ticks
|
||||
USEMODULE += ztimer64_xtimer_compat
|
||||
|
||||
# Add also the shell, some shell commands
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_cmds_default
|
||||
USEMODULE += ps
|
||||
USEMODULE += netstats_l2
|
||||
USEMODULE += netstats_ipv6
|
||||
USEMODULE += netstats_rpl
|
||||
|
||||
# libcoap needs some space
|
||||
CFLAGS += -DTHREAD_STACKSIZE_MAIN=\(3*THREAD_STACKSIZE_DEFAULT\)
|
||||
|
||||
# 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:
|
||||
DEVELHELP ?= 1
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
# QUIET ?= 1
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
70
examples/libcoap-client/Makefile.ci
Normal file
70
examples/libcoap-client/Makefile.ci
Normal file
@ -0,0 +1,70 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
airfy-beacon \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-mega2560 \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega256rfr2-xpro \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
atmega8 \
|
||||
atxmega-a3bu-xplained \
|
||||
b-l072z-lrwan1 \
|
||||
blackpill-stm32f103c8 \
|
||||
blackpill-stm32f103cb \
|
||||
bluepill-stm32f030c8 \
|
||||
bluepill-stm32f103c8 \
|
||||
bluepill-stm32f103cb \
|
||||
calliope-mini \
|
||||
cc2650-launchpad \
|
||||
cc2650stk \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
hifive1b \
|
||||
i-nucleo-lrwan1 \
|
||||
im880b \
|
||||
lsn50 \
|
||||
maple-mini \
|
||||
microbit \
|
||||
microduino-corerf \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
nrf51dk \
|
||||
nrf51dongle \
|
||||
nrf6310 \
|
||||
nucleo-f030r8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-f070rb \
|
||||
nucleo-f072rb \
|
||||
nucleo-f103rb \
|
||||
nucleo-f302r8 \
|
||||
nucleo-f303k8 \
|
||||
nucleo-f334r8 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
nucleo-l073rz \
|
||||
olimex-msp430-h1611 \
|
||||
olimex-msp430-h2618 \
|
||||
opencm904 \
|
||||
samd10-xmini \
|
||||
saml10-xpro \
|
||||
saml11-xpro \
|
||||
samr21-xpro \
|
||||
slstk3400a \
|
||||
spark-core \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32f7508-dk \
|
||||
stm32g0316-disco \
|
||||
stm32l0538-disco \
|
||||
stm32mp157c-dk2 \
|
||||
telosb \
|
||||
waspmote-pro \
|
||||
yunjia-nrf51822 \
|
||||
z1 \
|
||||
zigduino \
|
||||
#
|
24
examples/libcoap-client/README.md
Normal file
24
examples/libcoap-client/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# libcoap client example
|
||||
|
||||
This example shows how to configure a client to use libcoap
|
||||
|
||||
## Fast configuration (Between RIOT instances):
|
||||
|
||||
Preparing the logical interfaces:
|
||||
|
||||
sudo ./../../dist/tools/tapsetup/tapsetup --create 2
|
||||
|
||||
## Client invocation
|
||||
For the client:
|
||||
|
||||
PORT=tap0 make term
|
||||
coapc coap://[ip6-address]/some/path
|
||||
|
||||
The IP address to connect to needs to be that as returned by libcoap_server,
|
||||
or that of the tap0 interface, etc.
|
||||
|
||||
## Handling the static memory allocation
|
||||
|
||||
libcoap for RIOT is using the `sys/memarray` module and therefore there
|
||||
are certain limits. Said resources are defined in `libcoap/src/coap_mem.c`,
|
||||
but can be overwritten at compile time.
|
8
examples/libcoap-client/app.config
Normal file
8
examples/libcoap-client/app.config
Normal file
@ -0,0 +1,8 @@
|
||||
CONFIG_LIBCOAP_CLIENT_SUPPORT=y
|
||||
|
||||
CONFIG_LIBCOAP_CLIENT_URI="coap://[fe80::405:5aff:fe15:9b7f]/.well-known/core"
|
||||
|
||||
CONFIG_LIBCOAP_USE_PSK="secretPSK"
|
||||
CONFIG_LIBCOAP_USE_PSK_ID="user_abc"
|
||||
|
||||
# Logging levels are defined in pkg/libcoap using Kconfig
|
270
examples/libcoap-client/client-coap.c
Normal file
270
examples/libcoap-client/client-coap.c
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* client-coap.c -- RIOT client example
|
||||
*
|
||||
* Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#include <thread.h>
|
||||
#include <debug.h>
|
||||
#include <coap3/coap.h>
|
||||
#include "client-coap.h"
|
||||
#include <stdio.h>
|
||||
#include "macros/utils.h"
|
||||
|
||||
#ifdef CONFIG_LIBCOAP_CLIENT_URI
|
||||
#define COAP_CLIENT_URI CONFIG_LIBCOAP_CLIENT_URI
|
||||
#else /* ! CONFIG_LIBCOAP_CLIENT_URI */
|
||||
#define COAP_CLIENT_URI "coap://[fe80::405:5aff:fe15:9b7f]/.well-known/core"
|
||||
#endif /* ! CONFIG_LIBCOAP_CLIENT_URI */
|
||||
|
||||
#ifdef CONFIG_LIBCOAP_USE_PSK
|
||||
#define COAP_USE_PSK CONFIG_LIBCOAP_USE_PSK
|
||||
#else /* ! CONFIG_LIBCOAP_USE_PSK */
|
||||
#define COAP_USE_PSK NULL
|
||||
#endif /* ! CONFIG_LIBCOAP_USE_PSK */
|
||||
|
||||
#ifdef CONFIG_LIBCOAP_USE_PSK_ID
|
||||
#define COAP_USE_PSK_ID CONFIG_LIBCOAP_USE_PSK_ID
|
||||
#else /* ! CONFIG_LIBCOAP_USE_PSK_ID */
|
||||
#define COAP_USE_PSK_ID NULL
|
||||
#endif /* ! CONFIG_LIBCOAP_USE_PSK_ID */
|
||||
|
||||
static coap_context_t *main_coap_context = NULL;
|
||||
static coap_optlist_t *optlist = NULL;
|
||||
|
||||
static int quit = 0;
|
||||
static int is_mcast = 0;
|
||||
|
||||
#define DEFAULT_WAIT_TIME 15
|
||||
|
||||
unsigned int wait_seconds = DEFAULT_WAIT_TIME; /* default timeout in seconds */
|
||||
|
||||
static coap_response_t
|
||||
message_handler(coap_session_t *session,
|
||||
const coap_pdu_t *sent,
|
||||
const coap_pdu_t *received,
|
||||
const coap_mid_t id)
|
||||
{
|
||||
const uint8_t *data;
|
||||
size_t len;
|
||||
size_t offset;
|
||||
size_t total;
|
||||
|
||||
(void)session;
|
||||
(void)sent;
|
||||
(void)id;
|
||||
if (coap_get_data_large(received, &len, &data, &offset, &total)) {
|
||||
printf("%*.*s", (int)len, (int)len, (const char *)data);
|
||||
if (len + offset == total) {
|
||||
printf("\n");
|
||||
quit = 1;
|
||||
}
|
||||
}
|
||||
return COAP_RESPONSE_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
nack_handler(coap_session_t *session COAP_UNUSED,
|
||||
const coap_pdu_t *sent COAP_UNUSED,
|
||||
const coap_nack_reason_t reason,
|
||||
const coap_mid_t id COAP_UNUSED)
|
||||
{
|
||||
|
||||
switch (reason) {
|
||||
case COAP_NACK_TOO_MANY_RETRIES:
|
||||
case COAP_NACK_NOT_DELIVERABLE:
|
||||
case COAP_NACK_RST:
|
||||
case COAP_NACK_TLS_FAILED:
|
||||
case COAP_NACK_TLS_LAYER_FAILED:
|
||||
case COAP_NACK_WS_LAYER_FAILED:
|
||||
case COAP_NACK_WS_FAILED:
|
||||
coap_log_err("cannot send CoAP pdu\n");
|
||||
quit = 1;
|
||||
break;
|
||||
case COAP_NACK_ICMP_ISSUE:
|
||||
case COAP_NACK_BAD_RESPONSE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
resolve_address(const char *host, const char *service, coap_address_t *dst,
|
||||
int scheme_hint_bits)
|
||||
{
|
||||
uint16_t port = service ? atoi(service) : 0;
|
||||
int ret = 0;
|
||||
coap_str_const_t str_host;
|
||||
coap_addr_info_t *addr_info;
|
||||
|
||||
str_host.s = (const uint8_t *)host;
|
||||
str_host.length = strlen(host);
|
||||
addr_info = coap_resolve_address_info(&str_host, port, port, port, port,
|
||||
AF_UNSPEC, scheme_hint_bits,
|
||||
COAP_RESOLVE_TYPE_REMOTE);
|
||||
if (addr_info) {
|
||||
ret = 1;
|
||||
*dst = addr_info->addr;
|
||||
is_mcast = coap_is_mcast(dst);
|
||||
}
|
||||
|
||||
coap_free_address_info(addr_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
client_coap_init(int argc, char **argv)
|
||||
{
|
||||
coap_session_t *session = NULL;
|
||||
coap_pdu_t *pdu;
|
||||
coap_address_t dst;
|
||||
coap_mid_t mid;
|
||||
int len;
|
||||
coap_uri_t uri;
|
||||
char portbuf[8];
|
||||
unsigned int wait_ms = 0;
|
||||
int result = -1;
|
||||
#define BUFSIZE 100
|
||||
unsigned char buf[BUFSIZE];
|
||||
int res;
|
||||
const char *coap_uri = COAP_CLIENT_URI;
|
||||
|
||||
if (argc > 1) {
|
||||
coap_uri = argv[1];
|
||||
}
|
||||
|
||||
/* Initialize libcoap library */
|
||||
coap_startup();
|
||||
|
||||
coap_set_log_level(COAP_MAX_LOGGING_LEVEL);
|
||||
|
||||
/* Parse the URI */
|
||||
len = coap_split_uri((const unsigned char *)coap_uri, strlen(coap_uri), &uri);
|
||||
if (len != 0) {
|
||||
coap_log_warn("Failed to parse uri %s\n", coap_uri);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", uri.port);
|
||||
snprintf((char *)buf, sizeof(buf), "%*.*s", (int)uri.host.length,
|
||||
(int)uri.host.length, (const char *)uri.host.s);
|
||||
/* resolve destination address where packet should be sent */
|
||||
len = resolve_address((const char *)buf, portbuf, &dst, 1 << uri.scheme);
|
||||
if (len <= 0) {
|
||||
coap_log_warn("Failed to resolve address %*.*s\n", (int)uri.host.length,
|
||||
(int)uri.host.length, (const char *)uri.host.s);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
main_coap_context = coap_new_context(NULL);
|
||||
if (!main_coap_context) {
|
||||
coap_log_warn("Failed to initialize context\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
coap_context_set_block_mode(main_coap_context, COAP_BLOCK_USE_LIBCOAP);
|
||||
|
||||
if (uri.scheme == COAP_URI_SCHEME_COAP) {
|
||||
session = coap_new_client_session(main_coap_context, NULL, &dst,
|
||||
COAP_PROTO_UDP);
|
||||
}
|
||||
else if (uri.scheme == COAP_URI_SCHEME_COAP_TCP) {
|
||||
session = coap_new_client_session(main_coap_context, NULL, &dst,
|
||||
COAP_PROTO_TCP);
|
||||
#if defined (COAP_USE_PSK) && defined(COAP_USE_PSK_ID)
|
||||
}
|
||||
else {
|
||||
static coap_dtls_cpsk_t dtls_psk;
|
||||
static char client_sni[256];
|
||||
|
||||
memset(&dtls_psk, 0, sizeof(dtls_psk));
|
||||
dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION;
|
||||
snprintf(client_sni, sizeof(client_sni), "%*.*s", (int)uri.host.length, (int)uri.host.length, uri.host.s);
|
||||
dtls_psk.client_sni = client_sni;
|
||||
dtls_psk.psk_info.identity.s = (const uint8_t *)COAP_USE_PSK_ID;
|
||||
dtls_psk.psk_info.identity.length = strlen(COAP_USE_PSK_ID);
|
||||
dtls_psk.psk_info.key.s = (const uint8_t *)COAP_USE_PSK;
|
||||
dtls_psk.psk_info.key.length = strlen(COAP_USE_PSK);
|
||||
|
||||
session = coap_new_client_session_psk2(main_coap_context, NULL, &dst,
|
||||
COAP_PROTO_DTLS, &dtls_psk);
|
||||
#else /* ! COAP_USE_PSK && ! COAP_USE_PSK_ID */
|
||||
coap_log_err("CONFIG_LIBCOAP_USE_PSK and CONFIG_LIBCOAP_USE_PSK_ID not defined\n");
|
||||
goto fail;
|
||||
#endif /* ! COAP_USE_PSK && ! COAP_USE_PSK_ID */
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
coap_log_warn("Failed to create session\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
coap_register_response_handler(main_coap_context, message_handler);
|
||||
coap_register_nack_handler(main_coap_context, nack_handler);
|
||||
|
||||
/* construct CoAP message */
|
||||
pdu = coap_pdu_init(is_mcast ? COAP_MESSAGE_NON : COAP_MESSAGE_CON,
|
||||
COAP_REQUEST_CODE_GET,
|
||||
coap_new_message_id(session),
|
||||
coap_session_max_pdu_size(session));
|
||||
if (!pdu) {
|
||||
coap_log_warn("Failed to create PDU\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = coap_uri_into_optlist(&uri, &dst, &optlist, 1);
|
||||
if (res) {
|
||||
coap_log_warn("Failed to create options\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Add option list (which will be sorted) to the PDU */
|
||||
if (optlist) {
|
||||
res = coap_add_optlist_pdu(pdu, &optlist);
|
||||
if (res != 1) {
|
||||
coap_log_warn("Failed to add options to PDU\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (is_mcast) {
|
||||
/* Allow for other servers to respond within DEFAULT_LEISURE RFC7252 8.2 */
|
||||
wait_seconds = coap_session_get_default_leisure(session).integer_part + 1;
|
||||
}
|
||||
wait_ms = wait_seconds * 1000;
|
||||
|
||||
/* and send the PDU */
|
||||
mid = coap_send(session, pdu);
|
||||
if (mid == COAP_INVALID_MID) {
|
||||
coap_log_warn("Failed to send PDU\n");
|
||||
goto fail;
|
||||
}
|
||||
while (!quit || is_mcast) {
|
||||
result = coap_io_process(main_coap_context, 1000);
|
||||
if (result >= 0) {
|
||||
if (wait_ms > 0) {
|
||||
if ((unsigned)result >= wait_ms) {
|
||||
coap_log_info("timeout\n");
|
||||
break;
|
||||
} else {
|
||||
wait_ms -= result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fail:
|
||||
/* Clean up library usage so client can be run again */
|
||||
quit = 0;
|
||||
coap_delete_optlist(optlist);
|
||||
optlist = NULL;
|
||||
coap_session_release(session);
|
||||
session = NULL;
|
||||
coap_free_context(main_coap_context);
|
||||
main_coap_context = NULL;
|
||||
coap_cleanup();
|
||||
}
|
26
examples/libcoap-client/client-coap.h
Normal file
26
examples/libcoap-client/client-coap.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* client-coap.h -- RIOT client example
|
||||
*
|
||||
* Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef CLIENT_COAP_H
|
||||
#define CLIENT_COAP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Start up the CoAP Client */
|
||||
void client_coap_init(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CLIENT_COAP_H */
|
55
examples/libcoap-client/main.c
Normal file
55
examples/libcoap-client/main.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* Copyright (C) 2018 Inria
|
||||
*
|
||||
* 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 Example application for libcoap client
|
||||
*
|
||||
* @author Raul Fuentes <>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "msg.h"
|
||||
|
||||
#include "coap3/coap.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
extern int client_coap_init(int argc, char **argv);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "coapc", "Start a libcoap client", client_coap_init },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
puts("RIOT libcoap client testing implementation");
|
||||
|
||||
/* start shell */
|
||||
puts("All up, running the shell now");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
/* should be never reached */
|
||||
return 0;
|
||||
}
|
22
examples/libcoap-server/Kconfig
Normal file
22
examples/libcoap-server/Kconfig
Normal file
@ -0,0 +1,22 @@
|
||||
# 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.
|
||||
#
|
||||
menu "libcoap-server"
|
||||
depends on USEPKG_LIBCOAP
|
||||
|
||||
config LIBCOAP_USE_PSK
|
||||
string "Secret to use for PSK communications"
|
||||
default "secretPSK"
|
||||
depends on USEMODULE_TINYDTLS
|
||||
config LIBCOAP_CLIENT_SUPPORT
|
||||
bool "Set to y if ongoing proxy support is required"
|
||||
default n
|
||||
if LIBCOAP_CLIENT_SUPPORT
|
||||
config LIBCOAP_USE_PSK_ID
|
||||
string "User ID to use for ongoing PSK communications"
|
||||
default "user_abc"
|
||||
depends on USEMODULE_TINYDTLS
|
||||
endif # LIBCOAP_CLIENT_SUPPORT
|
||||
|
||||
endmenu # libcoap-server
|
70
examples/libcoap-server/Makefile
Normal file
70
examples/libcoap-server/Makefile
Normal file
@ -0,0 +1,70 @@
|
||||
# name of your application
|
||||
APPLICATION = libcoap-server
|
||||
|
||||
# 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)/../..
|
||||
|
||||
# Include packages that pull up and auto-init the link layer.
|
||||
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
|
||||
USEMODULE += netdev_default
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
|
||||
# Activate ICMPv6 error messages
|
||||
# USEMODULE += gnrc_icmpv6_error
|
||||
|
||||
# Specify the mandatory networking module for a IPv6 routing node
|
||||
USEMODULE += gnrc_ipv6_router_default
|
||||
|
||||
# Add a routing protocol
|
||||
USEMODULE += gnrc_rpl
|
||||
USEMODULE += auto_init_gnrc_rpl
|
||||
|
||||
# Additional networking modules that can be dropped if not needed
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
USEMODULE += shell_cmd_gnrc_udp
|
||||
|
||||
# Specify the mandatory networking modules for IPv6 and UDP
|
||||
USEMODULE += gnrc_ipv6_default
|
||||
USEMODULE += memarray
|
||||
USEMODULE += ipv4_addr
|
||||
|
||||
# a cryptographically secure implementation of PRNG is needed for tinydtls
|
||||
# Uncomment the following 3 lines for tinydtls support
|
||||
CFLAGS += -DWITH_RIOT_SOCK
|
||||
USEPKG += tinydtls
|
||||
USEMODULE += prng_sha1prng
|
||||
|
||||
# libcoap support
|
||||
USEPKG += libcoap
|
||||
# Uncomment to enable libcoap OSCORE support
|
||||
# USEMODULE += libcoap_oscore
|
||||
|
||||
# Configure if DNS is required
|
||||
USEMODULE += sock_dns
|
||||
|
||||
# USEMODULE += xtimer
|
||||
USEMODULE += ztimer64_xtimer_compat
|
||||
|
||||
# Add also the shell, some shell commands
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_cmds_default
|
||||
USEMODULE += ps
|
||||
USEMODULE += netstats_l2
|
||||
USEMODULE += netstats_ipv6
|
||||
USEMODULE += netstats_rpl
|
||||
|
||||
# libcoap needs some space
|
||||
CFLAGS += -DTHREAD_STACKSIZE_MAIN=\(3*THREAD_STACKSIZE_DEFAULT\)
|
||||
|
||||
# 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:
|
||||
DEVELHELP ?= 1
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
QUIET ?= 1
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
70
examples/libcoap-server/Makefile.ci
Normal file
70
examples/libcoap-server/Makefile.ci
Normal file
@ -0,0 +1,70 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
airfy-beacon \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-mega2560 \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega256rfr2-xpro \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
atmega8 \
|
||||
atxmega-a3bu-xplained \
|
||||
b-l072z-lrwan1 \
|
||||
blackpill-stm32f103c8 \
|
||||
blackpill-stm32f103cb \
|
||||
bluepill-stm32f030c8 \
|
||||
bluepill-stm32f103c8 \
|
||||
bluepill-stm32f103cb \
|
||||
calliope-mini \
|
||||
cc2650-launchpad \
|
||||
cc2650stk \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
hifive1b \
|
||||
i-nucleo-lrwan1 \
|
||||
im880b \
|
||||
lsn50 \
|
||||
maple-mini \
|
||||
microbit \
|
||||
microduino-corerf \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
nrf51dk \
|
||||
nrf51dongle \
|
||||
nrf6310 \
|
||||
nucleo-f030r8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-f070rb \
|
||||
nucleo-f072rb \
|
||||
nucleo-f103rb \
|
||||
nucleo-f302r8 \
|
||||
nucleo-f303k8 \
|
||||
nucleo-f334r8 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
nucleo-l073rz \
|
||||
olimex-msp430-h1611 \
|
||||
olimex-msp430-h2618 \
|
||||
opencm904 \
|
||||
samd10-xmini \
|
||||
saml10-xpro \
|
||||
saml11-xpro \
|
||||
samr21-xpro \
|
||||
slstk3400a \
|
||||
spark-core \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32f7508-dk \
|
||||
stm32g0316-disco \
|
||||
stm32l0538-disco \
|
||||
stm32mp157c-dk2 \
|
||||
telosb \
|
||||
waspmote-pro \
|
||||
yunjia-nrf51822 \
|
||||
z1 \
|
||||
zigduino \
|
||||
#
|
25
examples/libcoap-server/README.md
Normal file
25
examples/libcoap-server/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
# libcoap server example
|
||||
|
||||
This example shows how to configure a server to use libcoap
|
||||
|
||||
## Fast configuration (Between RIOT instances):
|
||||
|
||||
Preparing the logical interfaces:
|
||||
|
||||
sudo ./../../dist/tools/tapsetup/tapsetup --create 2
|
||||
|
||||
## Server invocation
|
||||
For the server:
|
||||
|
||||
PORT=tap0 make term
|
||||
coaps {stop|start}
|
||||
|
||||
The server supports requests for
|
||||
coap://[ip]/time?ticks
|
||||
coap://[ip]/.well-known/core
|
||||
|
||||
## Handling the static memory allocation
|
||||
|
||||
libcoap for RIOT is using the `sys/memarray` module and therefore there
|
||||
are certain limits. Said resources are defined in `libcoap/src/coap_mem.c`,
|
||||
but can be overwritten at compile time.
|
8
examples/libcoap-server/app.config
Normal file
8
examples/libcoap-server/app.config
Normal file
@ -0,0 +1,8 @@
|
||||
CONFIG_LIBCOAP_SERVER_SUPPORT=y
|
||||
|
||||
CONFIG_LIBCOAP_USE_PSK="secretPSK"
|
||||
|
||||
# Logging levels are defined in pkg/libcoap using Kconfig
|
||||
|
||||
CONFIG_DTLS_PEER_MAX=2
|
||||
CONFIG_DTLS_HANDSHAKE_MAX=2
|
55
examples/libcoap-server/main.c
Normal file
55
examples/libcoap-server/main.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* Copyright (C) 2018 Inria
|
||||
*
|
||||
* 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 Example application for libcoap server
|
||||
*
|
||||
* @author Raul Fuentes <>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "msg.h"
|
||||
|
||||
#include "coap3/coap.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
extern int server_coap_init(int argc, char **argv);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "coaps", "Start a libcoap server", server_coap_init },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
puts("RIOT libcoap server testing implementation");
|
||||
|
||||
/* start shell */
|
||||
puts("All up, running the shell now");
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
/* should be never reached */
|
||||
return 0;
|
||||
}
|
303
examples/libcoap-server/server-coap.c
Normal file
303
examples/libcoap-server/server-coap.c
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
* server-coap.c -- RIOT example
|
||||
*
|
||||
* Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#include "coap_config.h"
|
||||
#include <coap3/coap.h>
|
||||
#include "server-coap.h"
|
||||
#include <stdio.h>
|
||||
#include "macros/utils.h"
|
||||
|
||||
#ifdef CONFIG_LIBCOAP_USE_PSK
|
||||
#define COAP_USE_PSK CONFIG_LIBCOAP_USE_PSK
|
||||
#else /* CONFIG_LIBCOAP_USE_PSK */
|
||||
#define COAP_USE_PSK NULL
|
||||
#endif /* CONFIG_LIBCOAP_USE_PSK */
|
||||
|
||||
static volatile int running = 0;
|
||||
static int quit;
|
||||
|
||||
coap_context_t *main_coap_context;
|
||||
|
||||
static coap_time_t clock_offset;
|
||||
/* changeable clock base (see handle_put_time()) */
|
||||
static coap_time_t my_clock_base = 0;
|
||||
static coap_resource_t *time_resource = NULL; /* just for testing */
|
||||
|
||||
static void
|
||||
hnd_get_time(coap_resource_t *resource, coap_session_t *session,
|
||||
const coap_pdu_t *request, const coap_string_t *query,
|
||||
coap_pdu_t *response)
|
||||
{
|
||||
unsigned char buf[40];
|
||||
size_t len;
|
||||
coap_tick_t now;
|
||||
coap_tick_t t;
|
||||
|
||||
(void)resource;
|
||||
(void)session;
|
||||
(void)request;
|
||||
/* FIXME: return time, e.g. in human-readable by default and ticks
|
||||
* when query ?ticks is given. */
|
||||
|
||||
/* if my_clock_base was deleted, we pretend to have no such resource */
|
||||
coap_pdu_set_code(response, my_clock_base ? COAP_RESPONSE_CODE_CONTENT :
|
||||
COAP_RESPONSE_CODE_NOT_FOUND);
|
||||
if (my_clock_base) {
|
||||
coap_add_option(response, COAP_OPTION_CONTENT_FORMAT,
|
||||
coap_encode_var_safe(buf, sizeof(buf),
|
||||
COAP_MEDIATYPE_TEXT_PLAIN),
|
||||
buf);
|
||||
}
|
||||
|
||||
coap_add_option(response, COAP_OPTION_MAXAGE,
|
||||
coap_encode_var_safe(buf, sizeof(buf), 0x01), buf);
|
||||
|
||||
if (my_clock_base) {
|
||||
|
||||
/* calculate current time */
|
||||
coap_ticks(&t);
|
||||
now = my_clock_base + (t / COAP_TICKS_PER_SECOND);
|
||||
|
||||
if (query != NULL
|
||||
&& coap_string_equal(query, coap_make_str_const("ticks"))) {
|
||||
/* output ticks */
|
||||
len = snprintf((char *)buf, sizeof(buf), "%u", (unsigned int)now);
|
||||
coap_add_data(response, len, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_coap_resources(coap_context_t *ctx)
|
||||
{
|
||||
coap_resource_t *r;
|
||||
|
||||
#if 0
|
||||
r = coap_resource_init(NULL, 0, 0);
|
||||
coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index);
|
||||
|
||||
coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
|
||||
coap_add_attr(r, coap_make_str_const("title"), coap_make_str_const("\"General Info\""), 0);
|
||||
coap_add_resource(ctx, r);
|
||||
#endif
|
||||
/* store clock base to use in /time */
|
||||
my_clock_base = clock_offset;
|
||||
|
||||
r = coap_resource_init(coap_make_str_const("time"), 0);
|
||||
if (!r) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
coap_resource_set_get_observable(r, 1);
|
||||
time_resource = r;
|
||||
coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time);
|
||||
#if 0
|
||||
coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time);
|
||||
coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time);
|
||||
#endif
|
||||
coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
|
||||
/* coap_add_attr(r, coap_make_str_const("title"),
|
||||
coap_make_str_const("\"Internal Clock\""), 0); */
|
||||
coap_add_attr(r, coap_make_str_const("rt"), coap_make_str_const("\"ticks\""), 0);
|
||||
coap_add_attr(r, coap_make_str_const("if"), coap_make_str_const("\"clock\""), 0);
|
||||
|
||||
coap_add_resource(ctx, r);
|
||||
#if 0
|
||||
if (coap_async_is_supported()) {
|
||||
r = coap_resource_init(coap_make_str_const("async"), 0);
|
||||
coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async);
|
||||
|
||||
coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0);
|
||||
coap_add_resource(ctx, r);
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
error:
|
||||
coap_log_crit("cannot create resource\n");
|
||||
}
|
||||
|
||||
static int
|
||||
init_coap_context_endpoints(const char *use_psk)
|
||||
{
|
||||
coap_address_t listenaddress;
|
||||
gnrc_netif_t *netif = gnrc_netif_iter(NULL);
|
||||
ipv6_addr_t addr;
|
||||
char addr_str[INET6_ADDRSTRLEN + 8];
|
||||
int scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP;
|
||||
coap_addr_info_t *info = NULL;
|
||||
coap_addr_info_t *info_list = NULL;
|
||||
coap_str_const_t local;
|
||||
int have_ep = 0;
|
||||
|
||||
/* Get the first address on the interface */
|
||||
if (gnrc_netif_ipv6_addrs_get(netif, &addr, sizeof(addr)) < 0) {
|
||||
puts("Unable to get first address of the interface");
|
||||
return 0;
|
||||
}
|
||||
|
||||
coap_address_init(&listenaddress);
|
||||
listenaddress.riot.family = AF_INET6;
|
||||
memcpy(&listenaddress.riot.addr.ipv6, &addr,
|
||||
sizeof(listenaddress.riot.addr.ipv6));
|
||||
coap_print_ip_addr(&listenaddress, addr_str, sizeof(addr_str));
|
||||
coap_log_info("Server IP [%s]\n", addr_str);
|
||||
|
||||
main_coap_context = coap_new_context(NULL);
|
||||
if (!main_coap_context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (use_psk && coap_dtls_is_supported()) {
|
||||
coap_dtls_spsk_t setup_data;
|
||||
|
||||
/* Need PSK set up before setting up endpoints */
|
||||
memset(&setup_data, 0, sizeof(setup_data));
|
||||
setup_data.version = COAP_DTLS_SPSK_SETUP_VERSION;
|
||||
setup_data.psk_info.key.s = (const uint8_t *)use_psk;
|
||||
setup_data.psk_info.key.length = strlen(use_psk);
|
||||
coap_context_set_psk2(main_coap_context, &setup_data);
|
||||
scheme_hint_bits |= 1 << COAP_URI_SCHEME_COAPS;
|
||||
}
|
||||
|
||||
local.s = (uint8_t *)addr_str;
|
||||
local.length = strlen(addr_str);
|
||||
info_list = coap_resolve_address_info(&local, COAP_DEFAULT_PORT,
|
||||
COAPS_DEFAULT_PORT,
|
||||
0, 0,
|
||||
0,
|
||||
scheme_hint_bits,
|
||||
COAP_RESOLVE_TYPE_REMOTE);
|
||||
for (info = info_list; info != NULL; info = info->next) {
|
||||
coap_endpoint_t *ep;
|
||||
|
||||
ep = coap_new_endpoint(main_coap_context, &info->addr, info->proto);
|
||||
if (!ep) {
|
||||
coap_log_warn("cannot create endpoint for proto %u\n",
|
||||
info->proto);
|
||||
}
|
||||
else {
|
||||
have_ep = 1;
|
||||
}
|
||||
}
|
||||
coap_free_address_info(info_list);
|
||||
if (!have_ep) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *
|
||||
server_coap_run(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
/* Initialize libcoap library */
|
||||
coap_startup();
|
||||
|
||||
coap_set_log_level(COAP_MAX_LOGGING_LEVEL);
|
||||
|
||||
if (!init_coap_context_endpoints(COAP_USE_PSK)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Limit the number of idle sessions to save RAM */
|
||||
coap_context_set_max_idle_sessions(main_coap_context, 2);
|
||||
clock_offset = 1; /* Need a non-zero value */
|
||||
init_coap_resources(main_coap_context);
|
||||
|
||||
coap_log_info("libcoap server ready\n");
|
||||
/* Keep on processing ... */
|
||||
while (quit == 0) {
|
||||
coap_io_process(main_coap_context, 1000);
|
||||
}
|
||||
fail:
|
||||
/* Clean up library usage so client can be run again */
|
||||
coap_free_context(main_coap_context);
|
||||
main_coap_context = NULL;
|
||||
coap_cleanup();
|
||||
running = 0;
|
||||
quit = 0;
|
||||
coap_log_info("libcoap server stopped\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char server_stack[THREAD_STACKSIZE_MAIN +
|
||||
THREAD_EXTRA_STACKSIZE_PRINTF];
|
||||
|
||||
static
|
||||
void
|
||||
start_server(void)
|
||||
{
|
||||
kernel_pid_t server_pid;
|
||||
|
||||
/* Only one instance of the server */
|
||||
if (running) {
|
||||
puts("Error: server already running");
|
||||
return;
|
||||
}
|
||||
|
||||
/* The server is initialized */
|
||||
server_pid = thread_create(server_stack,
|
||||
sizeof(server_stack),
|
||||
THREAD_PRIORITY_MAIN - 1,
|
||||
THREAD_CREATE_STACKTEST,
|
||||
server_coap_run, NULL, "libcoap_server");
|
||||
|
||||
/* Uncommon but better be sure */
|
||||
if (server_pid == EINVAL) {
|
||||
puts("ERROR: Thread invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (server_pid == EOVERFLOW) {
|
||||
puts("ERROR: Thread overflow!");
|
||||
return;
|
||||
}
|
||||
|
||||
running = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
stop_server(void)
|
||||
{
|
||||
/* check if server is running at all */
|
||||
if (running == 0) {
|
||||
puts("Error: libcoap server is not running");
|
||||
return;
|
||||
}
|
||||
|
||||
quit = 1;
|
||||
|
||||
puts("Stopping server...");
|
||||
}
|
||||
|
||||
void
|
||||
server_coap_init(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("usage: %s start|stop\n", argv[0]);
|
||||
return;
|
||||
}
|
||||
if (strcmp(argv[1], "start") == 0) {
|
||||
start_server();
|
||||
}
|
||||
else if (strcmp(argv[1], "stop") == 0) {
|
||||
stop_server();
|
||||
}
|
||||
else {
|
||||
printf("Error: invalid command. Usage: %s start|stop\n", argv[0]);
|
||||
}
|
||||
return;
|
||||
}
|
26
examples/libcoap-server/server-coap.h
Normal file
26
examples/libcoap-server/server-coap.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* server-coap.h -- RIOT client example
|
||||
*
|
||||
* Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef SERVER_COAP_H
|
||||
#define SERVER_COAP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Start up the CoAP Server */
|
||||
void server_coap_init(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SERVER_COAP_H */
|
@ -7,6 +7,7 @@
|
||||
menu "Packages"
|
||||
|
||||
rsource "flashdb/Kconfig"
|
||||
rsource "libcoap/Kconfig"
|
||||
rsource "libfixmath/Kconfig"
|
||||
rsource "libschc/Kconfig"
|
||||
rsource "littlefs2/Kconfig"
|
||||
|
302
pkg/libcoap/Kconfig
Normal file
302
pkg/libcoap/Kconfig
Normal file
@ -0,0 +1,302 @@
|
||||
# Copyright (c) 2019 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.
|
||||
#
|
||||
menu "libcoap"
|
||||
depends on USEPKG_LIBCOAP
|
||||
|
||||
choice LIBCOAP_DEBUG_LEVEL
|
||||
bool "Set CoAP debugging level"
|
||||
default LIBCOAP_LOG_INFO
|
||||
help
|
||||
Set CoAP debugging level
|
||||
|
||||
config LIBCOAP_LOG_EMERG
|
||||
bool "Emergency"
|
||||
config LIBCOAP_LOG_ALERT
|
||||
bool "Alert"
|
||||
config LIBCOAP_LOG_CRIT
|
||||
bool "Critical"
|
||||
config LIBCOAP_LOG_ERROR
|
||||
bool "Error"
|
||||
config LIBCOAP_LOG_WARNING
|
||||
bool "Warning"
|
||||
config LIBCOAP_LOG_NOTICE
|
||||
bool "Notice"
|
||||
config LIBCOAP_LOG_INFO
|
||||
bool "Info"
|
||||
config LIBCOAP_LOG_DEBUG
|
||||
bool "Debug"
|
||||
config LIBCOAP_LOG_OSCORE
|
||||
bool "OSCORE"
|
||||
endchoice
|
||||
|
||||
config LIBCOAP_MAX_LOGGING_LEVEL
|
||||
int
|
||||
default 0 if LIBCOAP_LOG_EMERG
|
||||
default 1 if LIBCOAP_LOG_ALERT
|
||||
default 2 if LIBCOAP_LOG_CRIT
|
||||
default 3 if LIBCOAP_LOG_ERROR
|
||||
default 4 if LIBCOAP_LOG_WARNING
|
||||
default 5 if LIBCOAP_LOG_NOTICE
|
||||
default 6 if LIBCOAP_LOG_INFO
|
||||
default 7 if LIBCOAP_LOG_DEBUG
|
||||
default 8 if LIBCOAP_LOG_OSCORE
|
||||
|
||||
config LIBCOAP_IPV4_SUPPORT
|
||||
bool "Enable IPv4 support within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable IPv4 functionality for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP IPv4 code is removed.
|
||||
[RIOT sock gnrc does not support this]
|
||||
|
||||
config LIBCOAP_IPV6_SUPPORT
|
||||
bool "Enable IPv6 support within CoAP"
|
||||
default y
|
||||
help
|
||||
Enable IPv6 functionality for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP IPv6 code is removed.
|
||||
|
||||
if USEMODULE_SOCK_TCP
|
||||
|
||||
config LIBCOAP_TCP_SUPPORT
|
||||
bool "Enable TCP support within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable TCP functionality for CoAP. This is required if TLS sessions
|
||||
are to be used. Note that RIOT TCP support also needs to be enabled.
|
||||
|
||||
If this option is disabled, redundant CoAP TCP code is removed.
|
||||
[RIOT sock gnrc does not support this]
|
||||
|
||||
endif # USEMODULE_SOCK_TCP
|
||||
|
||||
if USEMODULE_LIBCOAP_OSCORE
|
||||
|
||||
config LIBCOAP_OSCORE_SUPPORT
|
||||
bool "Enable OSCORE support within CoAP"
|
||||
default y
|
||||
help
|
||||
Enable OSCORE functionality for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP OSCORE code is removed.
|
||||
|
||||
endif # MODULE_LIBCOAP_OSCORE
|
||||
|
||||
config LIBCOAP_OBSERVE_PERSIST
|
||||
bool "Enable Observe persist support within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable Observe persist functionality for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP Observe persist code is removed.
|
||||
|
||||
config LIBCOAP_WS_SOCKET
|
||||
bool "Enable WebSocket support within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable WebSocket functionality for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP WebSocket code is removed.
|
||||
|
||||
config LIBCOAP_Q_BLOCK_SUPPORT
|
||||
bool "Enable Q-Block (RFC9177) support within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable Q-Block (RFC9177) functionality for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP Q-Block code is removed.
|
||||
|
||||
config LIBCOAP_ASYNC_SUPPORT
|
||||
bool "Enable separate responses support within CoAP"
|
||||
default y
|
||||
help
|
||||
Enable async separate responses functionality for CoAP.
|
||||
|
||||
If this option is disabled, redundent CoAP async separate responses code is removed.
|
||||
|
||||
config LIBCOAP_THREAD_SAFE
|
||||
bool "Enable thread safe support within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable thread safe support within CoAP.
|
||||
|
||||
If this option is disabled, libcoap is not thread safe,
|
||||
|
||||
config LIBCOAP_THREAD_RECURSIVE_CHECK
|
||||
bool "Enable thread recursive lock detection if thread safe support is enabled"
|
||||
depends on LIBCOAP_THREAD_SAFE
|
||||
default n
|
||||
help
|
||||
Enable thread recursive lock detection if thread safe support is enabled.
|
||||
|
||||
If this option is disabled, there is no multi thread recursive detection.
|
||||
|
||||
config LIBCOAP_CLIENT_SUPPORT
|
||||
bool "Enable Client functionality within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable client functionality (ability to make requests and receive
|
||||
responses) for CoAP. If the server is going to act as a proxy, then
|
||||
this needs to be enabled to support the ongoing session going to
|
||||
the next hop.
|
||||
|
||||
If this option is disabled, redundant CoAP client only code is
|
||||
removed.
|
||||
If both this option and LIBCOAP_SERVER_SUPPORT are disabled, then
|
||||
both are automatically enabled for backwards compatability.
|
||||
|
||||
if LIBCOAP_CLIENT_SUPPORT
|
||||
|
||||
config LIBCOAP_MAX_LG_CRCVS
|
||||
int "Max number of client large receives supported"
|
||||
default 1
|
||||
help
|
||||
The maximum number of supported client large receives.
|
||||
|
||||
endif # LIBCOAP_CLIENT_SUPPORT
|
||||
|
||||
config LIBCOAP_SERVER_SUPPORT
|
||||
bool "Enable Server functionality within CoAP"
|
||||
default n
|
||||
help
|
||||
Enable server functionality (ability to receive requests and send
|
||||
responses) for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP server only code is
|
||||
removed.
|
||||
If both this option and LIBCOAP_CLIENT_SUPPORT are disabled, then
|
||||
both are automatically enabled for backwards compatability.
|
||||
|
||||
if LIBCOAP_SERVER_SUPPORT
|
||||
|
||||
config LIBCOAP_MAX_ENDPOINTS
|
||||
int "Max number of endpoints supported"
|
||||
default 4 if LIBCOAP_TCP_SUPPORT
|
||||
default 2
|
||||
help
|
||||
The maximum number of supported endpoints.
|
||||
|
||||
config LIBCOAP_MAX_RESOURCES
|
||||
int "Max number of resources supported"
|
||||
default 8
|
||||
help
|
||||
The maximum number of supported resources.
|
||||
|
||||
config LIBCOAP_MAX_ATTRIBUTE_SIZE
|
||||
int "Max size of attribute memory allocation"
|
||||
default 16
|
||||
help
|
||||
The maximum size of a supported attribute.
|
||||
|
||||
config LIBCOAP_MAX_ATTRIBUTES
|
||||
int "Max number of resource attributes supported"
|
||||
default 32
|
||||
help
|
||||
The maximum number of supported resource attributes.
|
||||
|
||||
config LIBCOAP_MAX_CACHE_KEYS
|
||||
int "Max number of cache keys supported"
|
||||
default 2
|
||||
help
|
||||
The maximum number of supported cache keys.
|
||||
|
||||
config LIBCOAP_MAX_CACHE_ENTRIES
|
||||
int "Max number of cache entries supported"
|
||||
default 2
|
||||
help
|
||||
The maximum number of supported cache entries.
|
||||
|
||||
config LIBCOAP_MAX_LG_SRCVS
|
||||
int "Max number of server large receives supported"
|
||||
default 2
|
||||
help
|
||||
The maximum number of supported server large receives.
|
||||
|
||||
endif # LIBCOAP_SERVER_SUPPORT
|
||||
|
||||
config LIBCOAP_PROXY_SUPPORT
|
||||
bool "Enable Proxy functionality within CoAP"
|
||||
depends on LIBCOAP_CLIENT_SUPPORT && LIBCOAP_SERVER_SUPPORT
|
||||
default n
|
||||
help
|
||||
Enable Proxy functionality (ability to receive requests, pass
|
||||
them to an upstream server and send back responses to client)
|
||||
for CoAP.
|
||||
|
||||
If this option is disabled, redundant CoAP proxy only code is
|
||||
removed.
|
||||
|
||||
config LIBCOAP_MAX_LG_XMITS
|
||||
int "Max number of large transmits supported"
|
||||
default 2 if LIBCOAP_SERVER_SUPPORT
|
||||
default 1
|
||||
help
|
||||
The maximum number of supported large transmits.
|
||||
|
||||
config LIBCOAP_MAX_STRING_SIZE
|
||||
int "Max size of string memory allocation"
|
||||
default 64
|
||||
help
|
||||
The maximum size of a supported string.
|
||||
|
||||
config LIBCOAP_MAX_STRINGS
|
||||
int "Max number of strings supported"
|
||||
default 16
|
||||
help
|
||||
The maximum number of supported strings.
|
||||
|
||||
config LIBCOAP_MAX_PACKETS
|
||||
int "Max number of packets supported"
|
||||
default 4
|
||||
help
|
||||
The maximum number of supported packets.
|
||||
|
||||
config LIBCOAP_MAX_NODES
|
||||
int "Max number of nodes supported"
|
||||
default 4
|
||||
help
|
||||
The maximum number of supported nodes.
|
||||
|
||||
config LIBCOAP_MAX_CONTEXTS
|
||||
int "Max number of contexts supported"
|
||||
default 1
|
||||
help
|
||||
The maximum number of supported contexts.
|
||||
|
||||
config LIBCOAP_MAX_PDUS
|
||||
int "Max number of PDUs supported"
|
||||
default 4
|
||||
help
|
||||
The maximum number of supported PDUs.
|
||||
|
||||
config LIBCOAP_MAX_DTLS_SESSIONS
|
||||
int "Max number of DTLS sessions supported"
|
||||
default 2
|
||||
help
|
||||
The maximum number of supported DTLS sessions.
|
||||
|
||||
config LIBCOAP_MAX_SESSIONS
|
||||
int "Max number of sessions supported"
|
||||
default 4
|
||||
help
|
||||
The maximum number of supported sessions.
|
||||
|
||||
config LIBCOAP_MAX_OPTION_SIZE
|
||||
int "Max size of option memory allocation"
|
||||
default 16
|
||||
help
|
||||
The maximum size of a supported option.
|
||||
|
||||
config LIBCOAP_MAX_OPTIONS
|
||||
int "Max number of options supported"
|
||||
default 16
|
||||
help
|
||||
The maximum number of supported options.
|
||||
|
||||
endmenu # libcoap
|
23
pkg/libcoap/Makefile
Normal file
23
pkg/libcoap/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
PKG_NAME=libcoap
|
||||
PKG_URL=https://github.com/obgm/libcoap
|
||||
PKG_VERSION=0d240530b4beba90cc86c488e17bd0090437a0dd
|
||||
PKG_LICENSE=BSD-2-Clause
|
||||
|
||||
LIBCOAP_BUILD_DIR=$(BINDIR)/pkg/$(PKG_NAME)
|
||||
LIBCOAP_SOURCE_DIR=$(RIOTBASE)/build/pkg/$(PKG_NAME)
|
||||
LIBCOAP_INCLUDE_DIR=$(RIOTBASE)/build/pkg/$(PKG_NAME)/include/coap3
|
||||
|
||||
include $(RIOTBASE)/pkg/pkg.mk
|
||||
|
||||
ifneq (,$(filter libcoap_oscore,$(USEMODULE)))
|
||||
all: libcoap libcoap_oscore
|
||||
else
|
||||
all: libcoap
|
||||
endif
|
||||
|
||||
libcoap:
|
||||
$(QQ)@cp $(LIBCOAP_SOURCE_DIR)/coap_config.h.riot $(LIBCOAP_SOURCE_DIR)/coap_config.h
|
||||
$(QQ)"$(MAKE)" -C $(LIBCOAP_SOURCE_DIR)/src -f $(CURDIR)/Makefile.libcoap
|
||||
|
||||
libcoap_oscore:
|
||||
$(QQ)"$(MAKE)" -C $(LIBCOAP_SOURCE_DIR)/src/oscore -f $(CURDIR)/Makefile.oscore
|
11
pkg/libcoap/Makefile.dep
Normal file
11
pkg/libcoap/Makefile.dep
Normal file
@ -0,0 +1,11 @@
|
||||
USEMODULE += sock_udp
|
||||
USEMODULE += sock_aux_local
|
||||
USEMODULE += sock_async_event
|
||||
|
||||
ifneq (,$(filter libcoap,$(USEPKG)))
|
||||
USEMODULE += libcoap
|
||||
endif
|
||||
|
||||
ifneq (,$(filter libcoap_oscore,$(USEPKG)))
|
||||
USEMODULE += libcoap_oscore
|
||||
endif
|
2
pkg/libcoap/Makefile.include
Normal file
2
pkg/libcoap/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
||||
INCLUDES += -I$(PKGDIRBASE)/libcoap \
|
||||
-I$(PKGDIRBASE)/libcoap/include
|
43
pkg/libcoap/Makefile.libcoap
Normal file
43
pkg/libcoap/Makefile.libcoap
Normal file
@ -0,0 +1,43 @@
|
||||
MODULE := libcoap
|
||||
|
||||
SRC := coap_address.c \
|
||||
coap_asn1.c \
|
||||
coap_async.c \
|
||||
coap_block.c \
|
||||
coap_cache.c \
|
||||
coap_debug.c \
|
||||
coap_dtls.c \
|
||||
coap_encode.c \
|
||||
coap_event.c \
|
||||
coap_gnutls.c\
|
||||
coap_hashkey.c \
|
||||
coap_io.c \
|
||||
coap_io_riot.c\
|
||||
coap_layers.c\
|
||||
coap_mbedtls.c\
|
||||
coap_mem.c \
|
||||
coap_net.c \
|
||||
coap_netif.c \
|
||||
coap_notls.c \
|
||||
coap_openssl.c\
|
||||
coap_option.c \
|
||||
coap_oscore.c \
|
||||
coap_pdu.c \
|
||||
coap_prng.c \
|
||||
coap_proxy.c \
|
||||
coap_resource.c \
|
||||
coap_session.c \
|
||||
coap_sha1.c \
|
||||
coap_str.c \
|
||||
coap_subscribe.c \
|
||||
coap_tcp.c \
|
||||
coap_threadsafe.c \
|
||||
coap_tinydtls.c \
|
||||
coap_uri.c \
|
||||
coap_ws.c
|
||||
|
||||
ifneq (,$(filter libcoap_tinydtls,$(USEMODULE)))
|
||||
CFLAGS += -DCOAP_WITH_LIBTINYDTLS
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
10
pkg/libcoap/Makefile.oscore
Normal file
10
pkg/libcoap/Makefile.oscore
Normal file
@ -0,0 +1,10 @@
|
||||
MODULE := libcoap_oscore
|
||||
|
||||
SRC := \
|
||||
oscore.c \
|
||||
oscore_cbor.c \
|
||||
oscore_context.c \
|
||||
oscore_cose.c \
|
||||
oscore_crypto.c
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
17
tests/pkg/libcoap/Kconfig
Normal file
17
tests/pkg/libcoap/Kconfig
Normal file
@ -0,0 +1,17 @@
|
||||
# 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.
|
||||
#
|
||||
menu "tests_libcoap"
|
||||
depends on USEPKG_LIBCOAP
|
||||
|
||||
config LIBCOAP_USE_PSK
|
||||
string "Secret to use for PSK communications"
|
||||
default "secretPSK"
|
||||
depends on USEMODULE_TINYDTLS
|
||||
config LIBCOAP_USE_PSK_ID
|
||||
string "Identifier (user) to use for PSK communications"
|
||||
default "test_user"
|
||||
depends on USEMODULE_TINYDTLS
|
||||
|
||||
endmenu # tests_libcoap
|
35
tests/pkg/libcoap/Makefile
Normal file
35
tests/pkg/libcoap/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
# Include common testing definitions
|
||||
include ../Makefile.pkg_common
|
||||
|
||||
# This test depends on tap device setup not being set
|
||||
PORT=
|
||||
|
||||
# Include packages that pull up and auto-init the link layer.
|
||||
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
|
||||
USEMODULE += netdev_default
|
||||
USEMODULE += auto_init_gnrc_netif
|
||||
USEMODULE += gnrc_netif_single
|
||||
|
||||
# Additional networking modules that can be dropped if not needed
|
||||
USEMODULE += netutils
|
||||
|
||||
# Specify the mandatory networking modules for IPv6 and UDP
|
||||
USEMODULE += gnrc_ipv6_default
|
||||
|
||||
USEMODULE += memarray
|
||||
|
||||
# a cryptographically secure implementation of PRNG is needed for tinydtls
|
||||
CFLAGS += -DWITH_RIOT_SOCK
|
||||
CFLAGS += -DDTLS_PEER_MAX=2 -DDTLS_HANDSHAKE_MAX=2 -DNETQ_MAXCNT=5
|
||||
USEPKG += tinydtls
|
||||
USEMODULE += prng_sha1prng
|
||||
|
||||
# libcoap support
|
||||
USEPKG += libcoap
|
||||
|
||||
USEMODULE += ztimer64_xtimer_compat
|
||||
|
||||
# libcoap needs some space
|
||||
CFLAGS += -DTHREAD_STACKSIZE_MAIN=\(3*THREAD_STACKSIZE_DEFAULT\)
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
70
tests/pkg/libcoap/Makefile.ci
Normal file
70
tests/pkg/libcoap/Makefile.ci
Normal file
@ -0,0 +1,70 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
airfy-beacon \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-mega2560 \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega256rfr2-xpro \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
atmega8 \
|
||||
atxmega-a3bu-xplained \
|
||||
b-l072z-lrwan1 \
|
||||
blackpill-stm32f103c8 \
|
||||
blackpill-stm32f103cb \
|
||||
bluepill-stm32f030c8 \
|
||||
bluepill-stm32f103c8 \
|
||||
bluepill-stm32f103cb \
|
||||
calliope-mini \
|
||||
cc2650-launchpad \
|
||||
cc2650stk \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
hifive1b \
|
||||
i-nucleo-lrwan1 \
|
||||
im880b \
|
||||
lsn50 \
|
||||
maple-mini \
|
||||
microbit \
|
||||
microduino-corerf \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
nrf51dk \
|
||||
nrf51dongle \
|
||||
nrf6310 \
|
||||
nucleo-f030r8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-f070rb \
|
||||
nucleo-f072rb \
|
||||
nucleo-f103rb \
|
||||
nucleo-f302r8 \
|
||||
nucleo-f303k8 \
|
||||
nucleo-f334r8 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
nucleo-l073rz \
|
||||
olimex-msp430-h1611 \
|
||||
olimex-msp430-h2618 \
|
||||
opencm904 \
|
||||
samd10-xmini \
|
||||
saml10-xpro \
|
||||
saml11-xpro \
|
||||
samr21-xpro \
|
||||
slstk3400a \
|
||||
spark-core \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32f7508-dk \
|
||||
stm32g0316-disco \
|
||||
stm32l0538-disco \
|
||||
stm32mp157c-dk2 \
|
||||
telosb \
|
||||
waspmote-pro \
|
||||
yunjia-nrf51822 \
|
||||
z1 \
|
||||
zigduino \
|
||||
#
|
7
tests/pkg/libcoap/README.md
Normal file
7
tests/pkg/libcoap/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# libcoap test example
|
||||
|
||||
This test is to check that the libcoap client and server logic talk to
|
||||
each other.
|
||||
|
||||
THe client request generates a CoAP request, which is sent to the server
|
||||
who responds back to the client.
|
11
tests/pkg/libcoap/app.config
Normal file
11
tests/pkg/libcoap/app.config
Normal file
@ -0,0 +1,11 @@
|
||||
CONFIG_LIBCOAP_SERVER_SUPPORT=y
|
||||
CONFIG_LIBCOAP_CLIENT_SUPPORT=y
|
||||
|
||||
CONFIG_LIBCOAP_USE_PSK="secretPSK"
|
||||
CONFIG_LIBCOAP_USE_PSK_ID="test_user"
|
||||
|
||||
# Logging levels are defined in pkg/libcoap using Kconfig
|
||||
CONFIG_LIBCOAP_LOG_ALERT=y
|
||||
|
||||
CONFIG_DTLS_PEER_MAX=2
|
||||
CONFIG_DTLS_HANDSHAKE_MAX=2
|
327
tests/pkg/libcoap/libcoap-test.c
Normal file
327
tests/pkg/libcoap/libcoap-test.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
* libcoap-test.c -- RIOT example
|
||||
*
|
||||
* Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#include "coap_config.h"
|
||||
#include <coap3/coap.h>
|
||||
#include "libcoap-test.h"
|
||||
#include <stdio.h>
|
||||
#include "macros/utils.h"
|
||||
|
||||
#ifdef CONFIG_LIBCOAP_USE_PSK
|
||||
#define COAP_USE_PSK CONFIG_LIBCOAP_USE_PSK
|
||||
#else /* CONFIG_LIBCOAP_USE_PSK */
|
||||
#define COAP_USE_PSK NULL
|
||||
#endif /* CONFIG_LIBCOAP_USE_PSK */
|
||||
|
||||
#ifdef CONFIG_LIBCOAP_USE_PSK_ID
|
||||
#define COAP_USE_PSK_ID CONFIG_LIBCOAP_USE_PSK_ID
|
||||
#else /* CONFIG_LIBCOAP_USE_PSK_ID */
|
||||
#define COAP_USE_PSK_ID NULL
|
||||
#endif /* CONFIG_LIBCOAP_USE_PSK_ID */
|
||||
|
||||
static int quit;
|
||||
|
||||
#define INDEX "This is a DTLS loopback test client/server made with libcoap\n"
|
||||
|
||||
static void
|
||||
hnd_get_index(coap_resource_t *resource, coap_session_t *session,
|
||||
const coap_pdu_t *request, const coap_string_t *query,
|
||||
coap_pdu_t *response)
|
||||
{
|
||||
coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
|
||||
coap_add_data_large_response(resource, session, request, response,
|
||||
query, COAP_MEDIATYPE_TEXT_PLAIN,
|
||||
0x7fff, 0, strlen(INDEX),
|
||||
(const uint8_t *)INDEX, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
init_coap_resources(coap_context_t *ctx)
|
||||
{
|
||||
coap_resource_t *r;
|
||||
|
||||
r = coap_resource_init(NULL, 0);
|
||||
if (r == NULL) {
|
||||
goto error;
|
||||
}
|
||||
coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index);
|
||||
|
||||
coap_add_resource(ctx, r);
|
||||
|
||||
return;
|
||||
error:
|
||||
coap_log_crit("cannot create resource\n");
|
||||
}
|
||||
|
||||
static int
|
||||
init_coap_endpoints(coap_context_t *ctx, const char *use_psk)
|
||||
{
|
||||
char addr_str[INET6_ADDRSTRLEN + 8];
|
||||
int scheme_hint_bits = 1 << COAP_URI_SCHEME_COAP;
|
||||
coap_addr_info_t *info = NULL;
|
||||
coap_addr_info_t *info_list = NULL;
|
||||
coap_str_const_t local;
|
||||
int have_ep = 0;
|
||||
|
||||
if (use_psk && coap_dtls_is_supported()) {
|
||||
coap_dtls_spsk_t setup_data;
|
||||
|
||||
/* Need PSK set up before setting up endpoints */
|
||||
memset(&setup_data, 0, sizeof(setup_data));
|
||||
setup_data.version = COAP_DTLS_SPSK_SETUP_VERSION;
|
||||
setup_data.psk_info.key.s = (const uint8_t *)use_psk;
|
||||
setup_data.psk_info.key.length = strlen(use_psk);
|
||||
coap_context_set_psk2(ctx, &setup_data);
|
||||
scheme_hint_bits |= 1 << COAP_URI_SCHEME_COAPS;
|
||||
}
|
||||
|
||||
local.s = (uint8_t *)"::1";
|
||||
local.length = strlen(addr_str);
|
||||
info_list = coap_resolve_address_info(&local, COAP_DEFAULT_PORT,
|
||||
COAPS_DEFAULT_PORT,
|
||||
0, 0,
|
||||
0,
|
||||
scheme_hint_bits,
|
||||
COAP_RESOLVE_TYPE_REMOTE);
|
||||
for (info = info_list; info != NULL; info = info->next) {
|
||||
coap_endpoint_t *ep;
|
||||
|
||||
ep = coap_new_endpoint(ctx, &info->addr, info->proto);
|
||||
if (!ep) {
|
||||
coap_log_warn("cannot create endpoint for proto %u\n",
|
||||
info->proto);
|
||||
}
|
||||
else {
|
||||
have_ep = 1;
|
||||
}
|
||||
}
|
||||
coap_free_address_info(info_list);
|
||||
if (!have_ep) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
coap_server_init(coap_context_t *ctx)
|
||||
{
|
||||
if (!init_coap_endpoints(ctx, COAP_USE_PSK)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
init_coap_resources(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
resolve_address(const char *host, const char *service, coap_address_t *dst,
|
||||
int scheme_hint_bits)
|
||||
{
|
||||
uint16_t port = service ? atoi(service) : 0;
|
||||
int ret = 0;
|
||||
coap_str_const_t str_host;
|
||||
coap_addr_info_t *addr_info;
|
||||
|
||||
str_host.s = (const uint8_t *)host;
|
||||
str_host.length = strlen(host);
|
||||
addr_info = coap_resolve_address_info(&str_host, port, port, port, port,
|
||||
AF_UNSPEC, scheme_hint_bits,
|
||||
COAP_RESOLVE_TYPE_REMOTE);
|
||||
if (addr_info) {
|
||||
ret = 1;
|
||||
*dst = addr_info->addr;
|
||||
}
|
||||
|
||||
coap_free_address_info(addr_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static coap_response_t
|
||||
message_handler(coap_session_t *session,
|
||||
const coap_pdu_t *sent,
|
||||
const coap_pdu_t *received,
|
||||
const coap_mid_t id)
|
||||
{
|
||||
const uint8_t *data;
|
||||
size_t len;
|
||||
size_t offset;
|
||||
size_t total;
|
||||
|
||||
(void)session;
|
||||
(void)sent;
|
||||
(void)id;
|
||||
if (coap_get_data_large(received, &len, &data, &offset, &total)) {
|
||||
printf("%*.*s", (int)len, (int)len, (const char *)data);
|
||||
if (len + offset == total) {
|
||||
printf("\n");
|
||||
quit = 1;
|
||||
}
|
||||
}
|
||||
return COAP_RESPONSE_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
coap_client_init(coap_context_t *ctx)
|
||||
{
|
||||
coap_session_t *session = NULL;
|
||||
coap_pdu_t *pdu;
|
||||
coap_address_t dst;
|
||||
coap_mid_t mid;
|
||||
int len;
|
||||
coap_uri_t uri;
|
||||
char portbuf[8];
|
||||
coap_optlist_t *optlist = NULL;
|
||||
|
||||
#define BUFSIZE 100
|
||||
unsigned char buf[BUFSIZE];
|
||||
int res;
|
||||
const char *coap_uri = "coaps://[::1]";
|
||||
|
||||
/* Parse the URI */
|
||||
len = coap_split_uri((const unsigned char *)coap_uri, strlen(coap_uri), &uri);
|
||||
if (len != 0) {
|
||||
coap_log_warn("Failed to parse uri %s\n", coap_uri);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", uri.port);
|
||||
snprintf((char *)buf, sizeof(buf), "%*.*s", (int)uri.host.length,
|
||||
(int)uri.host.length, (const char *)uri.host.s);
|
||||
/* resolve destination address where packet should be sent */
|
||||
len = resolve_address((const char *)buf, portbuf, &dst, 1 << uri.scheme);
|
||||
if (len <= 0) {
|
||||
coap_log_warn("Failed to resolve address %*.*s\n", (int)uri.host.length,
|
||||
(int)uri.host.length, (const char *)uri.host.s);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (uri.scheme == COAP_URI_SCHEME_COAP) {
|
||||
session = coap_new_client_session(ctx, NULL, &dst,
|
||||
COAP_PROTO_UDP);
|
||||
}
|
||||
else if (uri.scheme == COAP_URI_SCHEME_COAP_TCP) {
|
||||
goto fail;
|
||||
}
|
||||
else if (uri.scheme == COAP_URI_SCHEME_COAPS_TCP) {
|
||||
goto fail;
|
||||
}
|
||||
else if (uri.scheme == COAP_URI_SCHEME_COAPS) {
|
||||
#if defined (COAP_USE_PSK) && defined(COAP_USE_PSK_ID)
|
||||
static coap_dtls_cpsk_t dtls_psk;
|
||||
static char client_sni[256];
|
||||
|
||||
memset(client_sni, 0, sizeof(client_sni));
|
||||
memset(&dtls_psk, 0, sizeof(dtls_psk));
|
||||
dtls_psk.version = COAP_DTLS_CPSK_SETUP_VERSION;
|
||||
if (uri.host.length) {
|
||||
memcpy(client_sni, uri.host.s,
|
||||
MIN(uri.host.length, sizeof(client_sni) - 1));
|
||||
}
|
||||
else {
|
||||
memcpy(client_sni, "localhost", 9);
|
||||
}
|
||||
dtls_psk.client_sni = client_sni;
|
||||
dtls_psk.psk_info.identity.s = (const uint8_t *)COAP_USE_PSK_ID;
|
||||
dtls_psk.psk_info.identity.length = strlen(COAP_USE_PSK_ID);
|
||||
dtls_psk.psk_info.key.s = (const uint8_t *)COAP_USE_PSK;
|
||||
dtls_psk.psk_info.key.length = strlen(COAP_USE_PSK);
|
||||
|
||||
session = coap_new_client_session_psk2(ctx, NULL, &dst,
|
||||
COAP_PROTO_DTLS, &dtls_psk);
|
||||
#else /* ! COAP_USE_PSK && ! COAP_USE_PSK_ID */
|
||||
coap_log_err("CONFIG_LIBCOAP_USE_PSK and CONFIG_LIBCOAP_USE_PSK_ID not defined\n");
|
||||
goto fail;
|
||||
#endif /* ! COAP_USE_PSK && ! COAP_USE_PSK_ID */
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
coap_log_warn("Failed to create session\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
coap_register_response_handler(ctx, message_handler);
|
||||
|
||||
/* construct CoAP message */
|
||||
pdu = coap_pdu_init(COAP_MESSAGE_CON,
|
||||
COAP_REQUEST_CODE_GET,
|
||||
coap_new_message_id(session),
|
||||
coap_session_max_pdu_size(session));
|
||||
if (!pdu) {
|
||||
coap_log_warn("Failed to create PDU\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = coap_uri_into_optlist(&uri, &dst, &optlist, 1);
|
||||
if (res != 1) {
|
||||
coap_log_warn("Failed to create options\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Add option list (which will be sorted) to the PDU */
|
||||
if (optlist) {
|
||||
res = coap_add_optlist_pdu(pdu, &optlist);
|
||||
if (res != 1) {
|
||||
coap_log_warn("Failed to add options to PDU\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* and send the PDU */
|
||||
mid = coap_send(session, pdu);
|
||||
if (mid == COAP_INVALID_MID) {
|
||||
coap_log_warn("Failed to send PDU\n");
|
||||
goto fail;
|
||||
}
|
||||
coap_delete_optlist(optlist);
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
coap_delete_optlist(optlist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
libcoap_test_run(void)
|
||||
{
|
||||
coap_context_t *coap_context;
|
||||
|
||||
/* Initialize libcoap library */
|
||||
coap_startup();
|
||||
|
||||
coap_set_log_level(COAP_MAX_LOGGING_LEVEL);
|
||||
|
||||
coap_context = coap_new_context(NULL);
|
||||
if (!coap_context) {
|
||||
goto fail;
|
||||
}
|
||||
coap_context_set_block_mode(coap_context, COAP_BLOCK_USE_LIBCOAP);
|
||||
|
||||
/* Set up server logic */
|
||||
coap_server_init(coap_context);
|
||||
coap_log_info("libcoap test server ready\n");
|
||||
|
||||
/* Set up and initiate client logic */
|
||||
coap_client_init(coap_context);
|
||||
coap_log_info("libcoap test client started\n");
|
||||
|
||||
/* Keep on processing until response is back in ... */
|
||||
while (quit == 0) {
|
||||
coap_io_process(coap_context, 1000);
|
||||
}
|
||||
fail:
|
||||
/* Clean up library usage so client can be run again */
|
||||
coap_free_context(coap_context);
|
||||
|
||||
coap_cleanup();
|
||||
coap_log_info("libcoap test stopped\n");
|
||||
return;
|
||||
}
|
26
tests/pkg/libcoap/libcoap-test.h
Normal file
26
tests/pkg/libcoap/libcoap-test.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* libcoap-test.h -- RIOT client example
|
||||
*
|
||||
* Copyright (C) 2023-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* This file is part of the CoAP library libcoap. Please see README for terms
|
||||
* of use.
|
||||
*/
|
||||
|
||||
#ifndef LIBCOAP_TEST_H
|
||||
#define LIBCOAP_TEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Start up the CoAP Server */
|
||||
void libcoap_test_run(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBCOAP_TEST_H */
|
43
tests/pkg/libcoap/main.c
Normal file
43
tests/pkg/libcoap/main.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
* Copyright (C) 2018 Inria
|
||||
*
|
||||
* 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 Example test application for libcoap
|
||||
*
|
||||
* @author Raul Fuentes <>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shell.h"
|
||||
#include "msg.h"
|
||||
|
||||
#include "libcoap-test.h"
|
||||
#include "coap3/coap.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (8)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
/* we need a message queue for the thread running the shell in order to
|
||||
* receive potentially fast incoming networking packets */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
|
||||
libcoap_test_run();
|
||||
|
||||
return 0;
|
||||
}
|
18
tests/pkg/libcoap/tests/01-run.py
Executable file
18
tests/pkg/libcoap/tests/01-run.py
Executable file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
from testrunner import run
|
||||
|
||||
|
||||
def testfunc(child):
|
||||
child.expect_exact("This is a DTLS loopback test client/server made with libcoap\r\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(run(testfunc))
|
Loading…
Reference in New Issue
Block a user