Browse Source

Merge pull request #4287 from kaspar030/add_conn_coap_example

examples: add microcoap, gnrc, conn example
cc430
Oleg Hahm 7 years ago
parent
commit
548a63db0d
  1. 58
      examples/microcoap_server/Makefile
  2. 62
      examples/microcoap_server/README.md
  3. 101
      examples/microcoap_server/coap.c
  4. 47
      examples/microcoap_server/main.c
  5. 92
      examples/microcoap_server/microcoap_conn.c
  6. 30
      pkg/microcoap/0005-fix-uninitialized-variable.patch

58
examples/microcoap_server/Makefile

@ -0,0 +1,58 @@
# name of your application
APPLICATION = microcoap_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)/../..
BOARD_INSUFFICIENT_MEMORY := airfy-beacon chronos msb-430 msb-430h nrf51dongle \
nrf6310 pca10000 pca10005 spark-core \
stm32f0discovery telosb weio wsn430-v1_3b wsn430-v1_4 \
yunjia-nrf51822 z1
# Include packages that pull up and auto-init the link layer.
# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
USEMODULE += gnrc_netif_default
USEMODULE += auto_init_gnrc_netif
# Specify the mandatory networking modules for IPv6 and UDP
USEMODULE += gnrc_ipv6_router_default
USEMODULE += gnrc_udp
# Add a routing protocol
USEMODULE += gnrc_rpl
# Additional networking modules that can be dropped if not needed
USEMODULE += gnrc_icmpv6_echo
#
USEMODULE += gnrc_conn_udp
USEPKG += microcoap
CFLAGS += -DMICROCOAP_DEBUG
# include this for printing IP addresses
USEMODULE += shell_commands
# Comment this out to disable code in RIOT that does safety checking
# which is not needed in a production environment but helps in the
# development process:
#CFLAGS += -DDEVELHELP
# Use different settings when compiling for one of the following (low-memory)
# boards
LOW_MEMORY_BOARDS := nucleo-f334
ifneq (,$(filter $(BOARD),$(LOW_MEMORY_BOARDS)))
$(info Using low-memory configuration for microcoap_server.)
## low-memory tuning values
# lower pktbuf buffer size
CFLAGS += -DGNRC_PKTBUF_SIZE=1000
# disable fib, rpl
DISABLE_MODULE += fib gnrc_rpl
USEMODULE += prng_minstd
endif
# Change this to 0 show compiler invocation lines by default:
QUIET ?= 1
include $(RIOTBASE)/Makefile.include

62
examples/microcoap_server/README.md

@ -0,0 +1,62 @@
microcoap server example
========================
This application is meant to get you started with impementing a CoAP server on RIOT.
It uses the gnrc network stack through RIOT's conn socket API.
Usage
=====
To try on native, compile with
```
# make all
```
Then run the resulting binary, e.g.,
```
# make term
```
The application is now listening on all it's configured IP addresses.
Now find out it's link\_layer address:
```
$ make term
/home/kaspar/src/riot/examples/microcoap_server/bin/native/microcoap_server.elf tap0
RIOT native interrupts/signals initialized.
LED_GREEN_OFF
LED_RED_ON
RIOT native board initialized.
RIOT native hardware initialization complete.
main(): This is RIOT! (Version: 2015.12-devel-632-g8f451-booze-add_conn_coap_example)
RIOT microcoap example application
Configured network interfaces:
Iface 5 HWaddr: fa:bf:2b:01:9e:a3
MTU:1280 HL:64
Source address length: 6
Link type: wired
inet6 addr: ff02::1/128 scope: local [multicast]
inet6 addr: fe80::f8bf:2bff:fe01:9ea3/64 scope: local
inet6 addr: ff02::1:ff01:9ea3/128 scope: local [multicast]
inet6 addr: ff02::2/128 scope: local [multicast]
Waiting for incoming UDP packet...
```
The link-layer address in this case is "fe80::f8bf:2bff:fe01:9ea3", the only
"scope: local" address set.
Connect using libcoap CLI
=========================
(replace "fe80::f8bf:2bff:fe01:9ea3" with your link-layer address)
```
# coap-client coap://[fe80::f8bf:2bff:fe01:9ea3%tap0]/riot/board
```

101
examples/microcoap_server/coap.c

@ -0,0 +1,101 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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.
*/
#include <coap.h>
#include <string.h>
#define MAX_RESPONSE_LEN 500
static uint8_t response[MAX_RESPONSE_LEN] = { 0 };
static int handle_get_well_known_core(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt,
coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo);
static int handle_get_riot_board(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt,
coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo);
static const coap_endpoint_path_t path_well_known_core =
{ 2, { ".well-known", "core" } };
static const coap_endpoint_path_t path_riot_board =
{ 2, { "riot", "board" } };
const coap_endpoint_t endpoints[] =
{
{ COAP_METHOD_GET, handle_get_well_known_core,
&path_well_known_core, "ct=40" },
{ COAP_METHOD_GET, handle_get_riot_board,
&path_riot_board, "ct=0" },
/* marks the end of the endpoints array: */
{ (coap_method_t)0, NULL, NULL, NULL }
};
static int handle_get_well_known_core(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt, coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo)
{
char *rsp = (char *)response;
int len = sizeof(response);
const coap_endpoint_t *ep = endpoints;
int i;
len--; // Null-terminated string
while (NULL != ep->handler) {
if (NULL == ep->core_attr) {
ep++;
continue;
}
if (0 < strlen(rsp)) {
strncat(rsp, ",", len);
len--;
}
strncat(rsp, "<", len);
len--;
for (i = 0; i < ep->path->count; i++) {
strncat(rsp, "/", len);
len--;
strncat(rsp, ep->path->elems[i], len);
len -= strlen(ep->path->elems[i]);
}
strncat(rsp, ">;", len);
len -= 2;
strncat(rsp, ep->core_attr, len);
len -= strlen(ep->core_attr);
ep++;
}
return coap_make_response(scratch, outpkt, (const uint8_t *)rsp,
strlen(rsp), id_hi, id_lo, &inpkt->tok,
COAP_RSPCODE_CONTENT,
COAP_CONTENTTYPE_APPLICATION_LINKFORMAT);
}
static int handle_get_riot_board(coap_rw_buffer_t *scratch,
const coap_packet_t *inpkt, coap_packet_t *outpkt,
uint8_t id_hi, uint8_t id_lo)
{
const char *riot_name = RIOT_BOARD;
int len = strlen(RIOT_BOARD);
memcpy(response, riot_name, len);
return coap_make_response(scratch, outpkt, (const uint8_t *)response, len,
id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT,
COAP_CONTENTTYPE_TEXT_PLAIN);
}

