samples/net: Add a sample for a CoAP client
Change-Id: I17d88081eb719e55d97a5a034f6861e01ebb6a52 Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
This commit is contained in:
parent
97ea9b19ea
commit
8dad0093d3
|
@ -61,3 +61,14 @@ GET method.
|
|||
It can be run similar to the echo_server sample: using two terminals,
|
||||
(1) for zoap_server, run 'make server' in its directory, (2) for
|
||||
zoap_client, run 'make client' in the zoap_client test directory.
|
||||
|
||||
|
||||
zoap_client
|
||||
-----------
|
||||
|
||||
The Zoap client application does a single request against a 'a/light'
|
||||
resource, which has the first response lost (so retransmissions are
|
||||
basically verified).
|
||||
|
||||
Please refer to the section above about how to run these applications
|
||||
together.
|
||||
|
|
25
samples/net/zoap_client/Makefile
Normal file
25
samples/net/zoap_client/Makefile
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Makefile - coap server test application
|
||||
|
||||
#
|
||||
# Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
MDEF_FILE = prj.mdef
|
||||
KERNEL_TYPE ?= nano
|
||||
BOARD = qemu_x86
|
||||
CONF_FILE = prj.conf
|
||||
|
||||
include $(ZEPHYR_BASE)/Makefile.inc
|
||||
include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack
|
15
samples/net/zoap_client/prj.conf
Normal file
15
samples/net/zoap_client/prj.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
CONFIG_NANOKERNEL=y
|
||||
CONFIG_NANO_TIMEOUTS=y
|
||||
CONFIG_NANO_WORKQUEUE=y
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NETWORKING_DEBUG_UART=y
|
||||
CONFIG_NETWORKING_IPV6_NO_ND=y
|
||||
CONFIG_NETWORKING_TESTING=y
|
||||
CONFIG_NETWORKING_UART=y
|
||||
CONFIG_NETWORKING_WITH_IPV6=y
|
||||
CONFIG_NETWORKING_WITH_LOGGING=y
|
||||
CONFIG_NETWORKING_WITH_LOOPBACK=y
|
||||
CONFIG_NETWORK_IP_STACK_DEBUG_FULL=y
|
||||
CONFIG_NET_TESTING=y
|
||||
CONFIG_SYSTEM_WORKQUEUE=y
|
||||
CONFIG_ZOAP=y
|
5
samples/net/zoap_client/prj.mdef
Normal file
5
samples/net/zoap_client/prj.mdef
Normal file
|
@ -0,0 +1,5 @@
|
|||
% Application : zoap server
|
||||
|
||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
||||
% ===================================================
|
||||
TASK MAIN 7 main 2048 [EXE]
|
11
samples/net/zoap_client/src/Makefile
Normal file
11
samples/net/zoap_client/src/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os/lib
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os
|
||||
|
||||
ifeq ($(CONFIG_NET_TESTING), y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/
|
||||
ccflags-y +=-DNET_TESTING_SERVER=1
|
||||
endif
|
||||
|
||||
obj-y = zoap-client.o
|
231
samples/net/zoap_client/src/zoap-client.c
Normal file
231
samples/net/zoap_client/src/zoap-client.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <misc/nano_work.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_socket.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/ip_buf.h>
|
||||
|
||||
#include <net_testing.h>
|
||||
|
||||
#include <zoap.h>
|
||||
|
||||
#define MY_COAP_PORT 9998
|
||||
|
||||
#define STACKSIZE 2000
|
||||
|
||||
#define NUM_PENDINGS 3
|
||||
#define NUM_REPLIES 3
|
||||
|
||||
#define ALL_NODES_LOCAL_COAP_MCAST \
|
||||
{ { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfd } } }
|
||||
|
||||
char fiberStack[STACKSIZE];
|
||||
|
||||
static struct net_context *send_context, *receive_context;
|
||||
|
||||
struct zoap_pending pendings[NUM_PENDINGS];
|
||||
struct zoap_reply replies[NUM_REPLIES];
|
||||
struct nano_delayed_work retransmit_work;
|
||||
|
||||
static const char * const a_light_path[] = { "a", "light", NULL };
|
||||
|
||||
static void msg_dump(const char *s, uint8_t *data, unsigned len)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
printf("%s: ", s);
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%02x ", data[i]);
|
||||
printf("(%u bytes)\n", len);
|
||||
}
|
||||
|
||||
static int resource_reply_cb(const struct zoap_packet *response,
|
||||
struct zoap_reply *reply, const void *from)
|
||||
{
|
||||
struct net_buf *buf = response->buf;
|
||||
|
||||
msg_dump("reply", buf->data, buf->len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void udp_receive(void)
|
||||
{
|
||||
struct zoap_packet response;
|
||||
struct zoap_pending *pending;
|
||||
struct zoap_reply *reply;
|
||||
struct net_buf *buf;
|
||||
int r;
|
||||
|
||||
while (true) {
|
||||
buf = net_receive(receive_context, TICKS_UNLIMITED);
|
||||
if (!buf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r = zoap_packet_parse(&response, buf);
|
||||
if (r < 0) {
|
||||
printf("Invalid data received (%d)\n", r);
|
||||
continue;
|
||||
}
|
||||
|
||||
pending = zoap_pending_received(&response, pendings,
|
||||
NUM_PENDINGS);
|
||||
if (pending) {
|
||||
/* If necessary cancel retransmissions */
|
||||
}
|
||||
|
||||
reply = zoap_response_received(&response, buf,
|
||||
replies, NUM_REPLIES);
|
||||
if (!reply) {
|
||||
printf("No handler for response (%d)\n", r);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void retransmit_request(struct nano_work *work)
|
||||
{
|
||||
struct zoap_pending *pending;
|
||||
struct zoap_packet *request;
|
||||
struct net_buf *buf;
|
||||
int r, timeout;
|
||||
|
||||
pending = zoap_pending_next_to_expire(pendings, NUM_PENDINGS);
|
||||
if (!pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
request = &pending->request;
|
||||
buf = request->buf;
|
||||
|
||||
r = net_send(buf);
|
||||
if (r < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!zoap_pending_cycle(pending)) {
|
||||
net_buf_unref(buf);
|
||||
zoap_pending_clear(pending);
|
||||
return;
|
||||
}
|
||||
|
||||
timeout = pending->timeout * (sys_clock_ticks_per_sec / MSEC_PER_SEC);
|
||||
nano_delayed_work_submit(&retransmit_work, timeout);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
static struct net_addr mcast_addr = {
|
||||
.in6_addr = ALL_NODES_LOCAL_COAP_MCAST,
|
||||
.family = AF_INET6 };
|
||||
static struct net_addr any_addr = { .in6_addr = IN6ADDR_ANY_INIT,
|
||||
.family = AF_INET6 };
|
||||
struct zoap_packet request;
|
||||
struct zoap_pending *pending;
|
||||
struct zoap_reply *reply;
|
||||
const char * const *p;
|
||||
struct net_buf *buf;
|
||||
int r, timeout;
|
||||
uint8_t observe = 0;
|
||||
|
||||
net_init();
|
||||
net_testing_setup();
|
||||
|
||||
send_context = net_context_get(IPPROTO_UDP,
|
||||
&mcast_addr, MY_COAP_PORT,
|
||||
&any_addr, MY_COAP_PORT);
|
||||
|
||||
receive_context = net_context_get(IPPROTO_UDP,
|
||||
&any_addr, MY_COAP_PORT,
|
||||
&mcast_addr, MY_COAP_PORT);
|
||||
|
||||
task_fiber_start(&fiberStack[0], STACKSIZE,
|
||||
(nano_fiber_entry_t) udp_receive, 0, 0, 7, 0);
|
||||
|
||||
nano_delayed_work_init(&retransmit_work, retransmit_request);
|
||||
|
||||
buf = ip_buf_get_tx(send_context);
|
||||
if (!buf) {
|
||||
printk("Unable to get TX buffer, not enough memory.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
r = zoap_packet_init(&request, buf);
|
||||
if (r < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: Could be that zoap_packet_init() sets some defaults */
|
||||
zoap_header_set_version(&request, 1);
|
||||
zoap_header_set_type(&request, ZOAP_TYPE_CON);
|
||||
zoap_header_set_code(&request, ZOAP_METHOD_GET);
|
||||
zoap_header_set_id(&request, zoap_next_id());
|
||||
|
||||
/* Enable observing the resource. */
|
||||
r = zoap_add_option(&request, ZOAP_OPTION_OBSERVE,
|
||||
&observe, sizeof(observe));
|
||||
if (r < 0) {
|
||||
printk("Unable add option to request.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (p = a_light_path; p && *p; p++) {
|
||||
r = zoap_add_option(&request, ZOAP_OPTION_URI_PATH,
|
||||
*p, strlen(*p));
|
||||
if (r < 0) {
|
||||
printk("Unable add option to request.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pending = zoap_pending_next_unused(pendings, NUM_PENDINGS);
|
||||
if (!pending) {
|
||||
printk("Unable to find a free pending to track "
|
||||
"retransmissions.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
r = zoap_pending_init(pending, &request);
|
||||
if (r < 0) {
|
||||
printk("Unable to initialize a pending retransmission.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
reply = zoap_reply_next_unused(replies, NUM_REPLIES);
|
||||
if (!reply) {
|
||||
printk("No resources for waiting for replies.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
zoap_reply_init(reply, &request);
|
||||
reply->reply = resource_reply_cb;
|
||||
|
||||
r = net_send(buf);
|
||||
if (r < 0) {
|
||||
printk("Error sending the packet (%d).\n", r);
|
||||
}
|
||||
|
||||
zoap_pending_cycle(pending);
|
||||
timeout = pending->timeout * (sys_clock_ticks_per_sec / MSEC_PER_SEC);
|
||||
|
||||
nano_delayed_work_submit(&retransmit_work, timeout);
|
||||
}
|
4
samples/net/zoap_client/testcase.ini
Normal file
4
samples/net/zoap_client/testcase.ini
Normal file
|
@ -0,0 +1,4 @@
|
|||
[test]
|
||||
tags = net
|
||||
build_only = true
|
||||
arch_whitelist = x86
|
Loading…
Reference in a new issue