diff options
author | Sergio Rodriguez <sergio.sf.rodriguez@intel.com> | 2017-01-23 14:42:29 -0800 |
---|---|---|
committer | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2017-01-27 12:35:53 +0200 |
commit | 98d7ff00136ce366160b9feb67b3d68558cb3a61 (patch) | |
tree | 36cf3561e99c929b489689fc93d82acf6162da99 /samples | |
parent | 3818af4a7b12bf17e481efa8ba626347d4ca9d74 (diff) |
samples/coaps_client CoAP over DTLS client example app using mbedTLS
Jira: ZEP-941
Change-Id: Ia49087b75b33bcedb1b77b6a062368281c41e479
Signed-off-by: Sergio Rodriguez <sergio.sf.rodriguez@intel.com>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/net/coaps_client/Makefile | 14 | ||||
-rw-r--r-- | samples/net/coaps_client/README.rst | 53 | ||||
-rw-r--r-- | samples/net/coaps_client/prj_qemu_x86.conf | 27 | ||||
-rw-r--r-- | samples/net/coaps_client/src/Makefile | 7 | ||||
-rw-r--r-- | samples/net/coaps_client/src/coaps_client.c | 447 | ||||
-rw-r--r-- | samples/net/coaps_client/src/udp.c | 202 | ||||
-rw-r--r-- | samples/net/coaps_client/src/udp.h | 23 | ||||
-rw-r--r-- | samples/net/coaps_client/src/udp_cfg.h | 21 | ||||
-rw-r--r-- | samples/net/coaps_client/testcase.ini | 4 |
9 files changed, 798 insertions, 0 deletions
diff --git a/samples/net/coaps_client/Makefile b/samples/net/coaps_client/Makefile new file mode 100644 index 000000000..8e54ca81d --- /dev/null +++ b/samples/net/coaps_client/Makefile @@ -0,0 +1,14 @@ +# Makefile - CoAP secure client test application + +# +# Copyright (c) 2015 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +BOARD ?= qemu_x86 +CONF_FILE ?= prj_$(BOARD).conf + +include $(ZEPHYR_BASE)/Makefile.inc + +include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack diff --git a/samples/net/coaps_client/README.rst b/samples/net/coaps_client/README.rst new file mode 100644 index 000000000..bdc1696cd --- /dev/null +++ b/samples/net/coaps_client/README.rst @@ -0,0 +1,53 @@ +CoAP over DTLS sample client +############################ + +Overview +======== +This sample code shows a CoAP over DTLS client using mbedTLS on top of Zephyr. + +Building and Running +==================== + +Follow the steps for testing :ref:`networking with Qemu <networking_with_qemu>`. + +Run the server application at samples/net/coaps_server, with the following +command: + +.. code-block:: console + + make server + +In other terminal window, run this client application at samples/net/coaps_client: + +.. code-block:: console + + make client + +You will get the following output: + +.. code-block:: console + + reply: 60 45 00 01 ff 54 79 70 65 3a 20 30 0a 43 6f 64 65 3a 20 31 0a 4d + 49 44 3a 20 31 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 (123 bytes) + +From the server application directory the screen should display + +.. code-block:: console + + ******* + type: 0 code 1 id 1 + ******* + connection was closed gracefully + done + +If the server does not receive the messages, restart the app and try to connect +the client again. + +References +========== + +* https://wiki.zephyrproject.org/view/Networking-with-Qemu diff --git a/samples/net/coaps_client/prj_qemu_x86.conf b/samples/net/coaps_client/prj_qemu_x86.conf new file mode 100644 index 000000000..209dd3698 --- /dev/null +++ b/samples/net/coaps_client/prj_qemu_x86.conf @@ -0,0 +1,27 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV6=y +CONFIG_NET_UDP=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_BUF_LOG=y +CONFIG_NET_LOG=y +CONFIG_NET_SLIP_TAP=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_NBUF_RX_COUNT=14 +CONFIG_NET_NBUF_TX_COUNT=14 +CONFIG_NET_NBUF_DATA_COUNT=30 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 +CONFIG_NET_MAX_CONTEXTS=10 + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_CFG_FILE="config-coap.h" + +CONFIG_ZOAP=y + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::3" +CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::1" diff --git a/samples/net/coaps_client/src/Makefile b/samples/net/coaps_client/src/Makefile new file mode 100644 index 000000000..788664861 --- /dev/null +++ b/samples/net/coaps_client/src/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (c) 2016 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +obj-y += coaps_client.o udp.o diff --git a/samples/net/coaps_client/src/coaps_client.c b/samples/net/coaps_client/src/coaps_client.c new file mode 100644 index 000000000..84f875f74 --- /dev/null +++ b/samples/net/coaps_client/src/coaps_client.c @@ -0,0 +1,447 @@ +/* Sample CoAP over DTLS client using mbedTLS. + * (Meant to be used with config-coap.h) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * SPDX-License-Identifier: Apache-2.0 + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include <zephyr.h> +#include <stdio.h> +#include <errno.h> +#include <misc/printk.h> + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include <stdlib.h> +#define mbedtls_time_t time_t +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#include <string.h> +#include <net/net_context.h> +#include <net/net_if.h> +#include <net/buf.h> +#include <net/nbuf.h> +#include "udp.h" +#include "udp_cfg.h" + +#include "mbedtls/net.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include <net/zoap.h> + +#if defined(MBEDTLS_DEBUG_C) +#include "mbedtls/debug.h" +#define DEBUG_THRESHOLD 0 +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +static unsigned char heap[8192]; +#endif + +/* + * Hardcoded values for server host and port + */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +const unsigned char psk[] = "passwd\0"; +const char psk_id[] = "Client_identity\0"; +#endif + +const char *pers = "mini_client"; +static unsigned char payload[128]; + +#define NUM_REPLIES 3 +struct zoap_reply replies[NUM_REPLIES]; + +#define ZOAP_BUF_SIZE 128 + +NET_BUF_POOL_DEFINE(zoap_nbuf_pool, 4, 0, sizeof(struct net_nbuf), NULL); +NET_BUF_POOL_DEFINE(zoap_data_pool, 4, ZOAP_BUF_SIZE, 0, NULL); + +static const char *const test_path[] = { "test", NULL }; + +static struct in6_addr mcast_addr = MCAST_IP_ADDR; + +struct dtls_timing_context { + uint32_t snapshot; + uint32_t int_ms; + uint32_t fin_ms; +}; + +static void msg_dump(const char *s, uint8_t *data, unsigned int len) +{ + unsigned int i; + + printk("%s: ", s); + for (i = 0; i < len; i++) { + printk("%02x ", data[i]); + } + + printk("(%u bytes)\n", len); +} + +static int resource_reply_cb(const struct zoap_packet *response, + struct zoap_reply *reply, + const struct sockaddr *from) +{ + + struct net_buf *frag = response->buf->frags; + + while (frag) { + msg_dump("reply", frag->data, frag->len); + frag = frag->frags; + } + + return 0; +} + +static void my_debug(void *ctx, int level, + const char *file, int line, const char *str) +{ + const char *p, *basename; + + /* Extract basename from file */ + for (p = basename = file; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + basename = p + 1; + } + } + + mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); +} + +void dtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms) +{ + struct dtls_timing_context *ctx = (struct dtls_timing_context *)data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if (fin_ms != 0) { + ctx->snapshot = k_uptime_get_32(); + } +} + +int dtls_timing_get_delay(void *data) +{ + struct dtls_timing_context *ctx = (struct dtls_timing_context *)data; + unsigned long elapsed_ms; + + if (ctx->fin_ms == 0) { + return -1; + } + + elapsed_ms = k_uptime_get_32() - ctx->snapshot; + + if (elapsed_ms >= ctx->fin_ms) { + return 2; + } + + if (elapsed_ms >= ctx->int_ms) { + return 1; + } + + return 0; +} + +static int entropy_source(void *data, unsigned char *output, size_t len, + size_t *olen) +{ + uint32_t seed; + char *ptr = data; + + seed = sys_rand32_get(); + + if (!seed) { + seed = 7; + } + + for (int i = 0; i < len; i++) { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + *ptr++ = (char)seed; + } + + *olen = len; + return 0; +} + +void dtls_client(void) +{ + int ret; + struct udp_context ctx; + struct dtls_timing_context timer; + struct zoap_packet request, pkt; + struct zoap_reply *reply; + struct net_buf *nbuf, *frag; + uint8_t observe = 0; + const char *const *p; + uint16_t len; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_platform_set_printf(printk); + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + mbedtls_entropy_init(&entropy); + mbedtls_entropy_add_source(&entropy, entropy_source, NULL, + MBEDTLS_ENTROPY_MAX_GATHER, + MBEDTLS_ENTROPY_SOURCE_STRONG); + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (ret != 0) { + mbedtls_printf("mbedtls_ctr_drbg_seed failed returned -0x%x\n", + -ret); + goto exit; + } + + ret = mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) { + mbedtls_printf("mbedtls_ssl_config_defaults" + " failed! returned -0x%x\n", -ret); + goto exit; + } + +/* Modify this to change the default timeouts for the DTLS handshake */ +/* mbedtls_ssl_conf_handshake_timeout( &conf, min, max ); */ + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(DEBUG_THRESHOLD); +#endif + + mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); +#endif + + ret = mbedtls_ssl_setup(&ssl, &conf); + + if (ret != 0) { + mbedtls_printf("mbedtls_ssl_setup failed returned -0x%x\n", + -ret); + goto exit; + } + + ret = udp_init(&ctx); + if (ret != 0) { + mbedtls_printf("udp_init failed returned 0x%x\n", ret); + goto exit; + } + + udp_tx(&ctx, payload, 32); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + ret = mbedtls_ssl_conf_psk(&conf, psk, strlen(psk), psk_id, + strlen(psk_id)); + if (ret != 0) { + mbedtls_printf(" failed\n mbedtls_ssl_conf_psk" + " returned -0x%x\n", -ret); + goto exit; + } +#endif + + mbedtls_ssl_set_timer_cb(&ssl, &timer, dtls_timing_set_delay, + dtls_timing_get_delay); + + mbedtls_ssl_set_bio(&ssl, &ctx, udp_tx, NULL, udp_rx); + + do { + ret = mbedtls_ssl_handshake(&ssl); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (ret != 0) { + mbedtls_printf("mbedtls_ssl_handshake failed returned -0x%x\n", + -ret); + goto exit; + } + + /* Write to server */ +retry: + nbuf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!nbuf) { + goto exit; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + goto exit; + } + + net_buf_frag_add(nbuf, frag); + + ret = zoap_packet_init(&request, nbuf); + if (ret < 0) { + goto exit; + } + + 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()); + zoap_header_set_token(&request, zoap_next_token(), 0); + + /* Enable observing the resource. */ + ret = zoap_add_option(&request, ZOAP_OPTION_OBSERVE, + &observe, sizeof(observe)); + if (ret < 0) { + mbedtls_printf("Unable add option to request.\n"); + goto exit; + } + + for (p = test_path; p && *p; p++) { + ret = zoap_add_option(&request, ZOAP_OPTION_URI_PATH, + *p, strlen(*p)); + if (ret < 0) { + mbedtls_printf("Unable add option/path to request.\n"); + goto exit; + } + } + + reply = zoap_reply_next_unused(replies, NUM_REPLIES); + if (!reply) { + mbedtls_printf("No resources for waiting for replies.\n"); + goto exit; + } + + zoap_reply_init(reply, &request); + reply->reply = resource_reply_cb; + len = frag->len; + + do { + ret = mbedtls_ssl_write(&ssl, frag->data, len); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + net_buf_unref(nbuf); + + if (ret <= 0) { + mbedtls_printf("mbedtls_ssl_write failed returned 0x%x\n", + -ret); + goto exit; + } + + nbuf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!nbuf) { + mbedtls_printf("Could not get buffer from pool\n"); + goto exit; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + mbedtls_printf("Could not get frag from pool\n"); + goto exit; + } + + net_buf_frag_add(nbuf, frag); + len = ZOAP_BUF_SIZE - 1; + memset(frag->data, 0, ZOAP_BUF_SIZE); + + do { + ret = mbedtls_ssl_read(&ssl, frag->data, ZOAP_BUF_SIZE - 1); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (ret <= 0) { + net_buf_unref(nbuf); + + switch (ret) { + case MBEDTLS_ERR_SSL_TIMEOUT: + mbedtls_printf(" timeout\n"); + goto retry; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf(" connection was closed" + " gracefully\n"); + goto exit; + + default: + mbedtls_printf(" mbedtls_ssl_read" + " returned -0x%x\n", -ret); + goto exit; + } + } + + len = ret; + frag->len = len; + + ret = zoap_packet_parse(&pkt, nbuf); + if (ret) { + mbedtls_printf("Could not parse packet\n"); + goto exit; + } + + reply = zoap_response_received(&pkt, NULL, replies, NUM_REPLIES); + if (!reply) { + mbedtls_printf("No handler for response (%d)\n", ret); + } + + net_buf_unref(nbuf); + mbedtls_ssl_close_notify(&ssl); +exit: + + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); +} + +#define STACK_SIZE 4096 +uint8_t stack[STACK_SIZE]; + +static inline int init_app(void) +{ +#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR) + if (net_addr_pton(AF_INET6, + CONFIG_NET_SAMPLES_MY_IPV6_ADDR, + (struct sockaddr *)&client_addr) < 0) { + mbedtls_printf("Invalid IPv6 address %s", + CONFIG_NET_SAMPLES_MY_IPV6_ADDR); + } +#endif + if (!net_if_ipv6_addr_add(net_if_get_default(), &client_addr, + NET_ADDR_MANUAL, 0)) { + return -EIO; + } + + net_if_ipv6_maddr_add(net_if_get_default(), &mcast_addr); + + return 0; +} + +void main(void) +{ + if (init_app() != 0) { + printk("Cannot initialize network\n"); + return; + } + + k_thread_spawn(stack, STACK_SIZE, (k_thread_entry_t) dtls_client, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0); +} diff --git a/samples/net/coaps_client/src/udp.c b/samples/net/coaps_client/src/udp.c new file mode 100644 index 000000000..2663c79a0 --- /dev/null +++ b/samples/net/coaps_client/src/udp.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include <zephyr.h> +#include <net/net_core.h> +#include <net/net_context.h> +#include <net/nbuf.h> +#include <net/net_if.h> +#include <string.h> +#include <errno.h> +#include <misc/printk.h> + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif +#include "mbedtls/ssl.h" + +#include "udp_cfg.h" +#include "udp.h" + +static struct in6_addr server_addr; +static struct in6_addr mcast_addr = MCAST_IP_ADDR; +static const socklen_t addrlen = sizeof(struct sockaddr_in6); + +static void set_destination(struct sockaddr *addr) +{ + struct sockaddr_in6 *dst_addr = (struct sockaddr_in6 *)addr; + + net_ipaddr_copy(&dst_addr->sin6_addr, &server_addr); + dst_addr->sin6_family = AF_INET6; + dst_addr->sin6_port = htons(SERVER_PORT); +} + +static void udp_received(struct net_context *context, + struct net_buf *buf, int status, void *user_data) +{ + struct udp_context *ctx = user_data; + + ARG_UNUSED(context); + ARG_UNUSED(status); + + ctx->rx_nbuf = buf; + k_sem_give(&ctx->rx_sem); +} + +int udp_tx(void *context, const unsigned char *buf, size_t size) +{ + struct udp_context *ctx = context; + struct net_context *udp_ctx; + struct net_buf *send_buf; + struct sockaddr dst_addr; + int rc, len; + + udp_ctx = ctx->net_ctx; + + send_buf = net_nbuf_get_tx(udp_ctx); + if (!send_buf) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + rc = net_nbuf_append(send_buf, size, (uint8_t *) buf); + if (!rc) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + set_destination(&dst_addr); + len = net_buf_frags_len(send_buf); + k_sleep(UDP_TX_TIMEOUT); + + rc = net_context_sendto(send_buf, &dst_addr, + addrlen, NULL, K_FOREVER, NULL, NULL); + if (rc < 0) { + net_nbuf_unref(send_buf); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } else { + return len; + } +} + +int udp_rx(void *context, unsigned char *buf, size_t size, uint32_t timeout) +{ + struct udp_context *ctx = context; + struct net_buf *rx_buf = NULL; + uint16_t read_bytes; + uint8_t *ptr; + int pos; + int len; + int rc; + + rc = k_sem_take(&ctx->rx_sem, timeout == 0 ? K_FOREVER : timeout); + if (rc != 0) { + return MBEDTLS_ERR_SSL_TIMEOUT; + } + + read_bytes = net_nbuf_appdatalen(ctx->rx_nbuf); + if (read_bytes > size) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + ptr = net_nbuf_appdata(ctx->rx_nbuf); + rx_buf = ctx->rx_nbuf->frags; + len = rx_buf->len - (ptr - rx_buf->data); + pos = 0; + + while (rx_buf) { + memcpy(buf + pos, ptr, len); + pos += len; + + rx_buf = rx_buf->frags; + if (!rx_buf) { + break; + } + + ptr = rx_buf->data; + len = rx_buf->len; + } + + net_nbuf_unref(ctx->rx_nbuf); + ctx->rx_nbuf = NULL; + + if (read_bytes != pos) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + rc = read_bytes; + ctx->remaining = 0; + + return rc; +} + +int udp_init(struct udp_context *ctx) +{ + struct net_context *udp_ctx = { 0 }; + struct net_context *mcast_ctx = { 0 }; + struct sockaddr_in6 my_addr = { 0 }; + struct sockaddr_in6 my_mcast_addr = { 0 }; + int rc; + + k_sem_init(&ctx->rx_sem, 0, UINT_MAX); + + net_ipaddr_copy(&my_mcast_addr.sin6_addr, &mcast_addr); + my_mcast_addr.sin6_family = AF_INET6; + + net_ipaddr_copy(&my_addr.sin6_addr, &client_addr); + my_addr.sin6_family = AF_INET6; + my_addr.sin6_port = htons(CLIENT_PORT); + + rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &udp_ctx); + if (rc < 0) { + printk("Cannot get network context for IPv6 UDP (%d)", rc); + return -EIO; + } + + rc = net_context_bind(udp_ctx, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr_in6)); + if (rc < 0) { + printk("Cannot bind IPv6 UDP port %d (%d)", CLIENT_PORT, rc); + goto error; + } + + rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &mcast_ctx); + if (rc < 0) { + printk("Cannot get receiving IPv6 mcast (%d)", rc); + goto error; + } + + rc = net_context_bind(mcast_ctx, (struct sockaddr *)&my_mcast_addr, + sizeof(struct sockaddr_in6)); + if (rc < 0) { + printk("Cannot get bind IPv6 mcast (%d)", rc); + goto error; + } + + ctx->rx_nbuf = NULL; + ctx->remaining = 0; + ctx->net_ctx = udp_ctx; + +#if defined(CONFIG_NET_SAMPLES_PEER_IPV6_ADDR) + if (net_addr_pton(AF_INET6, + CONFIG_NET_SAMPLES_PEER_IPV6_ADDR, + (struct sockaddr *)&server_addr) < 0) { + printk("Invalid peer IPv6 address %s", + CONFIG_NET_SAMPLES_PEER_IPV6_ADDR); + } +#endif + + rc = net_context_recv(ctx->net_ctx, udp_received, K_NO_WAIT, ctx); + if (rc != 0) { + return -EIO; + } + + return 0; + +error: + net_context_put(udp_ctx); + return -EINVAL; +} diff --git a/samples/net/coaps_client/src/udp.h b/samples/net/coaps_client/src/udp.h new file mode 100644 index 000000000..7d96b3045 --- /dev/null +++ b/samples/net/coaps_client/src/udp.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _UDP_H_ +#define _UDP_H_ + +#include <net/net_core.h> + +struct udp_context { + struct net_context *net_ctx; + struct net_buf *rx_nbuf; + struct k_sem rx_sem; + int remaining; +}; + +int udp_init(struct udp_context *ctx); +int udp_tx(void *ctx, const unsigned char *buf, size_t size); +int udp_rx(void *ctx, unsigned char *buf, size_t size, uint32_t timeout); + +#endif diff --git a/samples/net/coaps_client/src/udp_cfg.h b/samples/net/coaps_client/src/udp_cfg.h new file mode 100644 index 000000000..d6cc6b6c6 --- /dev/null +++ b/samples/net/coaps_client/src/udp_cfg.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef UDP_CONFIG_H_ +#define UDP_CONFIG_H_ + +/* admin-local, dynamically allocated multicast address */ +#define MCAST_IP_ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0x2 } } } + +static struct in6_addr client_addr; + +#define SERVER_PORT 5684 +#define CLIENT_PORT 8484 + +#define UDP_TX_TIMEOUT 100 /* Timeout in milliseconds */ + +#endif diff --git a/samples/net/coaps_client/testcase.ini b/samples/net/coaps_client/testcase.ini new file mode 100644 index 000000000..bd398cafe --- /dev/null +++ b/samples/net/coaps_client/testcase.ini @@ -0,0 +1,4 @@ +[test] +tags = net +build_only = true +arch_whitelist = qemu_x86 arduino_101 |