47
examples/microcoap_server/main.c

@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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 CoAP example server application (using microcoap)
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @}
*/
#include <stdio.h>
#include "msg.h"
#define MAIN_QUEUE_SIZE (8)
static msg_t _main_msg_queue[MAIN_QUEUE_SIZE];
void microcoap_server_loop(void);
/* import "ifconfig" shell command, used for printing addresses */
extern int _netif_config(int argc, char **argv);
int main(void)
{
puts("RIOT microcoap example application");
/* microcoap_server uses conn which uses gnrc which needs a msg queue */
msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE);
/* print network addresses */
puts("Configured network interfaces:");
_netif_config(0, NULL);
/* start coap server loop */
microcoap_server_loop();
/* should be never reached */
return 0;
}

92
examples/microcoap_server/microcoap_conn.c

@ -0,0 +1,92 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
*
* 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.
*/
#include "net/af.h"
#include "net/conn/udp.h"
#ifdef MICROCOAP_DEBUG
#define ENABLE_DEBUG (1)
#else
#define ENABLE_DEBUG (0)
#endif
#include "debug.h"
#include "coap.h"
static uint8_t _udp_buf[512]; /* udp read buffer (max udp payload size) */
uint8_t scratch_raw[1024]; /* microcoap scratch buffer */
coap_rw_buffer_t scratch_buf = { scratch_raw, sizeof(scratch_raw) };
#define COAP_SERVER_PORT (5683)
/*
* Starts a blocking and never-returning loop dispatching CoAP requests.
*
* When using gnrc, make sure the calling thread has an initialized msg queue.
*/
void microcoap_server_loop(void)
{
uint8_t laddr[16] = { 0 };
uint8_t raddr[16] = { 0 };
size_t raddr_len;
uint16_t rport;
conn_udp_t conn;
int rc = conn_udp_create(&conn, laddr, sizeof(laddr), AF_INET6, COAP_SERVER_PORT);
while (1) {
DEBUG("Waiting for incoming UDP packet...\n");
rc = conn_udp_recvfrom(&conn, (char *)_udp_buf, sizeof(_udp_buf), raddr, &raddr_len, &rport);
if (rc < 0) {
DEBUG("Error in conn_udp_recvfrom(). rc=%u\n", rc);
continue;
}
size_t n = rc;
coap_packet_t pkt;
DEBUG("Received packet: ");
coap_dump(_udp_buf, n, true);
DEBUG("\n");
/* parse UDP packet to CoAP */
if (0 != (rc = coap_parse(&pkt, _udp_buf, n))) {
DEBUG("Bad packet rc=%d\n", rc);
}
else {
coap_packet_t rsppkt;
DEBUG("content:\n");
coap_dumpPacket(&pkt);
/* handle CoAP request */
coap_handle_req(&scratch_buf, &pkt, &rsppkt);
/* build reply */
size_t rsplen = sizeof(_udp_buf);
if ((rc = coap_build(_udp_buf, &rsplen, &rsppkt)) != 0) {
DEBUG("coap_build failed rc=%d\n", rc);
}
else {
DEBUG("Sending packet: ");
coap_dump(_udp_buf, rsplen, true);
DEBUG("\n");
DEBUG("content:\n");
coap_dumpPacket(&rsppkt);
/* send reply via UDP */
rc = conn_udp_sendto(_udp_buf, rsplen, NULL, 0, raddr, raddr_len, AF_INET6, COAP_SERVER_PORT, rport);
if (rc < 0) {
DEBUG("Error sending CoAP reply via udp; %u\n", rc);
}
}
}
}
}

30
pkg/microcoap/0005-fix-uninitialized-variable.patch

@ -0,0 +1,30 @@
From ac2d404d32d96a50a779ded7ad007f15bcf2b4b0 Mon Sep 17 00:00:00 2001
From: Kaspar Schleiser <kaspar@schleiser.de>
Date: Mon, 30 Nov 2015 02:11:12 +0100
Subject: [PATCH] fix uninitialized variable
coap.c: In function 'coap_build':
coap.c:298:17: error: 'len' may be used uninitialized in this function
[-Werror=maybe-uninitialized]
uint8_t len, delta = 0;
^
---
coap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/coap.c b/coap.c
index ada66c2..b6b05af 100644
--- a/coap.c
+++ b/coap.c
@@ -295,7 +295,7 @@ int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt)
for (i=0;i<pkt->numopts;i++)
{
uint32_t optDelta;
- uint8_t len, delta = 0;
+ uint8_t len = 0, delta = 0;
if (((size_t)(p-buf)) > *buflen)
return COAP_ERR_BUFFER_TOO_SMALL;
--
2.6.2
Loading…
Cancel
Save