Files
libcoap/examples/zephyr/client-src/src/main.c
T
Marco Casaroli a90916a4fe zephyr: mbedlts improvements
Add some improvements to make secure coap work on Zephyr 4.3.0
with mbedtls (not using Zephyr TLS protocol options).

We now set the build options to zephyr, so we make use of the
internal mbedtl in zephyr, so we do not require a specific header
file anymore.

In older versions of Zephyr, where mbedtls does not expose the
configuration, we can force-set the macro in the C flags, so that
mbedtls will have our required function.

This way, we do not need to change the mbedtls included in Zephyr,
while still supporting a few older versions.
2026-01-30 16:18:34 +00:00

213 lines
5.5 KiB
C

/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(coap_client, LOG_LEVEL_DBG);
#include <zephyr/kernel.h>
#include <errno.h>
#include "coap3/coap.h"
#include <stdio.h>
#include <zephyr/net/net_core.h>
#ifdef CONFIG_MBEDTLS
#define COAP_USE_PSK CONFIG_LIBCOAP_PSK_KEY
#define COAP_USE_PSK_ID CONFIG_LIBCOAP_PSK_IDENTITY
#endif /* CONFIG_MBEDTLS */
#define COAP_TARGET_DOMAIN_URI CONFIG_LIBCOAP_TARGET_DOMAIN_URI
const char *coap_uri = COAP_TARGET_DOMAIN_URI;
static int quit;
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;
/* 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_session3(ctx, NULL, &dst, COAP_PROTO_UDP, NULL, NULL, NULL);
} 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_psk3(ctx, NULL, &dst, COAP_PROTO_DTLS, &dtls_psk, NULL, NULL, NULL);
#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;
}
len = coap_uri_into_options(&uri, &dst, &optlist, 1, buf, sizeof(buf));
if (len) {
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;
}
/* This application itself does nothing as there is net-shell that can be used
* to monitor things.
*/
int main(void)
{
LOG_INF("Start application");
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 and initiate client logic */
int rc = coap_client_init(coap_context);
coap_log_info("libcoap test client started\n");
/* Keep on processing until response is back in ... */
while (rc && 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();
return 1;
}