Skip to content

AdrianCX/pico_https_example

Repository files navigation

Simple Websocket/HTTPS/TLS server on rp2040/rp2350 (raspberry pi pico 1 and 2).

Goal here is to have a simple build environment and libraries to create your own TLS server. A simple 'hello world' is provided as example that can handle simple HTTPS requests and WebSocket clients. That can also receive UF2s over https/websockets for OTA upgrades

Establishing outbound TCP/TLS connections can be done via Session class directly, see https://github.com/AdrianCX/pico_https_example/blob/main/telegram_tone_detector/telegram_notification.cpp

A few sample projects are provided:

  1. Simple hello world to copy/paste and adjust: https://github.com/AdrianCX/pico_https_example/tree/main/hello_world
  2. Microphone streamed over https/websockets: https://github.com/AdrianCX/pico_https_example/tree/main/audio_stream
  3. Camera streamed over https/websockets: https://github.com/AdrianCX/pico_https_example/tree/main/arducam_test
  4. Simple RC Car over https/websockets that reuses camera code: https://github.com/AdrianCX/pico_https_example/tree/main/rcbot
  5. detect washing machine jingle and notify over telegram: https://github.com/AdrianCX/pico_https_example/tree/main/telegram_tone_detector/

How to compile:

  1. Create certificates or insert your own.
cd hello_world/config/certificate

Either RSA or EC

./create_cert_rsa.sh
./create_cert_ec.sh

