Skip to content

Commit 2ca4da9

Browse files
committed
Add HTTP client examples
Examples to demonstrate HTTP, HTTPS and TLS validation Fixes #318
1 parent 96f4abe commit 2ca4da9

File tree

13 files changed

+601
-0
lines changed

13 files changed

+601
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ App|Description
130130
[picow_tls_verify](pico_w/wifi/tls_client) | Demonstrates how to make a HTTPS request using TLS with certificate verification.
131131
[picow_wifi_scan](pico_w/wifi/wifi_scan) | Scans for WiFi networks and prints the results.
132132
[picow_udp_beacon](pico_w/wifi/udp_beacon) | A simple UDP transmitter.
133+
[picow_http_client](pico_w/wifi/http_client) | Demonstrates how to make http and https requests
134+
[picow_http_client_verify](pico_w/wifi/http_client) | Demonstrates how to make a https request with server authentication
133135

134136
#### FreeRTOS examples
135137

@@ -142,6 +144,8 @@ App|Description
142144
[picow_freertos_iperf_server_sys](pico_w/wifi/freertos/iperf) | Runs an "iperf" server for WiFi speed testing under FreeRTOS in NO_SYS=0 (i.e. full FreeRTOS integration) mode. The LED is blinked in another task
143145
[picow_freertos_ping_nosys](pico_w/wifi/freertos/ping) | Runs the lwip-contrib/apps/ping test app under FreeRTOS in NO_SYS=1 mode.
144146
[picow_freertos_ping_sys](pico_w/wifi/freertos/ping) | Runs the lwip-contrib/apps/ping test app under FreeRTOS in NO_SYS=0 (i.e. full FreeRTOS integration) mode. The test app uses the lwIP _socket_ API in this case.
147+
[picow_freertos_http_client_nosys](pico_w/wifi/freertos/http_client) | Demonstrates how to make a https request in NO_SYS=1 mode
148+
[picow_freertos_http_client_sys](pico_w/wifi/freertos/http_client) | Demonstrates how to make a https request in NO_SYS=0 (i.e. full FreeRTOS integration)
145149

146150
### Pico W Bluetooth
147151

pico_w/wifi/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ else()
1616
add_subdirectory(tcp_server)
1717
add_subdirectory(freertos)
1818
add_subdirectory(udp_beacon)
19+
add_subdirectory(http_client)
1920

2021
if (NOT PICO_MBEDTLS_PATH)
2122
message("Skipping tls examples as PICO_MBEDTLS_PATH is not defined")

pico_w/wifi/freertos/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ else()
55

