Add Bluetooth examples
Co-authored-by: Peter Harper <77111776+peterharperuk@users.noreply.github.com>
This commit is contained in:
44
pico_w/wifi/tls_client/CMakeLists.txt
Normal file
44
pico_w/wifi/tls_client/CMakeLists.txt
Normal file
@@ -0,0 +1,44 @@
|
||||
add_executable(picow_tls_client_background
|
||||
picow_tls_client.c
|
||||
)
|
||||
target_compile_definitions(picow_tls_client_background PRIVATE
|
||||
WIFI_SSID=\"${WIFI_SSID}\"
|
||||
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
|
||||
)
|
||||
target_include_directories(picow_tls_client_background PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts
|
||||
)
|
||||
target_link_libraries(picow_tls_client_background
|
||||
pico_cyw43_arch_lwip_threadsafe_background
|
||||
pico_lwip_mbedtls
|
||||
pico_mbedtls
|
||||
pico_stdlib
|
||||
)
|
||||
pico_add_extra_outputs(picow_tls_client_background)
|
||||
|
||||
add_executable(picow_tls_client_poll
|
||||
picow_tls_client.c
|
||||
)
|
||||
target_compile_definitions(picow_tls_client_poll PRIVATE
|
||||
WIFI_SSID=\"${WIFI_SSID}\"
|
||||
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
|
||||
)
|
||||
target_include_directories(picow_tls_client_poll PRIVATE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts
|
||||
)
|
||||
target_link_libraries(picow_tls_client_poll
|
||||
pico_cyw43_arch_lwip_poll
|
||||
pico_lwip_mbedtls
|
||||
pico_mbedtls
|
||||
pico_stdlib
|
||||
)
|
||||
pico_add_extra_outputs(picow_tls_client_poll)
|
||||
|
||||
# Ignore warnings from lwip code
|
||||
set_source_files_properties(
|
||||
${PICO_LWIP_PATH}/src/apps/altcp_tls/altcp_tls_mbedtls.c
|
||||
PROPERTIES
|
||||
COMPILE_OPTIONS "-Wno-unused-result"
|
||||
)
|
||||
19
pico_w/wifi/tls_client/lwipopts.h
Normal file
19
pico_w/wifi/tls_client/lwipopts.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef _LWIPOPTS_H
|
||||
#define _LWIPOPTS_H
|
||||
|
||||
#include "lwipopts_examples_common.h"
|
||||
|
||||
/* TCP WND must be at least 16 kb to match TLS record size
|
||||
or you will get a warning "altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!" */
|
||||
#undef TCP_WND
|
||||
#define TCP_WND 16384
|
||||
|
||||
#define LWIP_ALTCP 1
|
||||
#define LWIP_ALTCP_TLS 1
|
||||
#define LWIP_ALTCP_TLS_MBEDTLS 1
|
||||
|
||||
#define LWIP_DEBUG 1
|
||||
#define ALTCP_MBEDTLS_DEBUG LWIP_DBG_ON
|
||||
|
||||
#endif
|
||||
|
||||
63
pico_w/wifi/tls_client/mbedtls_config.h
Normal file
63
pico_w/wifi/tls_client/mbedtls_config.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* Workaround for some mbedtls source files using INT_MAX without including limits.h */
|
||||
#include <limits.h>
|
||||
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
|
||||
#define MBEDTLS_SSL_OUT_CONTENT_LEN 2048
|
||||
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_SHA256_SMALLER
|
||||
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_ERROR_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PKCS5_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_AES_FEWER_TABLES
|
||||
|
||||
/* TLS 1.2 */
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#define MBEDTLS_GCM_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
|
||||
244
pico_w/wifi/tls_client/picow_tls_client.c
Normal file
244
pico_w/wifi/tls_client/picow_tls_client.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/cyw43_arch.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/altcp_tcp.h"
|
||||
#include "lwip/altcp_tls.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#define TLS_CLIENT_SERVER "worldtimeapi.org"
|
||||
#define TLS_CLIENT_HTTP_REQUEST "GET /api/ip HTTP/1.1\r\n" \
|
||||
"Host: " TLS_CLIENT_SERVER "\r\n" \
|
||||
"Connection: close\r\n" \
|
||||
"\r\n"
|
||||
#define TLS_CLIENT_TIMEOUT_SECS 15
|
||||
|
||||
|
||||
typedef struct TLS_CLIENT_T_ {
|
||||
struct altcp_pcb *pcb;
|
||||
bool complete;
|
||||
} TLS_CLIENT_T;
|
||||
|
||||
static struct altcp_tls_config *tls_config = NULL;
|
||||
|
||||
static err_t tls_client_close(void *arg) {
|
||||
TLS_CLIENT_T *state = (TLS_CLIENT_T*)arg;
|
||||
err_t err = ERR_OK;
|
||||
|
||||
state->complete = true;
|
||||
if (state->pcb != NULL) {
|
||||
altcp_arg(state->pcb, NULL);
|
||||
altcp_poll(state->pcb, NULL, 0);
|
||||
altcp_recv(state->pcb, NULL);
|
||||
altcp_err(state->pcb, NULL);
|
||||
err = altcp_close(state->pcb);
|
||||
if (err != ERR_OK) {
|
||||
printf("close failed %d, calling abort\n", err);
|
||||
altcp_abort(state->pcb);
|
||||
err = ERR_ABRT;
|
||||
}
|
||||
state->pcb = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static err_t tls_client_connected(void *arg, struct altcp_pcb *pcb, err_t err) {
|
||||
TLS_CLIENT_T *state = (TLS_CLIENT_T*)arg;
|
||||
if (err != ERR_OK) {
|
||||
printf("connect failed %d\n", err);
|
||||
return tls_client_close(state);
|
||||
}
|
||||
|
||||
printf("connected to server, sending request\n");
|
||||
err = altcp_write(state->pcb, TLS_CLIENT_HTTP_REQUEST, strlen(TLS_CLIENT_HTTP_REQUEST), TCP_WRITE_FLAG_COPY);
|
||||
if (err != ERR_OK) {
|
||||
printf("error writing data, err=%d", err);
|
||||
return tls_client_close(state);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t tls_client_poll(void *arg, struct altcp_pcb *pcb) {
|
||||
printf("timed out");
|
||||
return tls_client_close(arg);
|
||||
}
|
||||
|
||||
static void tls_client_err(void *arg, err_t err) {
|
||||
TLS_CLIENT_T *state = (TLS_CLIENT_T*)arg;
|
||||
printf("tls_client_err %d\n", err);
|
||||
state->pcb = NULL; /* pcb freed by lwip when _err function is called */
|
||||
}
|
||||
|
||||
static err_t tls_client_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) {
|
||||
TLS_CLIENT_T *state = (TLS_CLIENT_T*)arg;
|
||||
if (!p) {
|
||||
printf("connection closed\n");
|
||||
return tls_client_close(state);
|
||||
}
|
||||
|
||||
if (p->tot_len > 0) {
|
||||
/* For simplicity this examples creates a buffer on stack the size of the data pending here,
|
||||
and copies all the data to it in one go.
|
||||
Do be aware that the amount of data can potentially be a bit large (TLS record size can be 16 KB),
|
||||
so you may want to use a smaller fixed size buffer and copy the data to it using a loop, if memory is a concern */
|
||||
char buf[p->tot_len + 1];
|
||||
|
||||
pbuf_copy_partial(p, buf, p->tot_len, 0);
|
||||
buf[p->tot_len] = 0;
|
||||
|
||||
printf("***\nnew data received from server:\n***\n\n%s\n", buf);
|
||||
|
||||
altcp_recved(pcb, p->tot_len);
|
||||
}
|
||||
pbuf_free(p);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void tls_client_connect_to_server_ip(const ip_addr_t *ipaddr, TLS_CLIENT_T *state)
|
||||
{
|
||||
err_t err;
|
||||
u16_t port = 443;
|
||||
|
||||
printf("connecting to server IP %s port %d\n", ipaddr_ntoa(ipaddr), port);
|
||||
err = altcp_connect(state->pcb, ipaddr, port, tls_client_connected);
|
||||
if (err != ERR_OK)
|
||||
{
|
||||
fprintf(stderr, "error initiating connect, err=%d\n", err);
|
||||
tls_client_close(state);
|
||||
}
|
||||
}
|
||||
|
||||
static void tls_client_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg)
|
||||
{
|
||||
if (ipaddr)
|
||||
{
|
||||
printf("DNS resolving complete\n");
|
||||
tls_client_connect_to_server_ip(ipaddr, (TLS_CLIENT_T *) arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("error resolving hostname %s\n", hostname);
|
||||
tls_client_close(arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool tls_client_open(const char *hostname, void *arg) {
|
||||
err_t err;
|
||||
ip_addr_t server_ip;
|
||||
TLS_CLIENT_T *state = (TLS_CLIENT_T*)arg;
|
||||
|
||||
state->pcb = altcp_tls_new(tls_config, IPADDR_TYPE_ANY);
|
||||
if (!state->pcb) {
|
||||
printf("failed to create pcb\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
altcp_arg(state->pcb, state);
|
||||
altcp_poll(state->pcb, tls_client_poll, TLS_CLIENT_TIMEOUT_SECS * 2);
|
||||
altcp_recv(state->pcb, tls_client_recv);
|
||||
altcp_err(state->pcb, tls_client_err);
|
||||
|
||||
/* Set SNI */
|
||||
mbedtls_ssl_set_hostname(altcp_tls_context(state->pcb), hostname);
|
||||
|
||||
printf("resolving %s\n", hostname);
|
||||
|
||||
// cyw43_arch_lwip_begin/end should be used around calls into lwIP to ensure correct locking.
|
||||
// You can omit them if you are in a callback from lwIP. Note that when using pico_cyw_arch_poll
|
||||
// these calls are a no-op and can be omitted, but it is a good practice to use them in
|
||||
// case you switch the cyw43_arch type later.
|
||||
cyw43_arch_lwip_begin();
|
||||
|
||||
err = dns_gethostbyname(hostname, &server_ip, tls_client_dns_found, state);
|
||||
if (err == ERR_OK)
|
||||
{
|
||||
/* host is in DNS cache */
|
||||
tls_client_connect_to_server_ip(&server_ip, state);
|
||||
}
|
||||
else if (err != ERR_INPROGRESS)
|
||||
{
|
||||
printf("error initiating DNS resolving, err=%d\n", err);
|
||||
tls_client_close(state->pcb);
|
||||
}
|
||||
|
||||
cyw43_arch_lwip_end();
|
||||
|
||||
return err == ERR_OK || err == ERR_INPROGRESS;
|
||||
}
|
||||
|
||||
// Perform initialisation
|
||||
static TLS_CLIENT_T* tls_client_init(void) {
|
||||
TLS_CLIENT_T *state = calloc(1, sizeof(TLS_CLIENT_T));
|
||||
if (!state) {
|
||||
printf("failed to allocate state\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void run_tls_client_test(void) {
|
||||
/* No CA certificate checking */
|
||||
tls_config = altcp_tls_create_config_client(NULL, 0);
|
||||
|
||||
TLS_CLIENT_T *state = tls_client_init();
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
if (!tls_client_open(TLS_CLIENT_SERVER, state)) {
|
||||
return;
|
||||
}
|
||||
while(!state->complete) {
|
||||
// the following #ifdef is only here so this same example can be used in multiple modes;
|
||||
// you do not need it in your code
|
||||
#if PICO_CYW43_ARCH_POLL
|
||||
// if you are using pico_cyw43_arch_poll, then you must poll periodically from your
|
||||
// main loop (not from a timer) to check for Wi-Fi driver or lwIP work that needs to be done.
|
||||
cyw43_arch_poll();
|
||||
// you can poll as often as you like, however if you have nothing else to do you can
|
||||
// choose to sleep until either a specified time, or cyw43_arch_poll() has work to do:
|
||||
cyw43_arch_wait_for_work_until(make_timeout_time_ms(1000));
|
||||
#else
|
||||
// if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work
|
||||
// is done via interrupt in the background. This sleep is just an example of some (blocking)
|
||||
// work you might be doing.
|
||||
sleep_ms(1000);
|
||||
#endif
|
||||
}
|
||||
free(state);
|
||||
altcp_tls_free_config(tls_config);
|
||||
}
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
if (cyw43_arch_init()) {
|
||||
printf("failed to initialise\n");
|
||||
return 1;
|
||||
}
|
||||
cyw43_arch_enable_sta_mode();
|
||||
|
||||
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||
printf("failed to connect\n");
|
||||
return 1;
|
||||
}
|
||||
run_tls_client_test();
|
||||
|
||||
/* sleep a bit to let usb stdio write out any buffer to host */
|
||||
sleep_ms(100);
|
||||
|
||||
cyw43_arch_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user