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"
|
menu "Packages"
|
||||||
|
|
||||||
rsource "flashdb/Kconfig"
|
rsource "flashdb/Kconfig"
|
||||||
|
rsource "libcoap/Kconfig"
|
||||||
rsource "libfixmath/Kconfig"
|
rsource "libfixmath/Kconfig"
|
||||||
rsource "libschc/Kconfig"
|
rsource "libschc/Kconfig"
|
||||||
rsource "littlefs2/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