66
add_subdirectory(iperf)
77
add_subdirectory(ping)
8+
add_subdirectory(http_client)
89
endif()
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
add_executable(picow_freertos_http_client_nosys
2+
picow_freertos_http_client.c
3+
)
4+
target_compile_definitions(picow_freertos_http_client_nosys PRIVATE
5+
WIFI_SSID=\"${WIFI_SSID}\"
6+
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
7+
ALTCP_MBEDTLS_AUTHMODE=MBEDTLS_SSL_VERIFY_REQUIRED
8+
)
9+
target_include_directories(picow_freertos_http_client_nosys PRIVATE
10+
${CMAKE_CURRENT_LIST_DIR}
11+
${CMAKE_CURRENT_LIST_DIR}/.. # for our common FreeRTOSConfig
12+
${CMAKE_CURRENT_LIST_DIR}/../.. # for our common lwipopts
13+
)
14+
target_link_libraries(picow_freertos_http_client_nosys
15+
pico_cyw43_arch_lwip_threadsafe_background
16+
pico_stdlib
17+
pico_lwip_http_util
18+
FreeRTOS-Kernel-Heap4 # FreeRTOS kernel and dynamic heap
19+
)
20+
pico_add_extra_outputs(picow_freertos_http_client_nosys)
21+
22+
add_executable(picow_freertos_http_client_sys
23+
picow_freertos_http_client.c
24+
)
25+
target_compile_definitions(picow_freertos_http_client_sys PRIVATE
26+
WIFI_SSID=\"${WIFI_SSID}\"
27+
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
28+
NO_SYS=0 # don't want NO_SYS (generally this would be in your lwipopts.h)
29+
ALTCP_MBEDTLS_AUTHMODE=MBEDTLS_SSL_VERIFY_REQUIRED
30+
)
31+
target_include_directories(picow_freertos_http_client_sys PRIVATE
32+
${CMAKE_CURRENT_LIST_DIR}
33+
${CMAKE_CURRENT_LIST_DIR}/.. # for our common FreeRTOSConfig
34+
${CMAKE_CURRENT_LIST_DIR}/../.. # for our common lwipopts
35+
)
36+
target_link_libraries(picow_freertos_http_client_sys
37+
pico_cyw43_arch_lwip_sys_freertos
38+
pico_stdlib
39+
pico_lwip_http_util
40+
FreeRTOS-Kernel-Heap4 # FreeRTOS kernel and dynamic heap
41+
)
42+
pico_add_extra_outputs(picow_freertos_http_client_sys)
43+
44+
# Ignore warnings from lwip code
45+
set_source_files_properties(
46+
${PICO_LWIP_PATH}/src/apps/altcp_tls/altcp_tls_mbedtls.c
47+
PROPERTIES
48+
COMPILE_OPTIONS "-Wno-unused-result"
49+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifndef FREERTOS_CONFIG_H
2+
#define FREERTOS_CONFIG_H
3+
4+
// This example uses a common include to avoid repetition
5+
#include "FreeRTOSConfig_examples_common.h"
6+
7+
#endif
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef _LWIPOPTS_H
2+
#define _LWIPOPTS_H
3+
4+
// Generally you would define your own explicit list of lwIP options
5+
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html)
6+
//
7+
// This example uses a common include to avoid repetition
8+
#include "lwipopts_examples_common.h"
9+
10+
#if !NO_SYS
11+
#define TCPIP_THREAD_STACKSIZE 1024
12+
#define DEFAULT_THREAD_STACKSIZE 1024
13+
#define DEFAULT_RAW_RECVMBOX_SIZE 8
14+
#define TCPIP_MBOX_SIZE 8
15+
#define LWIP_TIMEVAL_PRIVATE 0
16+
17+
// not necessary, can be done either way
18+
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
19+
20+
// ping_thread sets socket receive timeout, so enable this feature
21+
#define LWIP_SO_RCVTIMEO 1
22+
#endif
23+
24+
#define LWIP_ALTCP 1
25+
26+
// If you don't want to use TLS (just a http request) you can avoid linking to mbedtls and remove the following
27+
#define LWIP_ALTCP_TLS 1
28+
#define LWIP_ALTCP_TLS_MBEDTLS 1
29+
30+
// Note bug in lwip with LWIP_ALTCP and LWIP_DEBUG
31+
// https://savannah.nongnu.org/bugs/index.php?62159
32+
//#define LWIP_DEBUG 1
33+
#undef LWIP_DEBUG
34+
#define ALTCP_MBEDTLS_DEBUG LWIP_DBG_ON
35+
36+
#endif
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* Workaround for some mbedtls source files using INT_MAX without including limits.h */
2+
#include <limits.h>
3+
4+
#define MBEDTLS_NO_PLATFORM_ENTROPY
5+
#define MBEDTLS_ENTROPY_HARDWARE_ALT
6+
7+
#define MBEDTLS_SSL_OUT_CONTENT_LEN 2048
8+
9+
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
10+
#define MBEDTLS_HAVE_TIME
11+
12+
#define MBEDTLS_CIPHER_MODE_CBC
13+
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
14+
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
15+
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
16+
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
17+
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
18+
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
19+
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
20+
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
21+
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
22+
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
23+
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
24+
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
25+
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
26+
#define MBEDTLS_PKCS1_V15
27+
#define MBEDTLS_SHA256_SMALLER
28+
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
29+
#define MBEDTLS_AES_C
30+
#define MBEDTLS_ASN1_PARSE_C
31+
#define MBEDTLS_BIGNUM_C
32+
#define MBEDTLS_CIPHER_C
33+
#define MBEDTLS_CTR_DRBG_C
34+
#define MBEDTLS_ENTROPY_C
35+
#define MBEDTLS_ERROR_C
36+
#define MBEDTLS_MD_C
37+
#define MBEDTLS_MD5_C
38+
#define MBEDTLS_OID_C
39+
#define MBEDTLS_PKCS5_C
40+
#define MBEDTLS_PK_C
41+
#define MBEDTLS_PK_PARSE_C
42+
#define MBEDTLS_PLATFORM_C
43+
#define MBEDTLS_RSA_C
44+
#define MBEDTLS_SHA1_C
45+
#define MBEDTLS_SHA224_C
46+
#define MBEDTLS_SHA256_C
47+
#define MBEDTLS_SHA512_C
48+
#define MBEDTLS_SSL_CLI_C
49+
#define MBEDTLS_SSL_SRV_C
50+
#define MBEDTLS_SSL_TLS_C
51+
#define MBEDTLS_X509_CRT_PARSE_C
52+
#define MBEDTLS_X509_USE_C
53+
#define MBEDTLS_AES_FEWER_TABLES
54+
55+
/* TLS 1.2 */
56+
#define MBEDTLS_SSL_PROTO_TLS1_2
57+
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
58+
#define MBEDTLS_GCM_C
59+
#define MBEDTLS_ECDH_C
60+
#define MBEDTLS_ECP_C
61+
#define MBEDTLS_ECDSA_C
62+
#define MBEDTLS_ASN1_WRITE_C
63+
64+
// The following is needed to parse a certificate
65+
#define MBEDTLS_PEM_PARSE_C
66+
#define MBEDTLS_BASE64_C
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/**
2+
* Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include "pico/cyw43_arch.h"
8+
#include "pico/stdlib.h"
9+
#include "pico/http_client_util.h"
10+
#include "lwip/altcp_tls.h"
11+
12+
#include "lwip/netif.h"
13+
14+
#include "FreeRTOS.h"
15+
#include "task.h"
16+
17+
#ifndef RUN_FREERTOS_ON_CORE
18+
#define RUN_FREERTOS_ON_CORE 0
19+
#endif
20+
21+
#define TEST_TASK_PRIORITY ( tskIDLE_PRIORITY + 2UL )
22+
#define BLINK_TASK_PRIORITY ( tskIDLE_PRIORITY + 4UL )
23+
24+
// Using this url as we know the root cert won't change for a long time
25+
#define HOST "fw-download-alias1.raspberrypi.com"
26+
#define URL_REQUEST "/net_install/boot.sig"
27+
28+
// This is the PUBLIC root certificate exported from a browser
29+
// Note that the newlines are needed
30+
#define TLS_ROOT_CERT_OK "-----BEGIN CERTIFICATE-----\n\
31+
MIIC+jCCAn+gAwIBAgICEAAwCgYIKoZIzj0EAwIwgbcxCzAJBgNVBAYTAkdCMRAw\n\
32+
DgYDVQQIDAdFbmdsYW5kMRIwEAYDVQQHDAlDYW1icmlkZ2UxHTAbBgNVBAoMFFJh\n\
33+
c3BiZXJyeSBQSSBMaW1pdGVkMRwwGgYDVQQLDBNSYXNwYmVycnkgUEkgRUNDIENB\n\
34+
MR0wGwYDVQQDDBRSYXNwYmVycnkgUEkgUm9vdCBDQTEmMCQGCSqGSIb3DQEJARYX\n\
35+
c3VwcG9ydEByYXNwYmVycnlwaS5jb20wIBcNMjExMjA5MTEzMjU1WhgPMjA3MTEx\n\
36+
MjcxMTMyNTVaMIGrMQswCQYDVQQGEwJHQjEQMA4GA1UECAwHRW5nbGFuZDEdMBsG\n\
37+
A1UECgwUUmFzcGJlcnJ5IFBJIExpbWl0ZWQxHDAaBgNVBAsME1Jhc3BiZXJyeSBQ\n\
38+
SSBFQ0MgQ0ExJTAjBgNVBAMMHFJhc3BiZXJyeSBQSSBJbnRlcm1lZGlhdGUgQ0Ex\n\
39+
JjAkBgkqhkiG9w0BCQEWF3N1cHBvcnRAcmFzcGJlcnJ5cGkuY29tMHYwEAYHKoZI\n\
40+
zj0CAQYFK4EEACIDYgAEcN9K6Cpv+od3w6yKOnec4EbyHCBzF+X2ldjorc0b2Pq0\n\
41+
N+ZvyFHkhFZSgk2qvemsVEWIoPz+K4JSCpgPstz1fEV6WzgjYKfYI71ghELl5TeC\n\
42+
byoPY+ee3VZwF1PTy0cco2YwZDAdBgNVHQ4EFgQUJ6YzIqFh4rhQEbmCnEbWmHEo\n\
43+
XAUwHwYDVR0jBBgwFoAUIIAVCSiDPXut23NK39LGIyAA7NAwEgYDVR0TAQH/BAgw\n\
44+
BgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwIDaQAwZgIxAJYM+wIM\n\
45+
PC3wSPqJ1byJKA6D+ZyjKR1aORbiDQVEpDNWRKiQ5QapLg8wbcED0MrRKQIxAKUT\n\
46+
v8TJkb/8jC/oBVTmczKlPMkciN+uiaZSXahgYKyYhvKTatCTZb+geSIhc0w/2w==\n\
47+
-----END CERTIFICATE-----\n"
48+
49+
void blink_task(__unused void *params) {
50+
bool on = false;
51+
printf("blink_task starts\n");
52+
while (true) {
53+
#if 0 && configNUM_CORES > 1
54+
static int last_core_id;
55+
if (portGET_CORE_ID() != last_core_id) {
56+
last_core_id = portGET_CORE_ID();
57+
printf("blinking now from core %d\n", last_core_id);
58+
}
59+
#endif
60+
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, on);
61+
on = !on;
62+
vTaskDelay(200);
63+
}
64+
vTaskDelete(NULL);
65+
}
66+
67+
void main_task(__unused void *params) {
68+
if (cyw43_arch_init()) {
69+
printf("failed to initialise\n");
70+
return;
71+
}
72+
TaskHandle_t blinkHandle = NULL;
73+
xTaskCreate(blink_task, "BlinkThread", configMINIMAL_STACK_SIZE, NULL, BLINK_TASK_PRIORITY, &blinkHandle);
74+
75+
cyw43_arch_enable_sta_mode();
76+
printf("Connecting to Wi-Fi...\n");
77+
if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
78+
printf("failed to connect.\n");
79+
exit(1);
80+
} else {
81+
printf("Connected.\n");
82+
}
83+
84+
static const uint8_t cert_ok[] = TLS_ROOT_CERT_OK;
85+
PICO_HTTP_REQUEST_T req = {0};
86+
req.hostname = HOST;
87+
req.url = URL_REQUEST;
88+
req.headers_fn = http_client_header_print_fn;
89+
req.recv_fn = http_client_receive_print_fn;
90+
req.tls_config = altcp_tls_create_config_client(cert_ok, sizeof(cert_ok));
91+
int pass = http_client_request_sync(cyw43_arch_async_context(), &req);
92+
altcp_tls_free_config(req.tls_config);
93+
94+
if (pass != 0) {
95+
panic("test failed");
96+
}
97+
98+
vTaskDelete(blinkHandle);
99+
cyw43_arch_deinit();
100+
panic("Test passed");
101+
}
102+
103+
void vLaunch( void) {
104+
TaskHandle_t task;
105+
xTaskCreate(main_task, "TestMainThread", 1024, NULL, TEST_TASK_PRIORITY, &task);
106+
107+
#if NO_SYS && configUSE_CORE_AFFINITY && configNUM_CORES > 1
108+
// we must bind the main task to one core (well at least while the init is called)
109+
// (note we only do this in NO_SYS mode, because cyw43_arch_freertos
110+
// takes care of it otherwise)
111+
vTaskCoreAffinitySet(task, 1);
112+
#endif
113+
114+
/* Start the tasks and timer running. */
115+
vTaskStartScheduler();
116+
}
117+
118+
int main( void )
119+
{
120+
stdio_init_all();
121+
122+
/* Configure the hardware ready to run the demo. */
123+
const char *rtos_name;
124+
#if ( portSUPPORT_SMP == 1 )
125+
rtos_name = "FreeRTOS SMP";
126+
#else
127+
rtos_name = "FreeRTOS";
128+
#endif
129+
130+
#if ( portSUPPORT_SMP == 1 ) && ( configNUM_CORES == 2 )
131+
printf("Starting %s on both cores:\n", rtos_name);
132+
vLaunch();
133+
#elif ( RUN_FREERTOS_ON_CORE == 1 )
134+
printf("Starting %s on core 1:\n", rtos_name);
135+
multicore_launch_core1(vLaunch);
136+
while (true);
137+
#else
138+
printf("Starting %s on core 0:\n", rtos_name);
139+
vLaunch();
140+
#endif
141+
return 0;
142+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
add_executable(picow_http_client
2+
picow_http_client.c
3+
)
4+
target_compile_definitions(picow_http_client PRIVATE
5+
WIFI_SSID=\"${WIFI_SSID}\"
6+
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
7+
)
8+
target_include_directories(picow_http_client PRIVATE
9+
${CMAKE_CURRENT_LIST_DIR}
10+
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts
11+
)
12+
target_link_libraries(picow_http_client
13+
pico_cyw43_arch_lwip_threadsafe_background
14+
pico_lwip_http_util
15+
pico_stdlib
16+
)
17+
pico_add_extra_outputs(picow_http_client)
18+
19+
add_executable(picow_http_client_verify
20+
picow_http_verify.c
21+
)
22+
target_compile_definitions(picow_http_client_verify PRIVATE
23+
WIFI_SSID=\"${WIFI_SSID}\"
24+
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
25+
# By default verification is optional (MBEDTLS_SSL_VERIFY_OPTIONAL)
26+
# Make it required for this test
27+
ALTCP_MBEDTLS_AUTHMODE=MBEDTLS_SSL_VERIFY_REQUIRED
28+
)
29+
target_include_directories(picow_http_client_verify PRIVATE
30+
${CMAKE_CURRENT_LIST_DIR}
31+
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts
32+
)
33+
target_link_libraries(picow_http_client_verify
34+
pico_cyw43_arch_lwip_threadsafe_background
35+
pico_lwip_http_util
36+
pico_stdlib
37+
)
38+
pico_add_extra_outputs(picow_http_client_verify)
39+
40+
# Ignore warnings from lwip code
41+
set_source_files_properties(
42+
${PICO_LWIP_PATH}/src/apps/altcp_tls/altcp_tls_mbedtls.c
43+
PROPERTIES
44+
COMPILE_OPTIONS "-Wno-unused-result"
45+
)

0 commit comments

Comments
 (0)