mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #17843 from benpicco/gcoap-block-server
examples/gcoap_block_server: add gcoap block server example
This commit is contained in:
commit
ac4ac64e58
47
examples/gcoap_block_server/Makefile
Normal file
47
examples/gcoap_block_server/Makefile
Normal file
@ -0,0 +1,47 @@
|
||||
# Default Makefile, for host native GNRC-based networking
|
||||
|
||||
# name of your application
|
||||
APPLICATION = gcoap_example
|
||||
|
||||
# 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)/../..
|
||||
|
||||
## Uncomment to redefine port, for example use 61616 for RFC 6282 UDP compression.
|
||||
#GCOAP_PORT = 5683
|
||||
#CFLAGS += -DGCOAP_PORT=$(GCOAP_PORT)
|
||||
|
||||
## Uncomment to redefine request token length, max 8.
|
||||
#GCOAP_TOKENLEN = 2
|
||||
#CFLAGS += -DGCOAP_TOKENLEN=$(GCOAP_TOKENLEN)
|
||||
|
||||
# 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
|
||||
# Specify the mandatory networking modules
|
||||
USEMODULE += gnrc_ipv6_default
|
||||
USEMODULE += gcoap
|
||||
# Additional networking modules that can be dropped if not needed
|
||||
USEMODULE += gnrc_icmpv6_echo
|
||||
#USEMODULE += gnrc_rpl
|
||||
|
||||
# Required by handlers
|
||||
USEMODULE += fmt
|
||||
USEMODULE += hashes
|
||||
# Add also the shell, some shell commands
|
||||
USEMODULE += shell
|
||||
USEMODULE += shell_commands
|
||||
USEMODULE += ps
|
||||
|
||||
# Comment this out to disable code in RIOT that does safety checking
|
||||
# which is not needed in a production environment but helps in the
|
||||
# development process:
|
||||
DEVELHELP ?= 1
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
QUIET ?= 1
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
38
examples/gcoap_block_server/Makefile.ci
Normal file
38
examples/gcoap_block_server/Makefile.ci
Normal file
@ -0,0 +1,38 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-mega2560 \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atmega328p-xplained-mini \
|
||||
atxmega-a3bu-xplained \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
m1284p \
|
||||
mega-xplained \
|
||||
microduino-corerf \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
nucleo-f030r8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
nucleo-f303k8 \
|
||||
nucleo-f334r8 \
|
||||
nucleo-l011k4 \
|
||||
nucleo-l031k6 \
|
||||
nucleo-l053r8 \
|
||||
samd10-xmini \
|
||||
slstk3400a \
|
||||
stk3200 \
|
||||
stm32f030f4-demo \
|
||||
stm32f0discovery \
|
||||
stm32g0316-disco \
|
||||
stm32l0538-disco \
|
||||
telosb \
|
||||
waspmote-pro \
|
||||
z1 \
|
||||
zigduino \
|
||||
#
|
8
examples/gcoap_block_server/README.md
Normal file
8
examples/gcoap_block_server/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
This application provides examples of CoAP server handling for Block requests, build with gcoap using nanocoap block handling functions.
|
||||
|
||||
This show the current status and is very likely to change with improvements made to gcoap and nanocoap and their API, see example/nanocoap_server for comparison.
|
||||
|
||||
Relevant resources:
|
||||
|
||||
* `/riot/ver` -- provides Block2 response payloads for GET request
|
||||
* `/sha256` -- provides SHA-256 digest from Block1 POST request input
|
161
examples/gcoap_block_server/gcoap_block.c
Normal file
161
examples/gcoap_block_server/gcoap_block.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Ken Bannister. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief gcoap block server handler example
|
||||
*
|
||||
* @author Ken Bannister <kb2ma@runbox.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "fmt.h"
|
||||
#include "hashes/sha256.h"
|
||||
#include "net/gcoap.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
static ssize_t _sha256_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
|
||||
static ssize_t _riot_block2_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx);
|
||||
|
||||
/* CoAP resources */
|
||||
static const coap_resource_t _resources[] = {
|
||||
{ "/riot/ver", COAP_GET, _riot_block2_handler, NULL },
|
||||
{ "/sha256", COAP_POST, _sha256_handler, NULL },
|
||||
};
|
||||
|
||||
static gcoap_listener_t _listener = {
|
||||
.resources = _resources,
|
||||
.resources_len = ARRAY_SIZE(_resources),
|
||||
};
|
||||
|
||||
/* Constants for /riot/ver. */
|
||||
static const uint8_t block2_intro[] = "This is RIOT (Version: ";
|
||||
static const uint8_t block2_board[] = " running on a ";
|
||||
static const uint8_t block2_mcu[] = " board with a ";
|
||||
|
||||
static ssize_t _riot_block2_handler(coap_pkt_t *pdu, uint8_t *buf, size_t len, void *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
coap_block_slicer_t slicer;
|
||||
coap_block2_init(pdu, &slicer);
|
||||
|
||||
gcoap_resp_init(pdu, buf, len, COAP_CODE_CONTENT);
|
||||
coap_opt_add_format(pdu, COAP_FORMAT_TEXT);
|
||||
coap_opt_add_block2(pdu, &slicer, 1);
|
||||
ssize_t plen = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);
|
||||
|
||||
/* Add actual content */
|
||||
plen += coap_blockwise_put_bytes(&slicer, buf+plen, block2_intro, sizeof(block2_intro)-1);
|
||||
plen += coap_blockwise_put_bytes(&slicer, buf+plen, (uint8_t*)RIOT_VERSION, strlen(RIOT_VERSION));
|
||||
plen += coap_blockwise_put_char(&slicer, buf+plen, ')');
|
||||
plen += coap_blockwise_put_bytes(&slicer, buf+plen, block2_board, sizeof(block2_board)-1);
|
||||
plen += coap_blockwise_put_bytes(&slicer, buf+plen, (uint8_t*)RIOT_BOARD, strlen(RIOT_BOARD));
|
||||
plen += coap_blockwise_put_bytes(&slicer, buf+plen, block2_mcu, sizeof(block2_mcu)-1);
|
||||
plen += coap_blockwise_put_bytes(&slicer, buf+plen, (uint8_t*)RIOT_MCU, strlen(RIOT_MCU));
|
||||
/* To demonstrate individual chars */
|
||||
plen += coap_blockwise_put_char(&slicer, buf+plen, ' ');
|
||||
plen += coap_blockwise_put_char(&slicer, buf+plen, 'M');
|
||||
plen += coap_blockwise_put_char(&slicer, buf+plen, 'C');
|
||||
plen += coap_blockwise_put_char(&slicer, buf+plen, 'U');
|
||||
plen += coap_blockwise_put_char(&slicer, buf+plen, '.');
|
||||
|
||||
coap_block2_finish(&slicer);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uses block1 POSTs to generate an sha256 digest. */
|
||||
static ssize_t _sha256_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
|
||||
/* using a shared sha256 context *will* break if two requests are handled
|
||||
* at the same time. doing it anyways, as this is meant to showcase block1
|
||||
* support, not proper synchronisation. */
|
||||
static sha256_context_t sha256;
|
||||
uint8_t digest[SHA256_DIGEST_LENGTH];
|
||||
coap_block1_t block1;
|
||||
|
||||
int blockwise = coap_get_block1(pdu, &block1);
|
||||
|
||||
printf("_sha256_handler: received data: offset=%u len=%u blockwise=%i more=%i\n",
|
||||
(unsigned)block1.offset, pdu->payload_len, blockwise, block1.more);
|
||||
|
||||
/* initialize sha256 calculation and add payload bytes */
|
||||
if (block1.blknum == 0) {
|
||||
puts("_sha256_handler: init");
|
||||
sha256_init(&sha256);
|
||||
}
|
||||
sha256_update(&sha256, pdu->payload, pdu->payload_len);
|
||||
|
||||
unsigned resp_code = COAP_CODE_CHANGED;
|
||||
if (block1.more) {
|
||||
resp_code = COAP_CODE_CONTINUE;
|
||||
}
|
||||
|
||||
/* start response */
|
||||
gcoap_resp_init(pdu, buf, len, resp_code);
|
||||
|
||||
/* has payload */
|
||||
if (!blockwise || !block1.more) {
|
||||
coap_opt_add_format(pdu, COAP_FORMAT_TEXT);
|
||||
}
|
||||
if (blockwise) {
|
||||
coap_opt_add_block1_control(pdu, &block1);
|
||||
}
|
||||
|
||||
/* include digest if done, otherwise response code above asks for next block */
|
||||
size_t pdu_len = 0;
|
||||
if (!blockwise || !block1.more) {
|
||||
puts("_sha256_handler: finish");
|
||||
sha256_final(&sha256, digest);
|
||||
pdu_len = coap_opt_finish(pdu, COAP_OPT_FINISH_PAYLOAD);
|
||||
|
||||
pdu_len += fmt_bytes_hex((char *)pdu->payload, digest, sizeof(digest));
|
||||
}
|
||||
else {
|
||||
pdu_len = coap_opt_finish(pdu, COAP_OPT_FINISH_NONE);
|
||||
}
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
int gcoap_cli_cmd(int argc, char **argv)
|
||||
{
|
||||
if (argc == 1) {
|
||||
/* show help for main commands */
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "info") == 0) {
|
||||
uint8_t open_reqs = gcoap_op_state();
|
||||
|
||||
printf("CoAP server is listening on port %u\n", CONFIG_GCOAP_PORT);
|
||||
printf("CoAP open requests: %u\n", open_reqs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
end:
|
||||
printf("usage: %s <info>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void gcoap_cli_init(void)
|
||||
{
|
||||
gcoap_register_listener(&_listener);
|
||||
}
|
52
examples/gcoap_block_server/main.c
Normal file
52
examples/gcoap_block_server/main.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016 Ken Bannister. All rights reserved.
|
||||
*
|
||||
* 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 gcoap example
|
||||
*
|
||||
* @author Ken Bannister <kb2ma@runbox.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "msg.h"
|
||||
|
||||
#include "net/gcoap.h"
|
||||
#include "shell.h"
|
||||
|
||||
#define MAIN_QUEUE_SIZE (4)
|
||||
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
|
||||
|
||||
extern int gcoap_cli_cmd(int argc, char **argv);
|
||||
extern void gcoap_cli_init(void);
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "coap", "CoAP example", gcoap_cli_cmd },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* for the thread running the shell */
|
||||
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
|
||||
gcoap_cli_init();
|
||||
puts("gcoap block handler");
|
||||
|
||||
/* 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 never be reached */
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user