This generates a self signed certificate in key.h/cert.h. Alternative is to create a 'certificate' folder with same file format anywhere else in include path.

  1. Configure wifi in example (otherwise it won't connect):
hello_world/config/wifi.h
  1. Fetch submodules
git submodule update --init --recursive
  1. Build

For raspberry pi pico 1 w (rp2040)

./build_via_docker.sh pico_w

For raspberry pi pico 2 w (rp2350)

./build_via_docker.sh pico2_w

For pimoroni pico 2 w

./build_via_docker.sh pimoroni_pico_plus2_w_rp2350

Result is: build/pico_w/docker/hello_world/hello_world_https.uf2 or build/pico2_w/docker/hello_world/hello_world_https.uf2

Logs

There are two different types of logs.

  1. Application logs

These are sent over UDP. Configure a host in "config/logging_config.h"

#define LOGGING_SERVER "192.168.100.150"
#define LOGGING_SERVER_PORT 21000

and on the remote remote host run the provided log receiver:

python3 util/log_receiver.py

OR:

netcat -ukl 21000

If it crashes you will see something like this

 50    11912 192.168.100.109 trace RequestHandler::onWebSocketData: this=20007920, len=20, data=[hello from websocket]
 51    11912 192.168.100.109 trace 
 52    11912 192.168.100.109 trace Firmware name: build/pico_w/docker/hello_world/hello_world_https, hardware version: pico_w, software version: 1.0
 53    11912 192.168.100.109 trace Fault on interrupt or bare metal(no OS) environment
 54    11913 192.168.100.109 trace =================== Registers information ====================
 55    11913 192.168.100.109 trace   R0 : 00000001  R1 : 20007a18  R2 : 00000380  R3 : 10000619
 56    11913 192.168.100.109 trace   R12: 0000e080  LR : 1002f647  PC : 10000618  PSR: 21000000
 57    11913 192.168.100.109 trace ==============================================================
 58    11913 192.168.100.109 trace Print call stack: addr2line -e build/pico_w/docker/hello_world/hello_world_https.elf -afpiC 10000618 1002f646 1002c396 1002bd14 1002c822 10003b26 10006192 1000a6fc 1000abbe 1000d59c 1000c2f0 1000d6b0 1000e266 100008aa 1000e4e2 1000ae3c 10000404 1002e524 1002e07c 10027f2c 1002d354 10000226 
 59    11914 192.168.100.109 trace force_restart: waiting for 5 seconds
 60    12914 192.168.100.109 trace force_restart: waiting for 4 seconds
 61    13914 192.168.100.109 trace force_restart: waiting for 3 seconds
 62    14914 192.168.100.109 trace force_restart: waiting for 2 seconds
 63    15914 192.168.100.109 trace force_restart: waiting for 1 seconds

If it hangs or crashes, it will result in a restart. Call stack will be reported on next boots, similar to below:

488   876294 192.168.100.109 trace meminfo[arena=63592, hblkhd=0, uordblks=58568, usmblks=0, fordblks=5024, fsmblks=0, keepcost=752], numSessions=2, lwip[avail=0, used=3128, max=7756, err=0, illegal=0] tcp[xmit=347, recv=683, fw=0, drop=0, chkerr=0, lenerr=0, memerr=0, rterr=0, proterr=0, opterr=0, err=0, cachehit=678] udp[xmit=491, recv=339, fw=0, drop=0, chkerr=0, lenerr=0, memerr=0, rterr=0, proterr=0, opterr=0, err=0, cachehit=2]
489   876294 192.168.100.109 trace report_saved_crash: watchdog info: 1/0, last_command: 0xdeadbeef, cur_depth: 29
490   876295 192.168.100.109 trace Print call stack: addr2line -e build/pico_w/docker/hello_world/hello_world_https.elf -afpiC 1000ebba 1000eae8 1000c4e2 1000c9a0 1000e15c 1000dad8 1000b32a 100099e8 10009ef6 1000af00 1000af8a 10002e66 10007978 100068ae 1000adf4 1000b2b6 1000dc94 1000c9e8 1000dda8 1000e95e 100008ea 1000ebda 1000b534 10000406 1002f188 1002ece0 100286c8 1002dfb8 10000226 

You can use addr2line for more info:

$ addr2line -e build/pico_w/docker/hello_world/hello_world_https.elf -afpiC 10000618 1002f646 1002c396 1002bd14 1002c822 10003b26 10006192 1000a6fc 1000abbe 1000d59c 1000c2f0 1000d6b0 1000e266 100008aa 1000e4e2 1000ae3c 10000404 1002e524 1002e07c 10027f2c 1002d354 10000226
0x10000618: RequestHandler::onWebSocketData(unsigned char*, unsigned int) at /source/hello_world/request_handler.cpp:81
0x1002f646: _free_r at /build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v6-m/nofp/newlib/libc/stdlib/../../../../../../../../newlib/libc/stdlib/mallocr.c:2730
0x1002c396: WebSocketHandler::decodeData(unsigned char*, unsigned int, WebSocketInterface*) at /source/pico_https/pico_http/websocket_handler.cpp:112
0x1002bd14: HTTPSession::on_recv(unsigned char*, unsigned int) at /source/pico_https/pico_http/http_session.cpp:81
0x1002c822: Session::http_recv(void*, altcp_pcb*, pbuf*, signed char) at /source/pico_https/pico_tls/session.cpp:204
0x10003b26: altcp_tcp_recv at /source/pico_https/pico-sdk/lib/lwip/src/core/altcp_tcp.c:110
0x10006192: tcp_input at /source/pico_https/pico-sdk/lib/lwip/src/core/tcp_in.c:502 (discriminator 4)
0x1000a6fc: ip4_input at /source/pico_https/pico-sdk/lib/lwip/src/core/ipv4/ip4.c:744
0x1000abbe: ethernet_input at /source/pico_https/pico-sdk/lib/lwip/src/netif/ethernet.c:188
0x1000d59c: cyw43_cb_process_ethernet at /source/pico_https/pico-sdk/lib/cyw43-driver/src/cyw43_lwip.c:278
0x1000c2f0: cyw43_ll_process_packets at /source/pico_https/pico-sdk/lib/cyw43-driver/src/cyw43_ll.c:1157
0x1000d6b0: cyw43_poll_func at /source/pico_https/pico-sdk/lib/cyw43-driver/src/cyw43_ctrl.c:233
 (inlined by) cyw43_poll_func at /source/pico_https/pico-sdk/lib/cyw43-driver/src/cyw43_ctrl.c:211
0x1000e266: cyw43_do_poll at /source/pico_https/pico-sdk/src/rp2_common/pico_cyw43_driver/cyw43_driver.c:92
0x100008aa: async_context_base_execute_once at /source/pico_https/pico-sdk/src/rp2_common/pico_async_context/async_context_base.c:98 (discriminator 2)
0x1000e4e2: async_context_poll_poll at /source/pico_https/pico-sdk/src/rp2_common/pico_async_context/async_context_poll.c:36
0x1000ae3c: cyw43_arch_poll at /source/pico_https/pico-sdk/src/rp2_common/pico_cyw43_arch/cyw43_arch.c:184
0x10000404: main at /source/hello_world/main.cpp:90
0x1002e524: malloc_extend_top at /build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v6-m/nofp/newlib/libc/stdlib/../../../../../../../../newlib/libc/stdlib/mallocr.c:2206
 (inlined by) _malloc_r at /build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v6-m/nofp/newlib/libc/stdlib/../../../../../../../../newlib/libc/stdlib/mallocr.c:2580
0x1002e07c: malloc at /build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v6-m/nofp/newlib/libc/stdlib/../../../../../../../../newlib/libc/stdlib/malloc.c:165
0x10027f2c: check_alloc at /source/pico_https/pico-sdk/src/rp2_common/pico_malloc/malloc.c:62
 (inlined by) __wrap_malloc at /source/pico_https/pico-sdk/src/rp2_common/pico_malloc/malloc.c:79
0x1002d354: _GLOBAL__sub_I__ZN9__gnu_cxx9__freeresEv at /build/libstdc++-arm-none-eabi-gDiE7C/libstdc++-arm-none-eabi-17/build/thumb/v6-m/nofp/libstdc++/libsupc++/../../../../../../src/libstdc++-v3/libsupc++/eh_alloc.cc:123
 (inlined by) __static_initialization_and_destruction_0 at /build/libstdc++-arm-none-eabi-gDiE7C/libstdc++-arm-none-eabi-17/build/thumb/v6-m/nofp/libstdc++/libsupc++/../../../../../../src/libstdc++-v3/libsupc++/eh_alloc.cc:262
 (inlined by) _GLOBAL__sub_I__ZN9__gnu_cxx9__freeresEv at /build/libstdc++-arm-none-eabi-gDiE7C/libstdc++-arm-none-eabi-17/build/thumb/v6-m/nofp/libstdc++/libsupc++/../../../../../../src/libstdc++-v3/libsupc++/eh_alloc.cc:338
0x10000226: platform_entry at /source/pico_https/pico-sdk/src/rp2_common/pico_crt0/crt0.S:456
  1. LWIP/mbedtls logs

Go to: 'hello_world/config/lwipopts_common.h'

Select which include you want (or make your own file / edit existing ones)

// 1. Full TCP/mbedtls debug logs
// #include "lwipopts_fulltcpdebug.h"

// 2. No LWIP/mbedtls debug logs.
#include "lwipopts_debug_off.h"

And use a build that doesn't have NDEBUG defined.

If full TCP logs enabled then LWIP/mbedtls traces will be sent over UDP to configured host in "logging_config.h".

You will see items like:

326    16416 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:2053 ssl->f_send() returned 1421 (-0xfffffa73)
327    16416 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:2080 <= flush output
328    16416 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:2755 <= write record
329    16417 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:5525 <= adrian ret ret: 0, max_len: 4096, len: 1392, out_left: 0
330    16417 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:5601 <= adrian 1392
331    16417 192.168.100.109 trace adrian: mbedtls_ssl_write return 1392, len: 1392
333    16418 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:3791 => read record
334    16418 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:1834 => fetch input
335    16418 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:1974 in_left: 0, nb_want: 5
336    16418 192.168.100.109 trace /source/pico_https/pico-sdk/lib/mbedtls/library/ssl_msg.c:1994 in_left: 0, nb_want: 5
337    16419 192.168.100.109 trace tcp_output: snd_wnd 62898, cwnd 1670, wnd 1670, effwnd 1460, seq 7853, ack 7853
338    16419 192.168.100.109 trace tcp_output: snd_wnd 62898, cwnd 1670, wnd 1670, effwnd 1460, seq 7853, ack 7853, i 0
339    16419 192.168.100.109 trace tcp_output_segment: rtseq 7853
340    16419 192.168.100.109 trace tcp_output_segment: 7853:9313
341    16420 192.168.100.109 trace State: ESTABLISHED
342    16445 192.168.100.109 trace tcp_slowtmr: processing active pcb
343    16445 192.168.100.109 trace tcp_slowtmr: polling application
344    16445 192.168.100.109 trace tcp_output: snd_wnd 62898, cwnd 1670, wnd 1670, effwnd 2920, seq 9313, ack 7853

About

Example for pico_https

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published