From 5472d5c52ff5a207bfb90d1d5d0e6d84678ad987 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 29 May 2018 11:25:24 +0200 Subject: [PATCH 01/60] asio: initial idf port of asio library without ssl * Original commit: espressif/esp-idf@1ef13c524c484e9fb62e6c0b11482c30c5383728 --- components/asio/asio | 1 + components/asio/component.mk | 6 + .../asio/port/include/esp_asio_config.h | 45 ++++ components/asio/port/include/esp_exception.h | 39 ++++ docs/en/api-reference/protocols/asio.rst | 32 +++ docs/zh_CN/api-reference/protocols/asio.rst | 1 + examples/protocols/asio/chat_client/Makefile | 7 + examples/protocols/asio/chat_client/README.md | 19 ++ .../asio/chat_client/asio_chat_client_test.py | 98 ++++++++ .../asio/chat_client/components/component.mk | 10 + .../asio/chat_client/components/wifi_asio.cpp | 136 +++++++++++ .../asio/chat_client/main/Kconfig.projbuild | 27 +++ .../asio/chat_client/main/chat_client.cpp | 165 ++++++++++++++ .../asio/chat_client/main/chat_message.hpp | 91 ++++++++ .../asio/chat_client/main/component.mk | 8 + .../asio/chat_client/sdkconfig.defaults | 1 + examples/protocols/asio/chat_server/Makefile | 7 + examples/protocols/asio/chat_server/README.md | 22 ++ .../asio/chat_server/asio_chat_server_test.py | 56 +++++ .../asio/chat_server/components/component.mk | 10 + .../asio/chat_server/components/wifi_asio.cpp | 136 +++++++++++ .../asio/chat_server/main/Kconfig.projbuild | 21 ++ .../asio/chat_server/main/chat_message.hpp | 91 ++++++++ .../asio/chat_server/main/chat_server.cpp | 214 ++++++++++++++++++ .../asio/chat_server/main/component.mk | 8 + .../asio/chat_server/sdkconfig.defaults | 1 + .../protocols/asio/tcp_echo_server/Makefile | 7 + .../protocols/asio/tcp_echo_server/README.md | 18 ++ .../tcp_echo_server/asio_tcp_server_test.py | 59 +++++ .../tcp_echo_server/components/component.mk | 10 + .../tcp_echo_server/components/wifi_asio.cpp | 136 +++++++++++ .../tcp_echo_server/main/Kconfig.projbuild | 21 ++ .../asio/tcp_echo_server/main/component.mk | 9 + .../asio/tcp_echo_server/main/echo_server.cpp | 91 ++++++++ .../asio/tcp_echo_server/sdkconfig.defaults | 1 + .../protocols/asio/udp_echo_server/Makefile | 7 + .../protocols/asio/udp_echo_server/README.md | 18 ++ .../udp_echo_server/asio_udp_server_test.py | 58 +++++ .../udp_echo_server/components/component.mk | 10 + .../udp_echo_server/components/wifi_asio.cpp | 136 +++++++++++ .../udp_echo_server/main/Kconfig.projbuild | 21 ++ .../asio/udp_echo_server/main/component.mk | 8 + .../udp_echo_server/main/udp_echo_server.cpp | 69 ++++++ .../asio/udp_echo_server/sdkconfig.defaults | 1 + .../protocols/asio/wifi_init/wifi_asio.cpp | 136 +++++++++++ 45 files changed, 2068 insertions(+) create mode 160000 components/asio/asio create mode 100644 components/asio/component.mk create mode 100644 components/asio/port/include/esp_asio_config.h create mode 100644 components/asio/port/include/esp_exception.h create mode 100644 docs/en/api-reference/protocols/asio.rst create mode 100644 docs/zh_CN/api-reference/protocols/asio.rst create mode 100644 examples/protocols/asio/chat_client/Makefile create mode 100644 examples/protocols/asio/chat_client/README.md create mode 100644 examples/protocols/asio/chat_client/asio_chat_client_test.py create mode 100644 examples/protocols/asio/chat_client/components/component.mk create mode 100644 examples/protocols/asio/chat_client/components/wifi_asio.cpp create mode 100644 examples/protocols/asio/chat_client/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/chat_client/main/chat_client.cpp create mode 100644 examples/protocols/asio/chat_client/main/chat_message.hpp create mode 100644 examples/protocols/asio/chat_client/main/component.mk create mode 100644 examples/protocols/asio/chat_client/sdkconfig.defaults create mode 100644 examples/protocols/asio/chat_server/Makefile create mode 100644 examples/protocols/asio/chat_server/README.md create mode 100644 examples/protocols/asio/chat_server/asio_chat_server_test.py create mode 100644 examples/protocols/asio/chat_server/components/component.mk create mode 100644 examples/protocols/asio/chat_server/components/wifi_asio.cpp create mode 100644 examples/protocols/asio/chat_server/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/chat_server/main/chat_message.hpp create mode 100644 examples/protocols/asio/chat_server/main/chat_server.cpp create mode 100644 examples/protocols/asio/chat_server/main/component.mk create mode 100644 examples/protocols/asio/chat_server/sdkconfig.defaults create mode 100644 examples/protocols/asio/tcp_echo_server/Makefile create mode 100644 examples/protocols/asio/tcp_echo_server/README.md create mode 100644 examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py create mode 100644 examples/protocols/asio/tcp_echo_server/components/component.mk create mode 100644 examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp create mode 100644 examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/tcp_echo_server/main/component.mk create mode 100644 examples/protocols/asio/tcp_echo_server/main/echo_server.cpp create mode 100644 examples/protocols/asio/tcp_echo_server/sdkconfig.defaults create mode 100644 examples/protocols/asio/udp_echo_server/Makefile create mode 100644 examples/protocols/asio/udp_echo_server/README.md create mode 100644 examples/protocols/asio/udp_echo_server/asio_udp_server_test.py create mode 100644 examples/protocols/asio/udp_echo_server/components/component.mk create mode 100644 examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp create mode 100644 examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/udp_echo_server/main/component.mk create mode 100644 examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp create mode 100644 examples/protocols/asio/udp_echo_server/sdkconfig.defaults create mode 100644 examples/protocols/asio/wifi_init/wifi_asio.cpp diff --git a/components/asio/asio b/components/asio/asio new file mode 160000 index 000000000..55efc179b --- /dev/null +++ b/components/asio/asio @@ -0,0 +1 @@ +Subproject commit 55efc179b76139c8f9b44bf22a4aba4803f7a7bd diff --git a/components/asio/component.mk b/components/asio/component.mk new file mode 100644 index 000000000..e024df3f3 --- /dev/null +++ b/components/asio/component.mk @@ -0,0 +1,6 @@ +COMPONENT_ADD_INCLUDEDIRS := asio/asio/include port/include +COMPONENT_PRIV_INCLUDEDIRS := private_include +COMPONENT_SRCDIRS := asio/asio/src +COMPONENT_OBJEXCLUDE := asio/asio/src/asio_ssl.o + +COMPONENT_SUBMODULES += asio diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h new file mode 100644 index 000000000..accccad0d --- /dev/null +++ b/components/asio/port/include/esp_asio_config.h @@ -0,0 +1,45 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ESP_ASIO_CONFIG_H_ +#define _ESP_ASIO_CONFIG_H_ + +// +// Enabling exceptions only when they are enabled in menuconfig +// +# include +# ifndef CONFIG_CXX_EXCEPTIONS +# define ASIO_NO_EXCEPTIONS +# endif // CONFIG_CXX_EXCEPTIONS + +// +// LWIP compatifility inet and address macros/functions +// +# define LWIP_COMPAT_SOCKET_INET 1 +# define LWIP_COMPAT_SOCKET_ADDR 1 + +// +// Specific ASIO feature flags +// +# define ASIO_DISABLE_SERIAL_PORT +# define ASIO_SEPARATE_COMPILATION +# define ASIO_STANDALONE +# define ASIO_NO_TYPEID +# define ASIO_DISABLE_SIGNAL +# define ASIO_HAS_PTHREADS +# define ASIO_DISABLE_EPOLL +# define ASIO_DISABLE_EVENTFD +# define ASIO_DISABLE_SIGNAL +# define ASIO_DISABLE_SIGACTION + +#endif // _ESP_ASIO_CONFIG_H_ diff --git a/components/asio/port/include/esp_exception.h b/components/asio/port/include/esp_exception.h new file mode 100644 index 000000000..3c5c04375 --- /dev/null +++ b/components/asio/port/include/esp_exception.h @@ -0,0 +1,39 @@ + +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _ESP_EXCEPTION_H_ +#define _ESP_EXCEPTION_H_ + +// +// This exception stub is enabled only if exceptions are disabled in menuconfig +// +#if !defined(CONFIG_CXX_EXCEPTIONS) && defined (ASIO_NO_EXCEPTIONS) + +#include "esp_log.h" + +// +// asio exception stub +// +namespace asio { +namespace detail { +template +void throw_exception(const Exception& e) +{ + ESP_LOGE("esp32_asio_exception", "Caught exception: %s!", e.what()); + abort(); +} +}} +#endif // CONFIG_CXX_EXCEPTIONS==1 && defined (ASIO_NO_EXCEPTIONS) + +#endif // _ESP_EXCEPTION_H_ diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst new file mode 100644 index 000000000..635ef053f --- /dev/null +++ b/docs/en/api-reference/protocols/asio.rst @@ -0,0 +1,32 @@ +ASIO port +========= + +Overview +-------- +Asio is a cross-platform C++ library, see https://think-async.com. It provides a consistent asynchronous model using a modern C++ approach. + + +ASIO documentation +^^^^^^^^^^^^^^^^^^ +Please refer to the original asio documentation at https://think-async.com/Asio/Documentation. +Asio also comes with a number of examples which could be find under Documentation/Examples on that web site. + +Supported features +^^^^^^^^^^^^^^^^^^ +ESP platform port currently supports only network asynchronous socket operations; does not support serial port and ssl. +Internal asio settings for ESP include +- EXCEPTIONS: Supported, choice in menuconfig +- SIGNAL, SIGACTION: Not supported +- EPOLL, EVENTFD: Not supported +- TYPEID: Disabled by default, but supported in toolchain and asio (provided stdlib recompiled with -frtti) + +Application Example +------------------- +ESP examples are based on standard asio examples `examples/protocols/asio`: +- udp_echo_server +- tcp_echo_server +- chat_client +- chat_server +Please refer to the specific example README.md for details + + diff --git a/docs/zh_CN/api-reference/protocols/asio.rst b/docs/zh_CN/api-reference/protocols/asio.rst new file mode 100644 index 000000000..d1afa231e --- /dev/null +++ b/docs/zh_CN/api-reference/protocols/asio.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/protocols/asio.rst \ No newline at end of file diff --git a/examples/protocols/asio/chat_client/Makefile b/examples/protocols/asio/chat_client/Makefile new file mode 100644 index 000000000..8f651a3eb --- /dev/null +++ b/examples/protocols/asio/chat_client/Makefile @@ -0,0 +1,7 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := asio_chatclient + +include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_client/README.md b/examples/protocols/asio/chat_client/README.md new file mode 100644 index 000000000..0ab16f578 --- /dev/null +++ b/examples/protocols/asio/chat_client/README.md @@ -0,0 +1,19 @@ +# ASIO chat server example + +Simple asio chat client using WiFi STA + +## Example workflow + +- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` +- Once connected and acquired IP address ASIO chat client connects to a corresponding server whose port number and ip are defined through `make menuconfig` +- Chat client receives all messages from other chat clients, also it sends message received from stdin using `make monitor` + +## Running the example + +- Run `make menuconfig` to configure the access point's SSID and Password and server ip address and port number +- Start chat server either on host machine or as another ESP device running chat_server example +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal +- Wait for WiFi to connect to your access point +- Receive and send messages to/from other clients on stdin/stdout via serial terminal. + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py new file mode 100644 index 000000000..a1cce97c5 --- /dev/null +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -0,0 +1,98 @@ +import re +import os +import sys +from socket import * +from threading import Thread +import time + +# this is a test case write with tiny-test-fw. +# to run test cases outside tiny-test-fw, +# we need to set environment variable `TEST_FW_PATH`, +# then get and insert `TEST_FW_PATH` to sys path before import FW module +test_fw_path = os.getenv("TEST_FW_PATH") +if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + +import TinyFW +import IDF + +global g_client_response; +global g_msg_to_client; + +g_client_response = "" +g_msg_to_client = " 3XYZ" + +def get_my_ip(): + s1 = socket(AF_INET, SOCK_DGRAM) + s1.connect(("8.8.8.8", 80)) + my_ip = s1.getsockname()[0] + s1.close() + return my_ip + +def chat_server_sketch(my_ip): + global g_client_response + print("Starting the server on {}".format(my_ip)) + port=2222 + s=socket(AF_INET, SOCK_STREAM) + s.bind((my_ip, port)) + s.listen(1) + q,addr=s.accept() + print("connection accepted") + q.send(g_msg_to_client) + data = q.recv(1024) + # check if received initial empty message + if (len(data)>4): + g_client_response = data + else: + g_client_response = q.recv(1024) + print("received from client {}".format(g_client_response)) + s.close() + print("server closed") + +@IDF.idf_example_test(env_tag="Example_WIFI") +def test_examples_protocol_asio_chat_client(env, extra_data): + """ + steps: | + 1. Test to start simple tcp server + 2. `dut1` joins AP + 3. Test injects server IP to `dut1`via stdin + 4. Test evaluates `dut1` receives a message server placed + 5. Test injects a message to `dut1` to be sent as chat_client message + 6. Test evaluates received test message in host server + """ + global g_client_response + global g_msg_to_client + test_msg="ABC" + dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client") + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, "asio_chatclient.bin") + bin_size = os.path.getsize(binary_file) + IDF.log_performance("asio_chatclient_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_chatclient_size", bin_size//1024) + # 1. start a tcp server on the host + host_ip = get_my_ip() + thread1 = Thread(target = chat_server_sketch, args = (host_ip,)) + thread1.start() + # 2. start the dut test and wait till client gets IP address + dut1.start_app() + data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + # 3. send host's IP to the client i.e. the `dut1` + dut1.write(host_ip) + # 4. client `dut1` should receive a message + dut1.expect(g_msg_to_client[4:]) # Strip out the front 4 bytes of message len (see chat_message protocol) + # 5. write test message from `dut1` chat_client to the server + dut1.write(test_msg) + while g_client_response == "": + time.sleep(1) + print(g_client_response) + # 6. evaluate host_server received this message + if (g_client_response[4:] == test_msg): + print("PASS: Received correct message") + pass + else: + print("Failure!") + raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(g_client_response, test_msg)) + thread1.join() + +if __name__ == '__main__': + test_examples_protocol_asio_chat_client() diff --git a/examples/protocols/asio/chat_client/components/component.mk b/examples/protocols/asio/chat_client/components/component.mk new file mode 100644 index 000000000..b23b0cb71 --- /dev/null +++ b/examples/protocols/asio/chat_client/components/component.mk @@ -0,0 +1,10 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/chat_client/components/wifi_asio.cpp b/examples/protocols/asio/chat_client/components/wifi_asio.cpp new file mode 100644 index 000000000..b90ce26ae --- /dev/null +++ b/examples/protocols/asio/chat_client/components/wifi_asio.cpp @@ -0,0 +1,136 @@ +/* Common WiFi Init as STA for ASIO examples + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "driver/uart.h" +#include "esp_console.h" +#include "esp_vfs_dev.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +#include + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int WIFI_CONNECTED_BIT = BIT0; + +static const char *TAG = "asio example wifi init"; + +/** + * Definition of ASIO main method, which is called after network initialized + */ +void asio_main(); + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", + MAC2STR(event->event_info.sta_connected.mac), + event->event_info.sta_connected.aid); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", + MAC2STR(event->event_info.sta_disconnected.mac), + event->event_info.sta_disconnected.aid); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +void wifi_init_sta() +{ + wifi_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config; + // zero out the config struct to ensure defaults are setup + memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); + // only copy ssid&password from example config + strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); + strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +extern "C" void app_main() +{ + //Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); + wifi_init_sta(); + + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + // wait till we receive IP, so asio realated code can be started + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); + + // network is ready, let's proceed with ASIO example + asio_main(); +} diff --git a/examples/protocols/asio/chat_client/main/Kconfig.projbuild b/examples/protocols/asio/chat_client/main/Kconfig.projbuild new file mode 100644 index 000000000..32e5f3fcb --- /dev/null +++ b/examples/protocols/asio/chat_client/main/Kconfig.projbuild @@ -0,0 +1,27 @@ +menu "Example Configuration" + +config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +config EXAMPLE_PORT + string "asio example port number" + default "2222" + help + Port number used by ASIO example + +config EXAMPLE_SERVER_IP + string "asio example server ip for this client to connect to (leave defalut=FROM_STDIN to enter the server address via serial terminal)" + default "FROM_STDIN" + help + Please set the host name or ip address of corespondant server running + +endmenu diff --git a/examples/protocols/asio/chat_client/main/chat_client.cpp b/examples/protocols/asio/chat_client/main/chat_client.cpp new file mode 100644 index 000000000..e18d8d4e3 --- /dev/null +++ b/examples/protocols/asio/chat_client/main/chat_client.cpp @@ -0,0 +1,165 @@ +// +// chat_client.cpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include "asio.hpp" +#include "chat_message.hpp" + +using asio::ip::tcp; + +typedef std::deque chat_message_queue; + +class chat_client +{ +public: + chat_client(asio::io_context& io_context, + const tcp::resolver::results_type& endpoints) + : io_context_(io_context), + socket_(io_context) + { + do_connect(endpoints); + } + + void write(const chat_message& msg) + { + asio::post(io_context_, + [this, msg]() + { + bool write_in_progress = !write_msgs_.empty(); + write_msgs_.push_back(msg); + if (!write_in_progress) + { + do_write(); + } + }); + } + + void close() + { + asio::post(io_context_, [this]() { socket_.close(); }); + } + +private: + void do_connect(const tcp::resolver::results_type& endpoints) + { + asio::async_connect(socket_, endpoints, + [this](std::error_code ec, tcp::endpoint) + { + if (!ec) + { + do_read_header(); + } + }); + } + + void do_read_header() + { + asio::async_read(socket_, + asio::buffer(read_msg_.data(), chat_message::header_length), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec && read_msg_.decode_header()) + { + do_read_body(); + } + else + { + socket_.close(); + } + }); + } + + void do_read_body() + { + asio::async_read(socket_, + asio::buffer(read_msg_.body(), read_msg_.body_length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + std::cout.write(read_msg_.body(), read_msg_.body_length()); + std::cout << "\n"; + do_read_header(); + } + else + { + socket_.close(); + } + }); + } + + void do_write() + { + asio::async_write(socket_, + asio::buffer(write_msgs_.front().data(), + write_msgs_.front().length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + write_msgs_.pop_front(); + if (!write_msgs_.empty()) + { + do_write(); + } + } + else + { + socket_.close(); + } + }); + } + +private: + asio::io_context& io_context_; + tcp::socket socket_; + chat_message read_msg_; + chat_message_queue write_msgs_; +}; + +void read_line(char * line, int max_chars); + + +void asio_main() +{ + std::string name(CONFIG_EXAMPLE_SERVER_IP); + std::string port(CONFIG_EXAMPLE_PORT); + char line[chat_message::max_body_length + 1] = { 0 }; + + if (name == "FROM_STDIN") { + std::cout << "Please enter ip address of chat server" << std::endl; + if (std::cin.getline(line, chat_message::max_body_length + 1)) { + name = line; + std::cout << "Chat server IP:" << name << std::endl; + } + } + + asio::io_context io_context; + tcp::resolver resolver(io_context); + auto endpoints = resolver.resolve(name, port); + + chat_client c(io_context, endpoints); + + std::thread t([&io_context](){ io_context.run(); }); + + while (std::cin.getline(line, chat_message::max_body_length + 1) && std::string(line) != "exit\n") { + chat_message msg; + msg.body_length(std::strlen(line)); + std::memcpy(msg.body(), line, msg.body_length()); + msg.encode_header(); + c.write(msg); + } + + c.close(); + t.join(); +} diff --git a/examples/protocols/asio/chat_client/main/chat_message.hpp b/examples/protocols/asio/chat_client/main/chat_message.hpp new file mode 100644 index 000000000..629105b05 --- /dev/null +++ b/examples/protocols/asio/chat_client/main/chat_message.hpp @@ -0,0 +1,91 @@ +// +// chat_message.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CHAT_MESSAGE_HPP +#define CHAT_MESSAGE_HPP + +#include +#include +#include + +class chat_message +{ +public: + enum { header_length = 4 }; + enum { max_body_length = 512 }; + + chat_message() + : body_length_(0) + { + } + + const char* data() const + { + return data_; + } + + char* data() + { + return data_; + } + + std::size_t length() const + { + return header_length + body_length_; + } + + const char* body() const + { + return data_ + header_length; + } + + char* body() + { + return data_ + header_length; + } + + std::size_t body_length() const + { + return body_length_; + } + + void body_length(std::size_t new_length) + { + body_length_ = new_length; + if (body_length_ > max_body_length) + body_length_ = max_body_length; + } + + bool decode_header() + { + char header[header_length + 1] = ""; + std::strncat(header, data_, header_length); + body_length_ = std::atoi(header); + if (body_length_ > max_body_length) + { + body_length_ = 0; + return false; + } + return true; + } + + void encode_header() + { + char header[header_length + 1] = ""; + std::sprintf(header, "%4d", static_cast(body_length_)); + std::memcpy(data_, header, header_length); + } + +private: + char data_[header_length + max_body_length]; + std::size_t body_length_; +}; + +#endif // CHAT_MESSAGE_HPP diff --git a/examples/protocols/asio/chat_client/main/component.mk b/examples/protocols/asio/chat_client/main/component.mk new file mode 100644 index 000000000..61f8990c3 --- /dev/null +++ b/examples/protocols/asio/chat_client/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/examples/protocols/asio/chat_client/sdkconfig.defaults b/examples/protocols/asio/chat_client/sdkconfig.defaults new file mode 100644 index 000000000..d99552e19 --- /dev/null +++ b/examples/protocols/asio/chat_client/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MAIN_TASK_STACK_SIZE=8192 diff --git a/examples/protocols/asio/chat_server/Makefile b/examples/protocols/asio/chat_server/Makefile new file mode 100644 index 000000000..c69f109c9 --- /dev/null +++ b/examples/protocols/asio/chat_server/Makefile @@ -0,0 +1,7 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := asio_chatserver + +include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_server/README.md b/examples/protocols/asio/chat_server/README.md new file mode 100644 index 000000000..591efd977 --- /dev/null +++ b/examples/protocols/asio/chat_server/README.md @@ -0,0 +1,22 @@ +# ASIO chat server example + +Simple asio chat server using WiFi STA + +## Example workflow + +- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` +- Once connected and acquired IP address, ASIO chat server is started on port number defined through `make menuconfig` +- Chat server echoes a message (received from any client) to all connected clients + +## Running the example + +- Run `make menuconfig` to configure the access point's SSID and Password and port number +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal +- Wait for WiFi to connect to your access point (note the IP address) +- Connect to the server using multiple clients, for example using any option below + - build and run asi chat client on your host machine + - run chat_client asio example on ESP platform + - since chat message consist of ascii size and message, it is possible to + netcat `nc IP PORT` and type for example ` 4ABC` to transmit 'ABC\n' + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py new file mode 100644 index 000000000..55746f1f9 --- /dev/null +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -0,0 +1,56 @@ +import re +import os +import sys +from socket import * + + +# this is a test case write with tiny-test-fw. +# to run test cases outside tiny-test-fw, +# we need to set environment variable `TEST_FW_PATH`, +# then get and insert `TEST_FW_PATH` to sys path before import FW module +test_fw_path = os.getenv("TEST_FW_PATH") +if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + +import TinyFW +import IDF + + + + +@IDF.idf_example_test(env_tag="Example_WIFI") +def test_examples_protocol_asio_chat_server(env, extra_data): + """ + steps: | + 1. join AP + 2. Start server + 3. Test connects to server and sends a test message + 4. Test evaluates received test message from server + """ + test_msg=" 4ABC\n" + dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server") + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, "asio_chatserver.bin") + bin_size = os.path.getsize(binary_file) + IDF.log_performance("asio_chatserver_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_chatserver_size", bin_size//1024) + # 1. start test + dut1.start_app() + # 2. get the server IP address + data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + # 3. create tcp client and connect to server + cli = socket(AF_INET,SOCK_STREAM) + cli.connect((data[0],80)) + cli.send(test_msg) + data = cli.recv(1024) + # 4. check the message received back from the server + if (data == test_msg): + print("PASS: Received correct message {}".format(data)) + pass + else: + print("Failure!") + raise ValueError('Wrong data received from asi tcp server: {} (expoected:{})'.format(data, test_msg)) + + +if __name__ == '__main__': + test_examples_protocol_asio_chat_server() diff --git a/examples/protocols/asio/chat_server/components/component.mk b/examples/protocols/asio/chat_server/components/component.mk new file mode 100644 index 000000000..b23b0cb71 --- /dev/null +++ b/examples/protocols/asio/chat_server/components/component.mk @@ -0,0 +1,10 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/chat_server/components/wifi_asio.cpp b/examples/protocols/asio/chat_server/components/wifi_asio.cpp new file mode 100644 index 000000000..b90ce26ae --- /dev/null +++ b/examples/protocols/asio/chat_server/components/wifi_asio.cpp @@ -0,0 +1,136 @@ +/* Common WiFi Init as STA for ASIO examples + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "driver/uart.h" +#include "esp_console.h" +#include "esp_vfs_dev.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +#include + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int WIFI_CONNECTED_BIT = BIT0; + +static const char *TAG = "asio example wifi init"; + +/** + * Definition of ASIO main method, which is called after network initialized + */ +void asio_main(); + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", + MAC2STR(event->event_info.sta_connected.mac), + event->event_info.sta_connected.aid); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", + MAC2STR(event->event_info.sta_disconnected.mac), + event->event_info.sta_disconnected.aid); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +void wifi_init_sta() +{ + wifi_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config; + // zero out the config struct to ensure defaults are setup + memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); + // only copy ssid&password from example config + strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); + strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +extern "C" void app_main() +{ + //Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); + wifi_init_sta(); + + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + // wait till we receive IP, so asio realated code can be started + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); + + // network is ready, let's proceed with ASIO example + asio_main(); +} diff --git a/examples/protocols/asio/chat_server/main/Kconfig.projbuild b/examples/protocols/asio/chat_server/main/Kconfig.projbuild new file mode 100644 index 000000000..c0d6fd9cd --- /dev/null +++ b/examples/protocols/asio/chat_server/main/Kconfig.projbuild @@ -0,0 +1,21 @@ +menu "Example Configuration" + +config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +config EXAMPLE_PORT + string "asio example port number" + default "80" + help + Port number used by ASIO example + +endmenu diff --git a/examples/protocols/asio/chat_server/main/chat_message.hpp b/examples/protocols/asio/chat_server/main/chat_message.hpp new file mode 100644 index 000000000..629105b05 --- /dev/null +++ b/examples/protocols/asio/chat_server/main/chat_message.hpp @@ -0,0 +1,91 @@ +// +// chat_message.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CHAT_MESSAGE_HPP +#define CHAT_MESSAGE_HPP + +#include +#include +#include + +class chat_message +{ +public: + enum { header_length = 4 }; + enum { max_body_length = 512 }; + + chat_message() + : body_length_(0) + { + } + + const char* data() const + { + return data_; + } + + char* data() + { + return data_; + } + + std::size_t length() const + { + return header_length + body_length_; + } + + const char* body() const + { + return data_ + header_length; + } + + char* body() + { + return data_ + header_length; + } + + std::size_t body_length() const + { + return body_length_; + } + + void body_length(std::size_t new_length) + { + body_length_ = new_length; + if (body_length_ > max_body_length) + body_length_ = max_body_length; + } + + bool decode_header() + { + char header[header_length + 1] = ""; + std::strncat(header, data_, header_length); + body_length_ = std::atoi(header); + if (body_length_ > max_body_length) + { + body_length_ = 0; + return false; + } + return true; + } + + void encode_header() + { + char header[header_length + 1] = ""; + std::sprintf(header, "%4d", static_cast(body_length_)); + std::memcpy(data_, header, header_length); + } + +private: + char data_[header_length + max_body_length]; + std::size_t body_length_; +}; + +#endif // CHAT_MESSAGE_HPP diff --git a/examples/protocols/asio/chat_server/main/chat_server.cpp b/examples/protocols/asio/chat_server/main/chat_server.cpp new file mode 100644 index 000000000..05740f479 --- /dev/null +++ b/examples/protocols/asio/chat_server/main/chat_server.cpp @@ -0,0 +1,214 @@ +// +// chat_server.cpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include +#include +#include +#include +#include "asio.hpp" +#include "chat_message.hpp" + +using asio::ip::tcp; + +//---------------------------------------------------------------------- + +typedef std::deque chat_message_queue; + +//---------------------------------------------------------------------- + +class chat_participant +{ +public: + virtual ~chat_participant() {} + virtual void deliver(const chat_message& msg) = 0; +}; + +typedef std::shared_ptr chat_participant_ptr; + +//---------------------------------------------------------------------- + +class chat_room +{ +public: + void join(chat_participant_ptr participant) + { + participants_.insert(participant); + for (auto msg: recent_msgs_) + participant->deliver(msg); + } + + void leave(chat_participant_ptr participant) + { + participants_.erase(participant); + } + + void deliver(const chat_message& msg) + { + recent_msgs_.push_back(msg); + while (recent_msgs_.size() > max_recent_msgs) + recent_msgs_.pop_front(); + + for (auto participant: participants_) + participant->deliver(msg); + } + +private: + std::set participants_; + enum { max_recent_msgs = 100 }; + chat_message_queue recent_msgs_; +}; + +//---------------------------------------------------------------------- + +class chat_session + : public chat_participant, + public std::enable_shared_from_this +{ +public: + chat_session(tcp::socket socket, chat_room& room) + : socket_(std::move(socket)), + room_(room) + { + } + + void start() + { + room_.join(shared_from_this()); + do_read_header(); + } + + void deliver(const chat_message& msg) + { + bool write_in_progress = !write_msgs_.empty(); + write_msgs_.push_back(msg); + if (!write_in_progress) + { + do_write(); + } + } + +private: + void do_read_header() + { + auto self(shared_from_this()); + asio::async_read(socket_, + asio::buffer(read_msg_.data(), chat_message::header_length), + [this, self](std::error_code ec, std::size_t /*length*/) + { + if (!ec && read_msg_.decode_header()) + { + do_read_body(); + } + else + { + room_.leave(shared_from_this()); + } + }); + } + + void do_read_body() + { + auto self(shared_from_this()); + asio::async_read(socket_, + asio::buffer(read_msg_.body(), read_msg_.body_length()), + [this, self](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + room_.deliver(read_msg_); + do_read_header(); + } + else + { + room_.leave(shared_from_this()); + } + }); + } + + void do_write() + { + auto self(shared_from_this()); + asio::async_write(socket_, + asio::buffer(write_msgs_.front().data(), + write_msgs_.front().length()), + [this, self](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + write_msgs_.pop_front(); + if (!write_msgs_.empty()) + { + do_write(); + } + } + else + { + room_.leave(shared_from_this()); + } + }); + } + + tcp::socket socket_; + chat_room& room_; + chat_message read_msg_; + chat_message_queue write_msgs_; +}; + +//---------------------------------------------------------------------- + +class chat_server +{ +public: + chat_server(asio::io_context& io_context, + const tcp::endpoint& endpoint) + : acceptor_(io_context, endpoint) + { + do_accept(); + } + +private: + void do_accept() + { + acceptor_.async_accept( + [this](std::error_code ec, tcp::socket socket) + { + if (!ec) + { + std::make_shared(std::move(socket), room_)->start(); + } + + do_accept(); + }); + } + + tcp::acceptor acceptor_; + chat_room room_; +}; + +//---------------------------------------------------------------------- + +int asio_main() +{ + asio::io_context io_context; + + std::list servers; + + { + tcp::endpoint endpoint(tcp::v4(), std::atoi(CONFIG_EXAMPLE_PORT)); + servers.emplace_back(io_context, endpoint); + } + + io_context.run(); + + return 0; +} diff --git a/examples/protocols/asio/chat_server/main/component.mk b/examples/protocols/asio/chat_server/main/component.mk new file mode 100644 index 000000000..61f8990c3 --- /dev/null +++ b/examples/protocols/asio/chat_server/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/examples/protocols/asio/chat_server/sdkconfig.defaults b/examples/protocols/asio/chat_server/sdkconfig.defaults new file mode 100644 index 000000000..d99552e19 --- /dev/null +++ b/examples/protocols/asio/chat_server/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MAIN_TASK_STACK_SIZE=8192 diff --git a/examples/protocols/asio/tcp_echo_server/Makefile b/examples/protocols/asio/tcp_echo_server/Makefile new file mode 100644 index 000000000..2a2839a54 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/Makefile @@ -0,0 +1,7 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := asio_tcp_echoserver + +include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/tcp_echo_server/README.md b/examples/protocols/asio/tcp_echo_server/README.md new file mode 100644 index 000000000..a32fd93ea --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/README.md @@ -0,0 +1,18 @@ +# ASIO tcp echo server example + +Simple asio echo server using WiFi STA + +## Example workflow + +- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` +- Once connected and acquired IP address, ASIO tcp server is started on port number defined through `make menuconfig` +- Server receives and echoes back messages transmitted from client + +## Running the example + +- Run `make menuconfig` to configure the access point's SSID and Password and port number +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal +- Wait for WiFi to connect to your access point (note the IP address) +- You can now send a tcp message and check it is repeated, for example using netcat `nc IP PORT` + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py new file mode 100644 index 000000000..1ab432e62 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -0,0 +1,59 @@ +import re +import os +import sys +from socket import * + + +# this is a test case write with tiny-test-fw. +# to run test cases outside tiny-test-fw, +# we need to set environment variable `TEST_FW_PATH`, +# then get and insert `TEST_FW_PATH` to sys path before import FW module +test_fw_path = os.getenv("TEST_FW_PATH") +if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + +import TinyFW +import IDF + + + + +@IDF.idf_example_test(env_tag="Example_WIFI") +def test_examples_protocol_asio_tcp_server(env, extra_data): + """ + steps: | + 1. join AP + 2. Start server + 3. Test connects to server and sends a test message + 4. Test evaluates received test message from server + 5. Test evaluates received test message on server stdout + """ + test_msg="echo message from client to server" + dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server") + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echoserver.bin") + bin_size = os.path.getsize(binary_file) + IDF.log_performance("asio_tcp_echoserver_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_tcp_echoserver_size", bin_size//1024) + # 1. start test + dut1.start_app() + # 2. get the server IP address + data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + # 3. create tcp client and connect to server + cli = socket(AF_INET,SOCK_STREAM) + cli.connect((data[0],80)) + cli.send(test_msg) + data = cli.recv(1024) + # 4. check the message received back from the server + if (data == test_msg): + print("PASS: Received correct message") + pass + else: + print("Failure!") + raise ValueError('Wrong data received from asi tcp server: {} (expoected:{})'.format(data, test_msg)) + # 5. check the client message appears also on server terminal + dut1.expect(test_msg) + + +if __name__ == '__main__': + test_examples_protocol_asio_tcp_server() diff --git a/examples/protocols/asio/tcp_echo_server/components/component.mk b/examples/protocols/asio/tcp_echo_server/components/component.mk new file mode 100644 index 000000000..b23b0cb71 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/components/component.mk @@ -0,0 +1,10 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp b/examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp new file mode 100644 index 000000000..b90ce26ae --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp @@ -0,0 +1,136 @@ +/* Common WiFi Init as STA for ASIO examples + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "driver/uart.h" +#include "esp_console.h" +#include "esp_vfs_dev.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +#include + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int WIFI_CONNECTED_BIT = BIT0; + +static const char *TAG = "asio example wifi init"; + +/** + * Definition of ASIO main method, which is called after network initialized + */ +void asio_main(); + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", + MAC2STR(event->event_info.sta_connected.mac), + event->event_info.sta_connected.aid); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", + MAC2STR(event->event_info.sta_disconnected.mac), + event->event_info.sta_disconnected.aid); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +void wifi_init_sta() +{ + wifi_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config; + // zero out the config struct to ensure defaults are setup + memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); + // only copy ssid&password from example config + strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); + strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +extern "C" void app_main() +{ + //Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); + wifi_init_sta(); + + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + // wait till we receive IP, so asio realated code can be started + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); + + // network is ready, let's proceed with ASIO example + asio_main(); +} diff --git a/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild b/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild new file mode 100644 index 000000000..c0d6fd9cd --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild @@ -0,0 +1,21 @@ +menu "Example Configuration" + +config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +config EXAMPLE_PORT + string "asio example port number" + default "80" + help + Port number used by ASIO example + +endmenu diff --git a/examples/protocols/asio/tcp_echo_server/main/component.mk b/examples/protocols/asio/tcp_echo_server/main/component.mk new file mode 100644 index 000000000..8c8d52abc --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/main/component.mk @@ -0,0 +1,9 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + diff --git a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp new file mode 100644 index 000000000..22f171f53 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp @@ -0,0 +1,91 @@ +#include "asio.hpp" +#include +#include + +using asio::ip::tcp; + +class session + : public std::enable_shared_from_this +{ +public: + session(tcp::socket socket) + : socket_(std::move(socket)) + { + } + + void start() + { + do_read(); + } + +private: + void do_read() + { + auto self(shared_from_this()); + socket_.async_read_some(asio::buffer(data_, max_length), + [this, self](std::error_code ec, std::size_t length) + { + if (!ec) + { + std::cout << data_ << std::endl; + do_write(length); + } + }); + } + + void do_write(std::size_t length) + { + auto self(shared_from_this()); + asio::async_write(socket_, asio::buffer(data_, length), + [this, self](std::error_code ec, std::size_t length) + { + if (!ec) + { + do_read(); + } + }); + } + + tcp::socket socket_; + enum { max_length = 1024 }; + char data_[max_length]; +}; + +class server +{ +public: + server(asio::io_context& io_context, short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) + { + do_accept(); + } + +private: + void do_accept() + { + acceptor_.async_accept( + [this](std::error_code ec, tcp::socket socket) + { + if (!ec) + { + std::make_shared(std::move(socket))->start(); + } + + do_accept(); + }); + } + + tcp::acceptor acceptor_; +}; + + +void asio_main() +{ + + asio::io_context io_context; + + server s(io_context, std::atoi(CONFIG_EXAMPLE_PORT)); + + io_context.run(); + +} \ No newline at end of file diff --git a/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults b/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults new file mode 100644 index 000000000..d99552e19 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MAIN_TASK_STACK_SIZE=8192 diff --git a/examples/protocols/asio/udp_echo_server/Makefile b/examples/protocols/asio/udp_echo_server/Makefile new file mode 100644 index 000000000..c659aeae0 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/Makefile @@ -0,0 +1,7 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := asio_udp_echoserver + +include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/udp_echo_server/README.md b/examples/protocols/asio/udp_echo_server/README.md new file mode 100644 index 000000000..6cf2c2ba3 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/README.md @@ -0,0 +1,18 @@ +# ASIO udp echo server example + +Simple asio echo server using WiFi STA + +## Example workflow + +- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` +- Once connected and acquired IP address, ASIO udp server is started on port number defined through `make menuconfig` +- Server receives and echoes back messages transmitted from client + +## Running the example + +- Run `make menuconfig` to configure the access point's SSID and Password and port number +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal +- Wait for WiFi to connect to your access point (note the IP address) +- You can now send a udp message and check it is repeated, for example using netcat `nc -u IP PORT` + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py new file mode 100644 index 000000000..490a8007a --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -0,0 +1,58 @@ +import re +import os +import sys +from socket import * + + +# this is a test case write with tiny-test-fw. +# to run test cases outside tiny-test-fw, +# we need to set environment variable `TEST_FW_PATH`, +# then get and insert `TEST_FW_PATH` to sys path before import FW module +test_fw_path = os.getenv("TEST_FW_PATH") +if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + +import TinyFW +import IDF + + + + +@IDF.idf_example_test(env_tag="Example_WIFI") +def test_examples_protocol_asio_udp_server(env, extra_data): + """ + steps: | + 1. join AP + 2. Start server + 3. Test connects to server and sends a test message + 4. Test evaluates received test message from server + 5. Test evaluates received test message on server stdout + """ + test_msg="echo message from client to server" + dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server") + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echoserver.bin") + bin_size = os.path.getsize(binary_file) + IDF.log_performance("asio_udp_echoserver_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_udp_echoserver_size", bin_size//1024) + # 1. start test + dut1.start_app() + # 2. get the server IP address + data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + # 3. create tcp client and connect to server + cli = socket(AF_INET, SOCK_DGRAM) + cli.connect((data[0], 80)) + cli.send(test_msg) + data = cli.recv(1024) + # 4. check the message received back from the server + if (data == test_msg): + print("PASS: Received correct message") + pass + else: + print("Failure!") + raise ValueError('Wrong data received from asi udp server: {} (expoected:{})'.format(data, test_msg)) + # 5. check the client message appears also on server terminal + dut1.expect(test_msg) + +if __name__ == '__main__': + test_examples_protocol_asio_udp_server() diff --git a/examples/protocols/asio/udp_echo_server/components/component.mk b/examples/protocols/asio/udp_echo_server/components/component.mk new file mode 100644 index 000000000..b23b0cb71 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/components/component.mk @@ -0,0 +1,10 @@ +# +# Component Makefile +# +# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, +# this will take the sources in the src/ directory, compile them and link them into +# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, +# please read the SDK documents if you need to do this. +# + +COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp b/examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp new file mode 100644 index 000000000..b90ce26ae --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp @@ -0,0 +1,136 @@ +/* Common WiFi Init as STA for ASIO examples + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "driver/uart.h" +#include "esp_console.h" +#include "esp_vfs_dev.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +#include + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int WIFI_CONNECTED_BIT = BIT0; + +static const char *TAG = "asio example wifi init"; + +/** + * Definition of ASIO main method, which is called after network initialized + */ +void asio_main(); + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", + MAC2STR(event->event_info.sta_connected.mac), + event->event_info.sta_connected.aid); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", + MAC2STR(event->event_info.sta_disconnected.mac), + event->event_info.sta_disconnected.aid); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +void wifi_init_sta() +{ + wifi_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config; + // zero out the config struct to ensure defaults are setup + memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); + // only copy ssid&password from example config + strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); + strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +extern "C" void app_main() +{ + //Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); + wifi_init_sta(); + + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + // wait till we receive IP, so asio realated code can be started + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); + + // network is ready, let's proceed with ASIO example + asio_main(); +} diff --git a/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild b/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild new file mode 100644 index 000000000..c0d6fd9cd --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild @@ -0,0 +1,21 @@ +menu "Example Configuration" + +config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + +config EXAMPLE_PORT + string "asio example port number" + default "80" + help + Port number used by ASIO example + +endmenu diff --git a/examples/protocols/asio/udp_echo_server/main/component.mk b/examples/protocols/asio/udp_echo_server/main/component.mk new file mode 100644 index 000000000..61f8990c3 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/main/component.mk @@ -0,0 +1,8 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# diff --git a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp new file mode 100644 index 000000000..5b6607d73 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp @@ -0,0 +1,69 @@ +// +// async_udp_echo_server.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +#include "asio.hpp" + +using asio::ip::udp; + +class server +{ +public: + server(asio::io_context& io_context, short port) + : socket_(io_context, udp::endpoint(udp::v4(), port)) + { + do_receive(); + } + + void do_receive() + { + socket_.async_receive_from( + asio::buffer(data_, max_length), sender_endpoint_, + [this](std::error_code ec, std::size_t bytes_recvd) + { + if (!ec && bytes_recvd > 0) + { + std::cout << data_ << std::endl; + do_send(bytes_recvd); + } + else + { + do_receive(); + } + }); + } + + void do_send(std::size_t length) + { + socket_.async_send_to( + asio::buffer(data_, length), sender_endpoint_, + [this](std::error_code /*ec*/, std::size_t bytes /*bytes_sent*/) + { + do_receive(); + }); + } + +private: + udp::socket socket_; + udp::endpoint sender_endpoint_; + enum { max_length = 1024 }; + char data_[max_length]; +}; + +void asio_main() +{ + asio::io_context io_context; + + server s(io_context, std::atoi(CONFIG_EXAMPLE_PORT)); + + io_context.run(); +} diff --git a/examples/protocols/asio/udp_echo_server/sdkconfig.defaults b/examples/protocols/asio/udp_echo_server/sdkconfig.defaults new file mode 100644 index 000000000..d99552e19 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_MAIN_TASK_STACK_SIZE=8192 diff --git a/examples/protocols/asio/wifi_init/wifi_asio.cpp b/examples/protocols/asio/wifi_init/wifi_asio.cpp new file mode 100644 index 000000000..b90ce26ae --- /dev/null +++ b/examples/protocols/asio/wifi_init/wifi_asio.cpp @@ -0,0 +1,136 @@ +/* Common WiFi Init as STA for ASIO examples + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "driver/uart.h" +#include "esp_console.h" +#include "esp_vfs_dev.h" + +#include "lwip/err.h" +#include "lwip/sys.h" + +#include + +/* The examples use simple WiFi configuration that you can set via + 'make menuconfig'. + + If you'd rather not, just change the below entries to strings with + the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" +*/ +#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int WIFI_CONNECTED_BIT = BIT0; + +static const char *TAG = "asio example wifi init"; + +/** + * Definition of ASIO main method, which is called after network initialized + */ +void asio_main(); + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch(event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + case SYSTEM_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", + MAC2STR(event->event_info.sta_connected.mac), + event->event_info.sta_connected.aid); + break; + case SYSTEM_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", + MAC2STR(event->event_info.sta_disconnected.mac), + event->event_info.sta_disconnected.aid); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +void wifi_init_sta() +{ + wifi_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + wifi_config_t wifi_config; + // zero out the config struct to ensure defaults are setup + memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); + // only copy ssid&password from example config + strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); + strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); +} + +extern "C" void app_main() +{ + //Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); + wifi_init_sta(); + + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); + esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); + + // wait till we receive IP, so asio realated code can be started + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); + + // network is ready, let's proceed with ASIO example + asio_main(); +} From 0ae8c3ca339b50c1e7e6439c413369f9a7ff2131 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 3 Aug 2018 16:59:23 +1000 Subject: [PATCH 02/60] asio example tests: Increase timeout for DHCP lease to 30s Covers time to connect to WiFi and negotiate lease, may be more than 5-10s on some busy APs * Original commit: espressif/esp-idf@8b35d8ef2576362fb1400ff9f04e009c5baa9a4d --- examples/protocols/asio/chat_client/asio_chat_client_test.py | 2 +- examples/protocols/asio/chat_server/asio_chat_server_test.py | 2 +- examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 2 +- examples/protocols/asio/udp_echo_server/asio_udp_server_test.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index a1cce97c5..5d6af28ee 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -75,7 +75,7 @@ def test_examples_protocol_asio_chat_client(env, extra_data): thread1.start() # 2. start the dut test and wait till client gets IP address dut1.start_app() - data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. send host's IP to the client i.e. the `dut1` dut1.write(host_ip) # 4. client `dut1` should receive a message diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 55746f1f9..b5eb71ff6 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -37,7 +37,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server cli = socket(AF_INET,SOCK_STREAM) cli.connect((data[0],80)) diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index 1ab432e62..6dcffa3a5 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -38,7 +38,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server cli = socket(AF_INET,SOCK_STREAM) cli.connect((data[0],80)) diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 490a8007a..642c686ed 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -38,7 +38,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" sta ip: ([^,]+),")) + data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server cli = socket(AF_INET, SOCK_DGRAM) cli.connect((data[0], 80)) From 6c47cfe30a9420a44e12981d9ba86b6aa71b2b6b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Sat, 4 Aug 2018 22:09:34 +0200 Subject: [PATCH 03/60] asio: added socket timeout for example tests * Original commit: espressif/esp-idf@c0186858ad2c4d52046835daa1bfcfa23256c725 --- examples/protocols/asio/chat_client/asio_chat_client_test.py | 4 +++- examples/protocols/asio/chat_server/asio_chat_server_test.py | 1 + .../protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 1 + .../protocols/asio/udp_echo_server/asio_udp_server_test.py | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index 5d6af28ee..f38c3f673 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -34,10 +34,12 @@ def chat_server_sketch(my_ip): print("Starting the server on {}".format(my_ip)) port=2222 s=socket(AF_INET, SOCK_STREAM) + s.settimeout(600) s.bind((my_ip, port)) s.listen(1) q,addr=s.accept() print("connection accepted") + q.settimeout(30) q.send(g_msg_to_client) data = q.recv(1024) # check if received initial empty message @@ -86,7 +88,7 @@ def test_examples_protocol_asio_chat_client(env, extra_data): time.sleep(1) print(g_client_response) # 6. evaluate host_server received this message - if (g_client_response[4:] == test_msg): + if (g_client_response[4:7] == test_msg): print("PASS: Received correct message") pass else: diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index b5eb71ff6..9f3e1408b 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -40,6 +40,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server cli = socket(AF_INET,SOCK_STREAM) + cli.settimeout(30) cli.connect((data[0],80)) cli.send(test_msg) data = cli.recv(1024) diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index 6dcffa3a5..3514bbc2c 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -41,6 +41,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server cli = socket(AF_INET,SOCK_STREAM) + cli.settimeout(30) cli.connect((data[0],80)) cli.send(test_msg) data = cli.recv(1024) diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 642c686ed..7b20b95ca 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -41,6 +41,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server cli = socket(AF_INET, SOCK_DGRAM) + cli.settimeout(30) cli.connect((data[0], 80)) cli.send(test_msg) data = cli.recv(1024) From 142200c7cad59edf218e875617ab33c049b39b67 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 16 Aug 2018 15:01:43 +1000 Subject: [PATCH 04/60] Merge branch 'master' into feature/cmake * Original commit: espressif/esp-idf@ff2404a27201e5a84e4b659bf3c5c131820d7b69 --- components/asio/CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 components/asio/CMakeLists.txt diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt new file mode 100644 index 000000000..9be66380e --- /dev/null +++ b/components/asio/CMakeLists.txt @@ -0,0 +1,8 @@ +set(COMPONENT_ADD_INCLUDEDIRS asio/asio/include port/include) +set(COMPONENT_SRCDIRS asio/asio/src) + +set(COMPONENT_SRCEXCLUDE asio/asio/src/asio_ssl.cpp) + +set(COMPONENT_REQUIRES lwip) + +register_component() From e8ea8786d2d8b94ae0b21b20279381624781d548 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 28 Aug 2018 11:10:48 +0800 Subject: [PATCH 05/60] cmake: Add missing example CMakeLists.txt files, CI check all examples have both * Original commit: espressif/esp-idf@5689e446dc92000b25cbe746355b217e3547b16b --- examples/protocols/asio/chat_client/CMakeLists.txt | 8 ++++++++ .../protocols/asio/chat_client/components/CMakeLists.txt | 5 +++++ examples/protocols/asio/chat_server/CMakeLists.txt | 8 ++++++++ .../protocols/asio/chat_server/components/CMakeLists.txt | 5 +++++ examples/protocols/asio/tcp_echo_server/CMakeLists.txt | 8 ++++++++ .../asio/tcp_echo_server/components/CMakeLists.txt | 5 +++++ examples/protocols/asio/udp_echo_server/CMakeLists.txt | 8 ++++++++ .../asio/udp_echo_server/components/CMakeLists.txt | 5 +++++ 8 files changed, 52 insertions(+) create mode 100644 examples/protocols/asio/chat_client/CMakeLists.txt create mode 100644 examples/protocols/asio/chat_client/components/CMakeLists.txt create mode 100644 examples/protocols/asio/chat_server/CMakeLists.txt create mode 100644 examples/protocols/asio/chat_server/components/CMakeLists.txt create mode 100644 examples/protocols/asio/tcp_echo_server/CMakeLists.txt create mode 100644 examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt create mode 100644 examples/protocols/asio/udp_echo_server/CMakeLists.txt create mode 100644 examples/protocols/asio/udp_echo_server/components/CMakeLists.txt diff --git a/examples/protocols/asio/chat_client/CMakeLists.txt b/examples/protocols/asio/chat_client/CMakeLists.txt new file mode 100644 index 000000000..78d29f0bd --- /dev/null +++ b/examples/protocols/asio/chat_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(MAIN_SRCS main/chat_client.cpp) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(asio_chat_client) diff --git a/examples/protocols/asio/chat_client/components/CMakeLists.txt b/examples/protocols/asio/chat_client/components/CMakeLists.txt new file mode 100644 index 000000000..4bb51e6a5 --- /dev/null +++ b/examples/protocols/asio/chat_client/components/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCDIRS ".") + +set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) + +register_component() diff --git a/examples/protocols/asio/chat_server/CMakeLists.txt b/examples/protocols/asio/chat_server/CMakeLists.txt new file mode 100644 index 000000000..91331df14 --- /dev/null +++ b/examples/protocols/asio/chat_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(MAIN_SRCS main/chat_server.cpp) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(asio_chat_server) diff --git a/examples/protocols/asio/chat_server/components/CMakeLists.txt b/examples/protocols/asio/chat_server/components/CMakeLists.txt new file mode 100644 index 000000000..4bb51e6a5 --- /dev/null +++ b/examples/protocols/asio/chat_server/components/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCDIRS ".") + +set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) + +register_component() diff --git a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt new file mode 100644 index 000000000..76bf9bcb6 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(MAIN_SRCS main/echo_server.cpp) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(asio_tcp_echo_server) diff --git a/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt new file mode 100644 index 000000000..4bb51e6a5 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCDIRS ".") + +set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) + +register_component() diff --git a/examples/protocols/asio/udp_echo_server/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/CMakeLists.txt new file mode 100644 index 000000000..143a364e4 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(MAIN_SRCS main/udp_echo_server.cpp) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(asio_udp_echo_server) diff --git a/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt new file mode 100644 index 000000000..4bb51e6a5 --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCDIRS ".") + +set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) + +register_component() From 57672d5add3ce3865cd6ef439cd7c5ea7f92da59 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 11 Sep 2018 09:44:12 +0800 Subject: [PATCH 06/60] cmake: make main a component again * Original commit: espressif/esp-idf@d9939cedd9b44d63dc148354c3a0a139b9c7113d --- components/asio/CMakeLists.txt | 4 +--- examples/protocols/asio/chat_client/CMakeLists.txt | 4 +--- examples/protocols/asio/chat_client/components/CMakeLists.txt | 2 +- examples/protocols/asio/chat_client/main/CMakeLists.txt | 4 ++++ examples/protocols/asio/chat_server/CMakeLists.txt | 4 +--- examples/protocols/asio/chat_server/components/CMakeLists.txt | 2 +- examples/protocols/asio/chat_server/main/CMakeLists.txt | 4 ++++ examples/protocols/asio/tcp_echo_server/CMakeLists.txt | 4 +--- .../protocols/asio/tcp_echo_server/components/CMakeLists.txt | 2 +- examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt | 4 ++++ examples/protocols/asio/udp_echo_server/CMakeLists.txt | 4 +--- .../protocols/asio/udp_echo_server/components/CMakeLists.txt | 2 +- examples/protocols/asio/udp_echo_server/main/CMakeLists.txt | 4 ++++ 13 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 examples/protocols/asio/chat_client/main/CMakeLists.txt create mode 100644 examples/protocols/asio/chat_server/main/CMakeLists.txt create mode 100644 examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt create mode 100644 examples/protocols/asio/udp_echo_server/main/CMakeLists.txt diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt index 9be66380e..43d428f8d 100644 --- a/components/asio/CMakeLists.txt +++ b/components/asio/CMakeLists.txt @@ -1,7 +1,5 @@ set(COMPONENT_ADD_INCLUDEDIRS asio/asio/include port/include) -set(COMPONENT_SRCDIRS asio/asio/src) - -set(COMPONENT_SRCEXCLUDE asio/asio/src/asio_ssl.cpp) +set(COMPONENT_SRCS "asio/asio/src/asio.cpp") set(COMPONENT_REQUIRES lwip) diff --git a/examples/protocols/asio/chat_client/CMakeLists.txt b/examples/protocols/asio/chat_client/CMakeLists.txt index 78d29f0bd..e0480c277 100644 --- a/examples/protocols/asio/chat_client/CMakeLists.txt +++ b/examples/protocols/asio/chat_client/CMakeLists.txt @@ -1,8 +1,6 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists +# The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(MAIN_SRCS main/chat_client.cpp) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_client) diff --git a/examples/protocols/asio/chat_client/components/CMakeLists.txt b/examples/protocols/asio/chat_client/components/CMakeLists.txt index 4bb51e6a5..e51766724 100644 --- a/examples/protocols/asio/chat_client/components/CMakeLists.txt +++ b/examples/protocols/asio/chat_client/components/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_SRCDIRS ".") +set(COMPONENT_SRCS "wifi_asio.cpp") set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) diff --git a/examples/protocols/asio/chat_client/main/CMakeLists.txt b/examples/protocols/asio/chat_client/main/CMakeLists.txt new file mode 100644 index 000000000..25419de4a --- /dev/null +++ b/examples/protocols/asio/chat_client/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "chat_client.cpp") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/protocols/asio/chat_server/CMakeLists.txt b/examples/protocols/asio/chat_server/CMakeLists.txt index 91331df14..c8c629856 100644 --- a/examples/protocols/asio/chat_server/CMakeLists.txt +++ b/examples/protocols/asio/chat_server/CMakeLists.txt @@ -1,8 +1,6 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists +# The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(MAIN_SRCS main/chat_server.cpp) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_server) diff --git a/examples/protocols/asio/chat_server/components/CMakeLists.txt b/examples/protocols/asio/chat_server/components/CMakeLists.txt index 4bb51e6a5..e51766724 100644 --- a/examples/protocols/asio/chat_server/components/CMakeLists.txt +++ b/examples/protocols/asio/chat_server/components/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_SRCDIRS ".") +set(COMPONENT_SRCS "wifi_asio.cpp") set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) diff --git a/examples/protocols/asio/chat_server/main/CMakeLists.txt b/examples/protocols/asio/chat_server/main/CMakeLists.txt new file mode 100644 index 000000000..7e44a9039 --- /dev/null +++ b/examples/protocols/asio/chat_server/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "chat_server.cpp") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt index 76bf9bcb6..b8d5638f7 100644 --- a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt @@ -1,8 +1,6 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists +# The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(MAIN_SRCS main/echo_server.cpp) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_tcp_echo_server) diff --git a/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt index 4bb51e6a5..e51766724 100644 --- a/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_SRCDIRS ".") +set(COMPONENT_SRCS "wifi_asio.cpp") set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) diff --git a/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt new file mode 100644 index 000000000..04c3c94d9 --- /dev/null +++ b/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "echo_server.cpp") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() diff --git a/examples/protocols/asio/udp_echo_server/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/CMakeLists.txt index 143a364e4..8d5c3a692 100644 --- a/examples/protocols/asio/udp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/CMakeLists.txt @@ -1,8 +1,6 @@ -# The following four lines of boilerplate have to be in your project's CMakeLists +# The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(MAIN_SRCS main/udp_echo_server.cpp) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_udp_echo_server) diff --git a/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt index 4bb51e6a5..e51766724 100644 --- a/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_SRCDIRS ".") +set(COMPONENT_SRCS "wifi_asio.cpp") set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) diff --git a/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt new file mode 100644 index 000000000..cd24937be --- /dev/null +++ b/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCS "udp_echo_server.cpp") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +register_component() From 86d107635bf7802de30bdbb8eb87f0d2a9d22a80 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 12 Sep 2018 15:52:38 +0200 Subject: [PATCH 07/60] asio: examples renamed to have consistent binary names when build in make and CMake * Original commit: espressif/esp-idf@9784df1c3a52592ecfd14a30d75cbad934dffa2e --- examples/protocols/asio/chat_client/Makefile | 2 +- .../protocols/asio/chat_client/asio_chat_client_test.py | 6 +++--- examples/protocols/asio/chat_server/Makefile | 2 +- .../protocols/asio/chat_server/asio_chat_server_test.py | 6 +++--- examples/protocols/asio/tcp_echo_server/Makefile | 2 +- .../protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 6 +++--- examples/protocols/asio/udp_echo_server/Makefile | 2 +- .../protocols/asio/udp_echo_server/asio_udp_server_test.py | 6 +++--- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/protocols/asio/chat_client/Makefile b/examples/protocols/asio/chat_client/Makefile index 8f651a3eb..924891a67 100644 --- a/examples/protocols/asio/chat_client/Makefile +++ b/examples/protocols/asio/chat_client/Makefile @@ -2,6 +2,6 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -PROJECT_NAME := asio_chatclient +PROJECT_NAME := asio_chat_client include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index f38c3f673..c8b9aacc6 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -67,10 +67,10 @@ def test_examples_protocol_asio_chat_client(env, extra_data): test_msg="ABC" dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client") # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_chatclient.bin") + binary_file = os.path.join(dut1.app.binary_path, "asio_chat_client.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_chatclient_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_chatclient_size", bin_size//1024) + IDF.log_performance("asio_chat_client_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_chat_client_size", bin_size//1024) # 1. start a tcp server on the host host_ip = get_my_ip() thread1 = Thread(target = chat_server_sketch, args = (host_ip,)) diff --git a/examples/protocols/asio/chat_server/Makefile b/examples/protocols/asio/chat_server/Makefile index c69f109c9..0b0ed1fc5 100644 --- a/examples/protocols/asio/chat_server/Makefile +++ b/examples/protocols/asio/chat_server/Makefile @@ -2,6 +2,6 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -PROJECT_NAME := asio_chatserver +PROJECT_NAME := asio_chat_server include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 9f3e1408b..ac90a9261 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -30,10 +30,10 @@ def test_examples_protocol_asio_chat_server(env, extra_data): test_msg=" 4ABC\n" dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server") # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_chatserver.bin") + binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_chatserver_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_chatserver_size", bin_size//1024) + IDF.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_chat_server_size", bin_size//1024) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/tcp_echo_server/Makefile b/examples/protocols/asio/tcp_echo_server/Makefile index 2a2839a54..ef5b79670 100644 --- a/examples/protocols/asio/tcp_echo_server/Makefile +++ b/examples/protocols/asio/tcp_echo_server/Makefile @@ -2,6 +2,6 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -PROJECT_NAME := asio_tcp_echoserver +PROJECT_NAME := asio_tcp_echo_server include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index 3514bbc2c..ad93a5596 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -31,10 +31,10 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): test_msg="echo message from client to server" dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server") # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echoserver.bin") + binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_tcp_echoserver_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_tcp_echoserver_size", bin_size//1024) + IDF.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_tcp_echo_server_size", bin_size//1024) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/udp_echo_server/Makefile b/examples/protocols/asio/udp_echo_server/Makefile index c659aeae0..a23a5c9ac 100644 --- a/examples/protocols/asio/udp_echo_server/Makefile +++ b/examples/protocols/asio/udp_echo_server/Makefile @@ -2,6 +2,6 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -PROJECT_NAME := asio_udp_echoserver +PROJECT_NAME := asio_udp_echo_server include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 7b20b95ca..44a577369 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -31,10 +31,10 @@ def test_examples_protocol_asio_udp_server(env, extra_data): test_msg="echo message from client to server" dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server") # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echoserver.bin") + binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_udp_echoserver_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_udp_echoserver_size", bin_size//1024) + IDF.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("asio_udp_echo_server_size", bin_size//1024) # 1. start test dut1.start_app() # 2. get the server IP address From a96c890f9715bc5fdd68dd276e262aa4acccb2aa Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Wed, 10 Oct 2018 13:19:31 +0200 Subject: [PATCH 08/60] Fix Python 3 compatibility issues * Original commit: espressif/esp-idf@9daf51e6be6991d6c952d587f47023eaef67ece4 --- .../asio/chat_client/asio_chat_client_test.py | 11 ++++++----- .../asio/chat_server/asio_chat_server_test.py | 2 +- .../asio/tcp_echo_server/asio_tcp_server_test.py | 4 ++-- .../asio/udp_echo_server/asio_udp_server_test.py | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index c8b9aacc6..37018ed37 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -19,8 +19,8 @@ import IDF global g_client_response; global g_msg_to_client; -g_client_response = "" -g_msg_to_client = " 3XYZ" +g_client_response = b"" +g_msg_to_client = b" 3XYZ" def get_my_ip(): s1 = socket(AF_INET, SOCK_DGRAM) @@ -81,11 +81,12 @@ def test_examples_protocol_asio_chat_client(env, extra_data): # 3. send host's IP to the client i.e. the `dut1` dut1.write(host_ip) # 4. client `dut1` should receive a message - dut1.expect(g_msg_to_client[4:]) # Strip out the front 4 bytes of message len (see chat_message protocol) + dut1.expect(g_msg_to_client[4:].decode()) # Strip out the front 4 bytes of message len (see chat_message protocol) # 5. write test message from `dut1` chat_client to the server dut1.write(test_msg) - while g_client_response == "": + while len(g_client_response) == 0: time.sleep(1) + g_client_response = g_client_response.decode() print(g_client_response) # 6. evaluate host_server received this message if (g_client_response[4:7] == test_msg): @@ -93,7 +94,7 @@ def test_examples_protocol_asio_chat_client(env, extra_data): pass else: print("Failure!") - raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(g_client_response, test_msg)) + raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(g_client_response[4:7], test_msg)) thread1.join() if __name__ == '__main__': diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index ac90a9261..7f25dc512 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -27,7 +27,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): 3. Test connects to server and sends a test message 4. Test evaluates received test message from server """ - test_msg=" 4ABC\n" + test_msg=b" 4ABC\n" dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server") # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index ad93a5596..840060d4c 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -28,7 +28,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): 4. Test evaluates received test message from server 5. Test evaluates received test message on server stdout """ - test_msg="echo message from client to server" + test_msg=b"echo message from client to server" dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server") # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") @@ -53,7 +53,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): print("Failure!") raise ValueError('Wrong data received from asi tcp server: {} (expoected:{})'.format(data, test_msg)) # 5. check the client message appears also on server terminal - dut1.expect(test_msg) + dut1.expect(test_msg.decode()) if __name__ == '__main__': diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 44a577369..5487700ff 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -28,7 +28,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): 4. Test evaluates received test message from server 5. Test evaluates received test message on server stdout """ - test_msg="echo message from client to server" + test_msg=b"echo message from client to server" dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server") # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") @@ -53,7 +53,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): print("Failure!") raise ValueError('Wrong data received from asi udp server: {} (expoected:{})'.format(data, test_msg)) # 5. check the client message appears also on server terminal - dut1.expect(test_msg) + dut1.expect(test_msg.decode()) if __name__ == '__main__': test_examples_protocol_asio_udp_server() From 21c0878f0e77486fa3f7368048df2f74bf14667b Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 4 Dec 2018 08:32:48 +0100 Subject: [PATCH 09/60] examples: Fix Python coding style * Original commit: espressif/esp-idf@57c54f96f1e58df6383fae5b8635fc15da816838 --- .../asio/chat_client/asio_chat_client_test.py | 53 ++++++++++--------- .../asio/chat_server/asio_chat_server_test.py | 33 ++++++------ .../tcp_echo_server/asio_tcp_server_test.py | 32 +++++------ .../udp_echo_server/asio_udp_server_test.py | 33 ++++++------ 4 files changed, 78 insertions(+), 73 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index 37018ed37..3b141c7d1 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -1,49 +1,52 @@ import re import os import sys -from socket import * +import socket from threading import Thread import time -# this is a test case write with tiny-test-fw. -# to run test cases outside tiny-test-fw, -# we need to set environment variable `TEST_FW_PATH`, -# then get and insert `TEST_FW_PATH` to sys path before import FW module -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) +try: + import IDF +except ImportError: + # this is a test case write with tiny-test-fw. + # to run test cases outside tiny-test-fw, + # we need to set environment variable `TEST_FW_PATH`, + # then get and insert `TEST_FW_PATH` to sys path before import FW module + test_fw_path = os.getenv("TEST_FW_PATH") + if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + import IDF -import TinyFW -import IDF - -global g_client_response; -global g_msg_to_client; +global g_client_response +global g_msg_to_client g_client_response = b"" g_msg_to_client = b" 3XYZ" + def get_my_ip(): - s1 = socket(AF_INET, SOCK_DGRAM) + s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s1.connect(("8.8.8.8", 80)) my_ip = s1.getsockname()[0] s1.close() return my_ip + def chat_server_sketch(my_ip): global g_client_response print("Starting the server on {}".format(my_ip)) - port=2222 - s=socket(AF_INET, SOCK_STREAM) + port = 2222 + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(600) s.bind((my_ip, port)) s.listen(1) - q,addr=s.accept() + q,addr = s.accept() print("connection accepted") q.settimeout(30) q.send(g_msg_to_client) data = q.recv(1024) # check if received initial empty message - if (len(data)>4): + if (len(data) > 4): g_client_response = data else: g_client_response = q.recv(1024) @@ -51,6 +54,7 @@ def chat_server_sketch(my_ip): s.close() print("server closed") + @IDF.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_asio_chat_client(env, extra_data): """ @@ -64,24 +68,24 @@ def test_examples_protocol_asio_chat_client(env, extra_data): """ global g_client_response global g_msg_to_client - test_msg="ABC" + test_msg = "ABC" dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client") # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_chat_client.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_chat_client_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_chat_client_size", bin_size//1024) + IDF.log_performance("asio_chat_client_size", "{}KB".format(bin_size // 1024)) + IDF.check_performance("asio_chat_client_size", bin_size // 1024) # 1. start a tcp server on the host host_ip = get_my_ip() - thread1 = Thread(target = chat_server_sketch, args = (host_ip,)) + thread1 = Thread(target=chat_server_sketch, args=(host_ip,)) thread1.start() # 2. start the dut test and wait till client gets IP address dut1.start_app() - data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. send host's IP to the client i.e. the `dut1` dut1.write(host_ip) # 4. client `dut1` should receive a message - dut1.expect(g_msg_to_client[4:].decode()) # Strip out the front 4 bytes of message len (see chat_message protocol) + dut1.expect(g_msg_to_client[4:].decode()) # Strip out the front 4 bytes of message len (see chat_message protocol) # 5. write test message from `dut1` chat_client to the server dut1.write(test_msg) while len(g_client_response) == 0: @@ -97,5 +101,6 @@ def test_examples_protocol_asio_chat_client(env, extra_data): raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(g_client_response[4:7], test_msg)) thread1.join() + if __name__ == '__main__': test_examples_protocol_asio_chat_client() diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 7f25dc512..4f28116aa 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -1,21 +1,20 @@ import re import os import sys -from socket import * - - -# this is a test case write with tiny-test-fw. -# to run test cases outside tiny-test-fw, -# we need to set environment variable `TEST_FW_PATH`, -# then get and insert `TEST_FW_PATH` to sys path before import FW module -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - -import TinyFW -import IDF +import socket +try: + import IDF +except ImportError: + # this is a test case write with tiny-test-fw. + # to run test cases outside tiny-test-fw, + # we need to set environment variable `TEST_FW_PATH`, + # then get and insert `TEST_FW_PATH` to sys path before import FW module + test_fw_path = os.getenv("TEST_FW_PATH") + if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + import IDF @IDF.idf_example_test(env_tag="Example_WIFI") @@ -27,19 +26,19 @@ def test_examples_protocol_asio_chat_server(env, extra_data): 3. Test connects to server and sends a test message 4. Test evaluates received test message from server """ - test_msg=b" 4ABC\n" + test_msg = b" 4ABC\n" dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server") # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_chat_server_size", bin_size//1024) + IDF.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size // 1024)) + IDF.check_performance("asio_chat_server_size", bin_size // 1024) # 1. start test dut1.start_app() # 2. get the server IP address data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server - cli = socket(AF_INET,SOCK_STREAM) + cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) cli.connect((data[0],80)) cli.send(test_msg) diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index 840060d4c..c29b8ce7b 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -1,21 +1,21 @@ import re import os import sys -from socket import * +import socket -# this is a test case write with tiny-test-fw. -# to run test cases outside tiny-test-fw, -# we need to set environment variable `TEST_FW_PATH`, -# then get and insert `TEST_FW_PATH` to sys path before import FW module -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - -import TinyFW -import IDF - +try: + import IDF +except ImportError: + # this is a test case write with tiny-test-fw. + # to run test cases outside tiny-test-fw, + # we need to set environment variable `TEST_FW_PATH`, + # then get and insert `TEST_FW_PATH` to sys path before import FW module + test_fw_path = os.getenv("TEST_FW_PATH") + if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + import IDF @IDF.idf_example_test(env_tag="Example_WIFI") @@ -28,19 +28,19 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): 4. Test evaluates received test message from server 5. Test evaluates received test message on server stdout """ - test_msg=b"echo message from client to server" + test_msg = b"echo message from client to server" dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server") # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_tcp_echo_server_size", bin_size//1024) + IDF.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) + IDF.check_performance("asio_tcp_echo_server_size", bin_size // 1024) # 1. start test dut1.start_app() # 2. get the server IP address data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server - cli = socket(AF_INET,SOCK_STREAM) + cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) cli.connect((data[0],80)) cli.send(test_msg) diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 5487700ff..d3a01563c 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -1,21 +1,21 @@ import re import os import sys -from socket import * +import socket -# this is a test case write with tiny-test-fw. -# to run test cases outside tiny-test-fw, -# we need to set environment variable `TEST_FW_PATH`, -# then get and insert `TEST_FW_PATH` to sys path before import FW module -test_fw_path = os.getenv("TEST_FW_PATH") -if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - -import TinyFW -import IDF - +try: + import IDF +except ImportError: + # this is a test case write with tiny-test-fw. + # to run test cases outside tiny-test-fw, + # we need to set environment variable `TEST_FW_PATH`, + # then get and insert `TEST_FW_PATH` to sys path before import FW module + test_fw_path = os.getenv("TEST_FW_PATH") + if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + import IDF @IDF.idf_example_test(env_tag="Example_WIFI") @@ -28,19 +28,19 @@ def test_examples_protocol_asio_udp_server(env, extra_data): 4. Test evaluates received test message from server 5. Test evaluates received test message on server stdout """ - test_msg=b"echo message from client to server" + test_msg = b"echo message from client to server" dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server") # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size//1024)) - IDF.check_performance("asio_udp_echo_server_size", bin_size//1024) + IDF.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) + IDF.check_performance("asio_udp_echo_server_size", bin_size // 1024) # 1. start test dut1.start_app() # 2. get the server IP address data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) # 3. create tcp client and connect to server - cli = socket(AF_INET, SOCK_DGRAM) + cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) cli.settimeout(30) cli.connect((data[0], 80)) cli.send(test_msg) @@ -55,5 +55,6 @@ def test_examples_protocol_asio_udp_server(env, extra_data): # 5. check the client message appears also on server terminal dut1.expect(test_msg.decode()) + if __name__ == '__main__': test_examples_protocol_asio_udp_server() From de830e51d4178df32dc1060b15daf8b626981087 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 25 Jan 2019 17:10:53 +0100 Subject: [PATCH 10/60] Correct Kconfigs according to the coding style * Original commit: espressif/esp-idf@37126d3451eabb44eeeb48b8e2ee554dc233e2a8 --- .../asio/chat_client/main/Kconfig.projbuild | 41 ++++++++++--------- .../asio/chat_server/main/Kconfig.projbuild | 30 +++++++------- .../tcp_echo_server/main/Kconfig.projbuild | 30 +++++++------- .../udp_echo_server/main/Kconfig.projbuild | 30 +++++++------- 4 files changed, 66 insertions(+), 65 deletions(-) diff --git a/examples/protocols/asio/chat_client/main/Kconfig.projbuild b/examples/protocols/asio/chat_client/main/Kconfig.projbuild index 32e5f3fcb..4185e2424 100644 --- a/examples/protocols/asio/chat_client/main/Kconfig.projbuild +++ b/examples/protocols/asio/chat_client/main/Kconfig.projbuild @@ -1,27 +1,28 @@ menu "Example Configuration" -config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config EXAMPLE_PORT - string "asio example port number" - default "2222" - help - Port number used by ASIO example + config EXAMPLE_PORT + string "asio example port number" + default "2222" + help + Port number used by ASIO example -config EXAMPLE_SERVER_IP - string "asio example server ip for this client to connect to (leave defalut=FROM_STDIN to enter the server address via serial terminal)" - default "FROM_STDIN" - help - Please set the host name or ip address of corespondant server running + config EXAMPLE_SERVER_IP + string "asio example server ip" + default "FROM_STDIN" + help + asio example server ip for this client to connect to (leave default=FROM_STDIN to enter the server address + via serial terminal). endmenu diff --git a/examples/protocols/asio/chat_server/main/Kconfig.projbuild b/examples/protocols/asio/chat_server/main/Kconfig.projbuild index c0d6fd9cd..ecbbf8ae9 100644 --- a/examples/protocols/asio/chat_server/main/Kconfig.projbuild +++ b/examples/protocols/asio/chat_server/main/Kconfig.projbuild @@ -1,21 +1,21 @@ menu "Example Configuration" -config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config EXAMPLE_PORT - string "asio example port number" - default "80" - help - Port number used by ASIO example + config EXAMPLE_PORT + string "asio example port number" + default "80" + help + Port number used by ASIO example endmenu diff --git a/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild b/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild index c0d6fd9cd..ecbbf8ae9 100644 --- a/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild +++ b/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild @@ -1,21 +1,21 @@ menu "Example Configuration" -config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config EXAMPLE_PORT - string "asio example port number" - default "80" - help - Port number used by ASIO example + config EXAMPLE_PORT + string "asio example port number" + default "80" + help + Port number used by ASIO example endmenu diff --git a/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild b/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild index c0d6fd9cd..ecbbf8ae9 100644 --- a/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild +++ b/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild @@ -1,21 +1,21 @@ menu "Example Configuration" -config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. + config ESP_WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. -config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. + config ESP_WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. -config EXAMPLE_PORT - string "asio example port number" - default "80" - help - Port number used by ASIO example + config EXAMPLE_PORT + string "asio example port number" + default "80" + help + Port number used by ASIO example endmenu From 3e7591e92a58a3471ad8450035e7e6302553352a Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 21 Nov 2018 00:44:31 +0800 Subject: [PATCH 11/60] examples/protocols/asio: use common network component * Original commit: espressif/esp-idf@aa4a7804ec5bd1f8a1da046dfe1fd7368ded2205 --- .../protocols/asio/chat_client/CMakeLists.txt | 4 + examples/protocols/asio/chat_client/Makefile | 2 + examples/protocols/asio/chat_client/README.md | 19 +-- .../chat_client/components/CMakeLists.txt | 5 - .../asio/chat_client/components/component.mk | 10 -- .../asio/chat_client/components/wifi_asio.cpp | 136 ------------------ .../asio/chat_client/main/Kconfig.projbuild | 22 +-- .../asio/chat_client/main/chat_client.cpp | 23 ++- .../protocols/asio/chat_server/CMakeLists.txt | 4 + examples/protocols/asio/chat_server/Makefile | 2 + examples/protocols/asio/chat_server/README.md | 19 +-- .../asio/chat_server/asio_chat_server_test.py | 2 +- .../chat_server/components/CMakeLists.txt | 5 - .../asio/chat_server/components/component.mk | 10 -- .../asio/chat_server/components/wifi_asio.cpp | 136 ------------------ .../asio/chat_server/main/Kconfig.projbuild | 18 +-- .../asio/chat_server/main/chat_server.cpp | 22 ++- .../asio/tcp_echo_server/CMakeLists.txt | 4 + .../protocols/asio/tcp_echo_server/Makefile | 2 + .../protocols/asio/tcp_echo_server/README.md | 19 +-- .../tcp_echo_server/asio_tcp_server_test.py | 4 +- .../tcp_echo_server/components/CMakeLists.txt | 5 - .../tcp_echo_server/components/component.mk | 10 -- .../tcp_echo_server/components/wifi_asio.cpp | 136 ------------------ .../tcp_echo_server/main/Kconfig.projbuild | 18 +-- .../asio/tcp_echo_server/main/echo_server.cpp | 20 ++- .../asio/udp_echo_server/CMakeLists.txt | 4 + .../protocols/asio/udp_echo_server/Makefile | 2 + .../protocols/asio/udp_echo_server/README.md | 17 +-- .../udp_echo_server/asio_udp_server_test.py | 4 +- .../udp_echo_server/components/CMakeLists.txt | 5 - .../udp_echo_server/components/component.mk | 10 -- .../udp_echo_server/components/wifi_asio.cpp | 136 ------------------ .../udp_echo_server/main/Kconfig.projbuild | 18 +-- .../udp_echo_server/main/udp_echo_server.cpp | 22 ++- .../protocols/asio/wifi_init/wifi_asio.cpp | 136 ------------------ 36 files changed, 161 insertions(+), 850 deletions(-) delete mode 100644 examples/protocols/asio/chat_client/components/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_client/components/component.mk delete mode 100644 examples/protocols/asio/chat_client/components/wifi_asio.cpp delete mode 100644 examples/protocols/asio/chat_server/components/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_server/components/component.mk delete mode 100644 examples/protocols/asio/chat_server/components/wifi_asio.cpp delete mode 100644 examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt delete mode 100644 examples/protocols/asio/tcp_echo_server/components/component.mk delete mode 100644 examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp delete mode 100644 examples/protocols/asio/udp_echo_server/components/CMakeLists.txt delete mode 100644 examples/protocols/asio/udp_echo_server/components/component.mk delete mode 100644 examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp delete mode 100644 examples/protocols/asio/wifi_init/wifi_asio.cpp diff --git a/examples/protocols/asio/chat_client/CMakeLists.txt b/examples/protocols/asio/chat_client/CMakeLists.txt index e0480c277..ddcc068ba 100644 --- a/examples/protocols/asio/chat_client/CMakeLists.txt +++ b/examples/protocols/asio/chat_client/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_client) diff --git a/examples/protocols/asio/chat_client/Makefile b/examples/protocols/asio/chat_client/Makefile index 924891a67..90197676a 100644 --- a/examples/protocols/asio/chat_client/Makefile +++ b/examples/protocols/asio/chat_client/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := asio_chat_client +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_client/README.md b/examples/protocols/asio/chat_client/README.md index 0ab16f578..951afad53 100644 --- a/examples/protocols/asio/chat_client/README.md +++ b/examples/protocols/asio/chat_client/README.md @@ -1,19 +1,20 @@ -# ASIO chat server example +# Asio chat client example -Simple asio chat client using WiFi STA +Simple Asio chat client using WiFi STA or Ethernet. ## Example workflow -- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` -- Once connected and acquired IP address ASIO chat client connects to a corresponding server whose port number and ip are defined through `make menuconfig` -- Chat client receives all messages from other chat clients, also it sends message received from stdin using `make monitor` +- Wi-Fi or Ethernet connection is established, and IP address is obtained. +- Asio chat client connects to the corresponding server whose port number and IP are defined through `make menuconfig`. +- Chat client receives all messages from other chat clients, also it sends message received from stdin using `make monitor`. ## Running the example -- Run `make menuconfig` to configure the access point's SSID and Password and server ip address and port number -- Start chat server either on host machine or as another ESP device running chat_server example -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal -- Wait for WiFi to connect to your access point +- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Set server IP address and port number in menuconfig, "Example configuration". +- Start chat server either on host machine or as another ESP device running chat_server example. +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet. - Receive and send messages to/from other clients on stdin/stdout via serial terminal. See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/chat_client/components/CMakeLists.txt b/examples/protocols/asio/chat_client/components/CMakeLists.txt deleted file mode 100644 index e51766724..000000000 --- a/examples/protocols/asio/chat_client/components/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(COMPONENT_SRCS "wifi_asio.cpp") - -set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) - -register_component() diff --git a/examples/protocols/asio/chat_client/components/component.mk b/examples/protocols/asio/chat_client/components/component.mk deleted file mode 100644 index b23b0cb71..000000000 --- a/examples/protocols/asio/chat_client/components/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# - -COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/chat_client/components/wifi_asio.cpp b/examples/protocols/asio/chat_client/components/wifi_asio.cpp deleted file mode 100644 index b90ce26ae..000000000 --- a/examples/protocols/asio/chat_client/components/wifi_asio.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* Common WiFi Init as STA for ASIO examples - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "driver/uart.h" -#include "esp_console.h" -#include "esp_vfs_dev.h" - -#include "lwip/err.h" -#include "lwip/sys.h" - -#include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int WIFI_CONNECTED_BIT = BIT0; - -static const char *TAG = "asio example wifi init"; - -/** - * Definition of ASIO main method, which is called after network initialized - */ -void asio_main(); - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void wifi_init_sta() -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config; - // zero out the config struct to ensure defaults are setup - memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); - // only copy ssid&password from example config - strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); - strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK(esp_wifi_start() ); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); -} - -extern "C" void app_main() -{ - //Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); - wifi_init_sta(); - - // Initialize VFS & UART so we can use std::cout/cin - setvbuf(stdin, NULL, _IONBF, 0); - setvbuf(stdout, NULL, _IONBF, 0); - /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, - 256, 0, 0, NULL, 0) ); - /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); - esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); - /* Move the caret to the beginning of the next line on '\n' */ - esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); - - // wait till we receive IP, so asio realated code can be started - xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); - - // network is ready, let's proceed with ASIO example - asio_main(); -} diff --git a/examples/protocols/asio/chat_client/main/Kconfig.projbuild b/examples/protocols/asio/chat_client/main/Kconfig.projbuild index 4185e2424..34d9e93cf 100644 --- a/examples/protocols/asio/chat_client/main/Kconfig.projbuild +++ b/examples/protocols/asio/chat_client/main/Kconfig.projbuild @@ -1,28 +1,16 @@ menu "Example Configuration" - config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config EXAMPLE_PORT - string "asio example port number" + string "Asio example server port number" default "2222" help - Port number used by ASIO example + Port number used by Asio example. config EXAMPLE_SERVER_IP - string "asio example server ip" + string "Asio example server ip" default "FROM_STDIN" help - asio example server ip for this client to connect to (leave default=FROM_STDIN to enter the server address - via serial terminal). + Asio example server ip for this client to connect to. + Leave default "FROM_STDIN" to enter the server address via serial terminal. endmenu diff --git a/examples/protocols/asio/chat_client/main/chat_client.cpp b/examples/protocols/asio/chat_client/main/chat_client.cpp index e18d8d4e3..d4a111057 100644 --- a/examples/protocols/asio/chat_client/main/chat_client.cpp +++ b/examples/protocols/asio/chat_client/main/chat_client.cpp @@ -14,6 +14,10 @@ #include #include "asio.hpp" #include "chat_message.hpp" +#include "protocol_examples_common.h" +#include "esp_event.h" +#include "tcpip_adapter.h" +#include "nvs_flash.h" using asio::ip::tcp; @@ -130,8 +134,21 @@ private: void read_line(char * line, int max_chars); -void asio_main() +extern "C" void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + /* This helper function configures blocking UART I/O */ + ESP_ERROR_CHECK(example_configure_stdin_stdout()); + std::string name(CONFIG_EXAMPLE_SERVER_IP); std::string port(CONFIG_EXAMPLE_PORT); char line[chat_message::max_body_length + 1] = { 0 }; @@ -152,7 +169,7 @@ void asio_main() std::thread t([&io_context](){ io_context.run(); }); - while (std::cin.getline(line, chat_message::max_body_length + 1) && std::string(line) != "exit\n") { + while (std::cin.getline(line, chat_message::max_body_length + 1) && std::string(line) != "exit") { chat_message msg; msg.body_length(std::strlen(line)); std::memcpy(msg.body(), line, msg.body_length()); @@ -162,4 +179,6 @@ void asio_main() c.close(); t.join(); + + ESP_ERROR_CHECK(example_disconnect()); } diff --git a/examples/protocols/asio/chat_server/CMakeLists.txt b/examples/protocols/asio/chat_server/CMakeLists.txt index c8c629856..182f8d402 100644 --- a/examples/protocols/asio/chat_server/CMakeLists.txt +++ b/examples/protocols/asio/chat_server/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_server) diff --git a/examples/protocols/asio/chat_server/Makefile b/examples/protocols/asio/chat_server/Makefile index 0b0ed1fc5..a7656889f 100644 --- a/examples/protocols/asio/chat_server/Makefile +++ b/examples/protocols/asio/chat_server/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := asio_chat_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_server/README.md b/examples/protocols/asio/chat_server/README.md index 591efd977..e043cba32 100644 --- a/examples/protocols/asio/chat_server/README.md +++ b/examples/protocols/asio/chat_server/README.md @@ -1,19 +1,20 @@ -# ASIO chat server example +# Asio chat server example -Simple asio chat server using WiFi STA +Simple Asio chat server using WiFi STA or Ethernet. ## Example workflow -- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` -- Once connected and acquired IP address, ASIO chat server is started on port number defined through `make menuconfig` -- Chat server echoes a message (received from any client) to all connected clients +- Wi-Fi or Ethernet connection is established, and IP address is obtained. +- Asio chat server is started on port number defined through `make menuconfig`. +- Chat server echoes a message (received from any client) to all connected clients. ## Running the example -- Run `make menuconfig` to configure the access point's SSID and Password and port number -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal -- Wait for WiFi to connect to your access point (note the IP address) -- Connect to the server using multiple clients, for example using any option below +- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Set server port number in menuconfig, "Example configuration". +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet (note the IP address). +- Connect to the server using multiple clients, for example using any option below. - build and run asi chat client on your host machine - run chat_client asio example on ESP platform - since chat message consist of ascii size and message, it is possible to diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 4f28116aa..ea4702c4e 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -40,7 +40,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) - cli.connect((data[0],80)) + cli.connect((data[0], 2222)) cli.send(test_msg) data = cli.recv(1024) # 4. check the message received back from the server diff --git a/examples/protocols/asio/chat_server/components/CMakeLists.txt b/examples/protocols/asio/chat_server/components/CMakeLists.txt deleted file mode 100644 index e51766724..000000000 --- a/examples/protocols/asio/chat_server/components/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(COMPONENT_SRCS "wifi_asio.cpp") - -set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) - -register_component() diff --git a/examples/protocols/asio/chat_server/components/component.mk b/examples/protocols/asio/chat_server/components/component.mk deleted file mode 100644 index b23b0cb71..000000000 --- a/examples/protocols/asio/chat_server/components/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# - -COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/chat_server/components/wifi_asio.cpp b/examples/protocols/asio/chat_server/components/wifi_asio.cpp deleted file mode 100644 index b90ce26ae..000000000 --- a/examples/protocols/asio/chat_server/components/wifi_asio.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* Common WiFi Init as STA for ASIO examples - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "driver/uart.h" -#include "esp_console.h" -#include "esp_vfs_dev.h" - -#include "lwip/err.h" -#include "lwip/sys.h" - -#include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int WIFI_CONNECTED_BIT = BIT0; - -static const char *TAG = "asio example wifi init"; - -/** - * Definition of ASIO main method, which is called after network initialized - */ -void asio_main(); - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void wifi_init_sta() -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config; - // zero out the config struct to ensure defaults are setup - memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); - // only copy ssid&password from example config - strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); - strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK(esp_wifi_start() ); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); -} - -extern "C" void app_main() -{ - //Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); - wifi_init_sta(); - - // Initialize VFS & UART so we can use std::cout/cin - setvbuf(stdin, NULL, _IONBF, 0); - setvbuf(stdout, NULL, _IONBF, 0); - /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, - 256, 0, 0, NULL, 0) ); - /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); - esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); - /* Move the caret to the beginning of the next line on '\n' */ - esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); - - // wait till we receive IP, so asio realated code can be started - xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); - - // network is ready, let's proceed with ASIO example - asio_main(); -} diff --git a/examples/protocols/asio/chat_server/main/Kconfig.projbuild b/examples/protocols/asio/chat_server/main/Kconfig.projbuild index ecbbf8ae9..c1f397b9c 100644 --- a/examples/protocols/asio/chat_server/main/Kconfig.projbuild +++ b/examples/protocols/asio/chat_server/main/Kconfig.projbuild @@ -1,21 +1,9 @@ menu "Example Configuration" - config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config EXAMPLE_PORT - string "asio example port number" - default "80" + string "Asio example server port number" + default "2222" help - Port number used by ASIO example + Port number used by Asio example endmenu diff --git a/examples/protocols/asio/chat_server/main/chat_server.cpp b/examples/protocols/asio/chat_server/main/chat_server.cpp index 05740f479..56a447e05 100644 --- a/examples/protocols/asio/chat_server/main/chat_server.cpp +++ b/examples/protocols/asio/chat_server/main/chat_server.cpp @@ -17,6 +17,11 @@ #include #include "asio.hpp" #include "chat_message.hpp" +#include "protocol_examples_common.h" +#include "esp_event.h" +#include "tcpip_adapter.h" +#include "nvs_flash.h" + using asio::ip::tcp; @@ -197,8 +202,21 @@ private: //---------------------------------------------------------------------- -int asio_main() +extern "C" void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + /* This helper function configures blocking UART I/O */ + ESP_ERROR_CHECK(example_configure_stdin_stdout()); + asio::io_context io_context; std::list servers; @@ -209,6 +227,4 @@ int asio_main() } io_context.run(); - - return 0; } diff --git a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt index b8d5638f7..6bf8f4682 100644 --- a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_tcp_echo_server) diff --git a/examples/protocols/asio/tcp_echo_server/Makefile b/examples/protocols/asio/tcp_echo_server/Makefile index ef5b79670..ed9cfb8d8 100644 --- a/examples/protocols/asio/tcp_echo_server/Makefile +++ b/examples/protocols/asio/tcp_echo_server/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := asio_tcp_echo_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/tcp_echo_server/README.md b/examples/protocols/asio/tcp_echo_server/README.md index a32fd93ea..f672027ef 100644 --- a/examples/protocols/asio/tcp_echo_server/README.md +++ b/examples/protocols/asio/tcp_echo_server/README.md @@ -1,18 +1,19 @@ -# ASIO tcp echo server example +# Asio TCP echo server example -Simple asio echo server using WiFi STA +Simple Asio TCP echo server using WiFi STA or Ethernet. ## Example workflow -- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` -- Once connected and acquired IP address, ASIO tcp server is started on port number defined through `make menuconfig` -- Server receives and echoes back messages transmitted from client +- Wi-Fi or Ethernet connection is established, and IP address is obtained. +- Asio TCP server is started on port number defined through `make menuconfig`. +- Server receives and echoes back messages transmitted from client. ## Running the example -- Run `make menuconfig` to configure the access point's SSID and Password and port number -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal -- Wait for WiFi to connect to your access point (note the IP address) -- You can now send a tcp message and check it is repeated, for example using netcat `nc IP PORT` +- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Set server port number in menuconfig, "Example configuration". +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet (note the IP address). +- You can now send a TCP message and check it is repeated, for example using netcat `nc IP PORT`. See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index c29b8ce7b..2cdfd45ae 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -42,7 +42,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) - cli.connect((data[0],80)) + cli.connect((data[0], 2222)) cli.send(test_msg) data = cli.recv(1024) # 4. check the message received back from the server @@ -51,7 +51,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): pass else: print("Failure!") - raise ValueError('Wrong data received from asi tcp server: {} (expoected:{})'.format(data, test_msg)) + raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(data, test_msg)) # 5. check the client message appears also on server terminal dut1.expect(test_msg.decode()) diff --git a/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt deleted file mode 100644 index e51766724..000000000 --- a/examples/protocols/asio/tcp_echo_server/components/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(COMPONENT_SRCS "wifi_asio.cpp") - -set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) - -register_component() diff --git a/examples/protocols/asio/tcp_echo_server/components/component.mk b/examples/protocols/asio/tcp_echo_server/components/component.mk deleted file mode 100644 index b23b0cb71..000000000 --- a/examples/protocols/asio/tcp_echo_server/components/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# - -COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp b/examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp deleted file mode 100644 index b90ce26ae..000000000 --- a/examples/protocols/asio/tcp_echo_server/components/wifi_asio.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* Common WiFi Init as STA for ASIO examples - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "driver/uart.h" -#include "esp_console.h" -#include "esp_vfs_dev.h" - -#include "lwip/err.h" -#include "lwip/sys.h" - -#include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int WIFI_CONNECTED_BIT = BIT0; - -static const char *TAG = "asio example wifi init"; - -/** - * Definition of ASIO main method, which is called after network initialized - */ -void asio_main(); - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void wifi_init_sta() -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config; - // zero out the config struct to ensure defaults are setup - memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); - // only copy ssid&password from example config - strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); - strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK(esp_wifi_start() ); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); -} - -extern "C" void app_main() -{ - //Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); - wifi_init_sta(); - - // Initialize VFS & UART so we can use std::cout/cin - setvbuf(stdin, NULL, _IONBF, 0); - setvbuf(stdout, NULL, _IONBF, 0); - /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, - 256, 0, 0, NULL, 0) ); - /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); - esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); - /* Move the caret to the beginning of the next line on '\n' */ - esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); - - // wait till we receive IP, so asio realated code can be started - xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); - - // network is ready, let's proceed with ASIO example - asio_main(); -} diff --git a/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild b/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild index ecbbf8ae9..795326db9 100644 --- a/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild +++ b/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild @@ -1,21 +1,9 @@ menu "Example Configuration" - config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config EXAMPLE_PORT - string "asio example port number" - default "80" + string "Asio example port number" + default "2222" help - Port number used by ASIO example + Port number used by Asio example. endmenu diff --git a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp index 22f171f53..008ec6ed7 100644 --- a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp +++ b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp @@ -1,6 +1,10 @@ #include "asio.hpp" #include #include +#include "protocol_examples_common.h" +#include "esp_event.h" +#include "tcpip_adapter.h" +#include "nvs_flash.h" using asio::ip::tcp; @@ -27,6 +31,7 @@ private: { if (!ec) { + data_[length] = 0; std::cout << data_ << std::endl; do_write(length); } @@ -79,13 +84,24 @@ private: }; -void asio_main() +extern "C" void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + /* This helper function configures blocking UART I/O */ + ESP_ERROR_CHECK(example_configure_stdin_stdout()); asio::io_context io_context; server s(io_context, std::atoi(CONFIG_EXAMPLE_PORT)); io_context.run(); - } \ No newline at end of file diff --git a/examples/protocols/asio/udp_echo_server/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/CMakeLists.txt index 8d5c3a692..59493277c 100644 --- a/examples/protocols/asio/udp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/CMakeLists.txt @@ -2,5 +2,9 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_udp_echo_server) diff --git a/examples/protocols/asio/udp_echo_server/Makefile b/examples/protocols/asio/udp_echo_server/Makefile index a23a5c9ac..f28a9d96a 100644 --- a/examples/protocols/asio/udp_echo_server/Makefile +++ b/examples/protocols/asio/udp_echo_server/Makefile @@ -4,4 +4,6 @@ # PROJECT_NAME := asio_udp_echo_server +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/udp_echo_server/README.md b/examples/protocols/asio/udp_echo_server/README.md index 6cf2c2ba3..cc69fee08 100644 --- a/examples/protocols/asio/udp_echo_server/README.md +++ b/examples/protocols/asio/udp_echo_server/README.md @@ -1,18 +1,19 @@ -# ASIO udp echo server example +# Asio UDP echo server example -Simple asio echo server using WiFi STA +Simple Asio UDP echo server using WiFi STA or Ethernet. ## Example workflow -- WiFi STA is started and trying to connect to the access point defined through `make menuconfig` -- Once connected and acquired IP address, ASIO udp server is started on port number defined through `make menuconfig` +- Wi-Fi or Ethernet connection is established, and IP address is obtained. +- Asio UDP server is started on port number defined through `make menuconfig` - Server receives and echoes back messages transmitted from client ## Running the example -- Run `make menuconfig` to configure the access point's SSID and Password and port number -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal -- Wait for WiFi to connect to your access point (note the IP address) -- You can now send a udp message and check it is repeated, for example using netcat `nc -u IP PORT` +- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Set server port number in menuconfig, "Example configuration". +- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet (note the IP address). +- You can now send a UDP message and check it is repeated, for example using netcat `nc -u IP PORT`. See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index d3a01563c..dc2cc78a8 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -42,7 +42,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) cli.settimeout(30) - cli.connect((data[0], 80)) + cli.connect((data[0], 2222)) cli.send(test_msg) data = cli.recv(1024) # 4. check the message received back from the server @@ -51,7 +51,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): pass else: print("Failure!") - raise ValueError('Wrong data received from asi udp server: {} (expoected:{})'.format(data, test_msg)) + raise ValueError('Wrong data received from asio udp server: {} (expected:{})'.format(data, test_msg)) # 5. check the client message appears also on server terminal dut1.expect(test_msg.decode()) diff --git a/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt deleted file mode 100644 index e51766724..000000000 --- a/examples/protocols/asio/udp_echo_server/components/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -set(COMPONENT_SRCS "wifi_asio.cpp") - -set(COMPONENT_PRIV_REQUIRES asio nvs_flash console) - -register_component() diff --git a/examples/protocols/asio/udp_echo_server/components/component.mk b/examples/protocols/asio/udp_echo_server/components/component.mk deleted file mode 100644 index b23b0cb71..000000000 --- a/examples/protocols/asio/udp_echo_server/components/component.mk +++ /dev/null @@ -1,10 +0,0 @@ -# -# Component Makefile -# -# This Makefile should, at the very least, just include $(SDK_PATH)/Makefile. By default, -# this will take the sources in the src/ directory, compile them and link them into -# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, -# please read the SDK documents if you need to do this. -# - -COMPONENT_SRCDIRS = . diff --git a/examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp b/examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp deleted file mode 100644 index b90ce26ae..000000000 --- a/examples/protocols/asio/udp_echo_server/components/wifi_asio.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* Common WiFi Init as STA for ASIO examples - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "driver/uart.h" -#include "esp_console.h" -#include "esp_vfs_dev.h" - -#include "lwip/err.h" -#include "lwip/sys.h" - -#include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int WIFI_CONNECTED_BIT = BIT0; - -static const char *TAG = "asio example wifi init"; - -/** - * Definition of ASIO main method, which is called after network initialized - */ -void asio_main(); - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void wifi_init_sta() -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config; - // zero out the config struct to ensure defaults are setup - memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); - // only copy ssid&password from example config - strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); - strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK(esp_wifi_start() ); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); -} - -extern "C" void app_main() -{ - //Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); - wifi_init_sta(); - - // Initialize VFS & UART so we can use std::cout/cin - setvbuf(stdin, NULL, _IONBF, 0); - setvbuf(stdout, NULL, _IONBF, 0); - /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, - 256, 0, 0, NULL, 0) ); - /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); - esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); - /* Move the caret to the beginning of the next line on '\n' */ - esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); - - // wait till we receive IP, so asio realated code can be started - xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); - - // network is ready, let's proceed with ASIO example - asio_main(); -} diff --git a/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild b/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild index ecbbf8ae9..795326db9 100644 --- a/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild +++ b/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild @@ -1,21 +1,9 @@ menu "Example Configuration" - config ESP_WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - - config ESP_WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - config EXAMPLE_PORT - string "asio example port number" - default "80" + string "Asio example port number" + default "2222" help - Port number used by ASIO example + Port number used by Asio example. endmenu diff --git a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp index 5b6607d73..06ac3fec9 100644 --- a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp +++ b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp @@ -13,6 +13,12 @@ #include "asio.hpp" +#include "protocol_examples_common.h" +#include "esp_event.h" +#include "tcpip_adapter.h" +#include "nvs_flash.h" + + using asio::ip::udp; class server @@ -32,6 +38,7 @@ public: { if (!ec && bytes_recvd > 0) { + data_[bytes_recvd] = 0; std::cout << data_ << std::endl; do_send(bytes_recvd); } @@ -59,8 +66,21 @@ private: char data_[max_length]; }; -void asio_main() +extern "C" void app_main() { + ESP_ERROR_CHECK(nvs_flash_init()); + tcpip_adapter_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + /* This helper function configures blocking UART I/O */ + ESP_ERROR_CHECK(example_configure_stdin_stdout()); + asio::io_context io_context; server s(io_context, std::atoi(CONFIG_EXAMPLE_PORT)); diff --git a/examples/protocols/asio/wifi_init/wifi_asio.cpp b/examples/protocols/asio/wifi_init/wifi_asio.cpp deleted file mode 100644 index b90ce26ae..000000000 --- a/examples/protocols/asio/wifi_init/wifi_asio.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* Common WiFi Init as STA for ASIO examples - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "driver/uart.h" -#include "esp_console.h" -#include "esp_vfs_dev.h" - -#include "lwip/err.h" -#include "lwip/sys.h" - -#include - -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID -#define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD - -/* FreeRTOS event group to signal when we are connected*/ -static EventGroupHandle_t wifi_event_group; - -/* The event group allows multiple bits for each event, - but we only care about one event - are we connected - to the AP with an IP? */ -const int WIFI_CONNECTED_BIT = BIT0; - -static const char *TAG = "asio example wifi init"; - -/** - * Definition of ASIO main method, which is called after network initialized - */ -void asio_main(); - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - break; - case SYSTEM_EVENT_STA_GOT_IP: - ESP_LOGI(TAG, "got ip:%s", - ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - case SYSTEM_EVENT_AP_STACONNECTED: - ESP_LOGI(TAG, "station:" MACSTR " join, AID=%d", - MAC2STR(event->event_info.sta_connected.mac), - event->event_info.sta_connected.aid); - break; - case SYSTEM_EVENT_AP_STADISCONNECTED: - ESP_LOGI(TAG, "station:" MACSTR "leave, AID=%d", - MAC2STR(event->event_info.sta_disconnected.mac), - event->event_info.sta_disconnected.aid); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); - break; - default: - break; - } - return ESP_OK; -} - -void wifi_init_sta() -{ - wifi_event_group = xEventGroupCreate(); - - tcpip_adapter_init(); - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) ); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - wifi_config_t wifi_config; - // zero out the config struct to ensure defaults are setup - memset(&wifi_config, 0, sizeof(wifi_sta_config_t)); - // only copy ssid&password from example config - strcpy((char*)(wifi_config.sta.ssid), EXAMPLE_ESP_WIFI_SSID); - strcpy((char*)(wifi_config.sta.password), EXAMPLE_ESP_WIFI_PASS); - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); - ESP_ERROR_CHECK(esp_wifi_start() ); - - ESP_LOGI(TAG, "wifi_init_sta finished."); - ESP_LOGI(TAG, "connect to ap SSID:%s password:%s", - EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); -} - -extern "C" void app_main() -{ - //Initialize NVS - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - ESP_LOGI(TAG, "ESP_WIFI_MODE_AP"); - wifi_init_sta(); - - // Initialize VFS & UART so we can use std::cout/cin - setvbuf(stdin, NULL, _IONBF, 0); - setvbuf(stdout, NULL, _IONBF, 0); - /* Install UART driver for interrupt-driven reads and writes */ - ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_CONSOLE_UART_NUM, - 256, 0, 0, NULL, 0) ); - /* Tell VFS to use UART driver */ - esp_vfs_dev_uart_use_driver(CONFIG_CONSOLE_UART_NUM); - esp_vfs_dev_uart_set_rx_line_endings(ESP_LINE_ENDINGS_CR); - /* Move the caret to the beginning of the next line on '\n' */ - esp_vfs_dev_uart_set_tx_line_endings(ESP_LINE_ENDINGS_CRLF); - - // wait till we receive IP, so asio realated code can be started - xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, 1, 1, portMAX_DELAY); - - // network is ready, let's proceed with ASIO example - asio_main(); -} From 3b49d1f559cd4b248fde93abc8fec630ff3e69e3 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Wed, 24 Apr 2019 15:02:25 +0200 Subject: [PATCH 12/60] Rename Kconfig options (root) * Original commit: espressif/esp-idf@c5000c83d250896fffbddd7a3991384ea0fc286d --- components/asio/port/include/esp_asio_config.h | 4 ++-- components/asio/port/include/esp_exception.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index accccad0d..f8617fcc9 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -18,9 +18,9 @@ // Enabling exceptions only when they are enabled in menuconfig // # include -# ifndef CONFIG_CXX_EXCEPTIONS +# ifndef CONFIG_COMPILER_CXX_EXCEPTIONS # define ASIO_NO_EXCEPTIONS -# endif // CONFIG_CXX_EXCEPTIONS +# endif // CONFIG_COMPILER_CXX_EXCEPTIONS // // LWIP compatifility inet and address macros/functions diff --git a/components/asio/port/include/esp_exception.h b/components/asio/port/include/esp_exception.h index 3c5c04375..a4a316013 100644 --- a/components/asio/port/include/esp_exception.h +++ b/components/asio/port/include/esp_exception.h @@ -18,7 +18,7 @@ // // This exception stub is enabled only if exceptions are disabled in menuconfig // -#if !defined(CONFIG_CXX_EXCEPTIONS) && defined (ASIO_NO_EXCEPTIONS) +#if !defined(CONFIG_COMPILER_CXX_EXCEPTIONS) && defined (ASIO_NO_EXCEPTIONS) #include "esp_log.h" @@ -34,6 +34,6 @@ void throw_exception(const Exception& e) abort(); } }} -#endif // CONFIG_CXX_EXCEPTIONS==1 && defined (ASIO_NO_EXCEPTIONS) +#endif // CONFIG_COMPILER_CXX_EXCEPTIONS==1 && defined (ASIO_NO_EXCEPTIONS) #endif // _ESP_EXCEPTION_H_ From 96d13293ab7e673fcfbb2dc1d8a80eabc77fc80c Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 30 Apr 2019 12:51:55 +0200 Subject: [PATCH 13/60] Rename Kconfig options (components/esp32) * Original commit: espressif/esp-idf@0ae53691bae8b841d35ed0d5a4d43e1f1a873d2a --- examples/protocols/asio/chat_client/sdkconfig.defaults | 2 +- examples/protocols/asio/chat_server/sdkconfig.defaults | 2 +- examples/protocols/asio/tcp_echo_server/sdkconfig.defaults | 2 +- examples/protocols/asio/udp_echo_server/sdkconfig.defaults | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/sdkconfig.defaults b/examples/protocols/asio/chat_client/sdkconfig.defaults index d99552e19..ce53d73ec 100644 --- a/examples/protocols/asio/chat_client/sdkconfig.defaults +++ b/examples/protocols/asio/chat_client/sdkconfig.defaults @@ -1 +1 @@ -CONFIG_MAIN_TASK_STACK_SIZE=8192 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 diff --git a/examples/protocols/asio/chat_server/sdkconfig.defaults b/examples/protocols/asio/chat_server/sdkconfig.defaults index d99552e19..ce53d73ec 100644 --- a/examples/protocols/asio/chat_server/sdkconfig.defaults +++ b/examples/protocols/asio/chat_server/sdkconfig.defaults @@ -1 +1 @@ -CONFIG_MAIN_TASK_STACK_SIZE=8192 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 diff --git a/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults b/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults index d99552e19..ce53d73ec 100644 --- a/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults +++ b/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults @@ -1 +1 @@ -CONFIG_MAIN_TASK_STACK_SIZE=8192 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 diff --git a/examples/protocols/asio/udp_echo_server/sdkconfig.defaults b/examples/protocols/asio/udp_echo_server/sdkconfig.defaults index d99552e19..ce53d73ec 100644 --- a/examples/protocols/asio/udp_echo_server/sdkconfig.defaults +++ b/examples/protocols/asio/udp_echo_server/sdkconfig.defaults @@ -1 +1 @@ -CONFIG_MAIN_TASK_STACK_SIZE=8192 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 From f82cbfde7ba6e90394ff18b0e9c4fa35fa084826 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Mon, 8 Jul 2019 09:16:06 +0800 Subject: [PATCH 14/60] ci: support to build esp32s2beta simple examples * Original commit: espressif/esp-idf@25ab8380c86d0c9c2fb5c9d091a9af4b7f160ca1 --- examples/protocols/asio/chat_client/CMakeLists.txt | 1 + examples/protocols/asio/chat_server/CMakeLists.txt | 1 + examples/protocols/asio/tcp_echo_server/CMakeLists.txt | 1 + examples/protocols/asio/udp_echo_server/CMakeLists.txt | 1 + 4 files changed, 4 insertions(+) diff --git a/examples/protocols/asio/chat_client/CMakeLists.txt b/examples/protocols/asio/chat_client/CMakeLists.txt index ddcc068ba..38033d943 100644 --- a/examples/protocols/asio/chat_client/CMakeLists.txt +++ b/examples/protocols/asio/chat_client/CMakeLists.txt @@ -6,5 +6,6 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_client) diff --git a/examples/protocols/asio/chat_server/CMakeLists.txt b/examples/protocols/asio/chat_server/CMakeLists.txt index 182f8d402..cd6a925f3 100644 --- a/examples/protocols/asio/chat_server/CMakeLists.txt +++ b/examples/protocols/asio/chat_server/CMakeLists.txt @@ -6,5 +6,6 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_server) diff --git a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt index 6bf8f4682..cc906e36c 100644 --- a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt @@ -6,5 +6,6 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_tcp_echo_server) diff --git a/examples/protocols/asio/udp_echo_server/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/CMakeLists.txt index 59493277c..0ebe12f2b 100644 --- a/examples/protocols/asio/udp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/CMakeLists.txt @@ -6,5 +6,6 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_udp_echo_server) From 9e83b1eb0eef12e60304a48d6b7c9e4d70655205 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Sun, 28 Apr 2019 15:38:23 +0800 Subject: [PATCH 15/60] components: use new component registration api * Original commit: espressif/esp-idf@9eccd7c0826d6cc2e9de59304d1e5f76c0063ccf --- components/asio/CMakeLists.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt index 43d428f8d..f2038278d 100644 --- a/components/asio/CMakeLists.txt +++ b/components/asio/CMakeLists.txt @@ -1,6 +1,3 @@ -set(COMPONENT_ADD_INCLUDEDIRS asio/asio/include port/include) -set(COMPONENT_SRCS "asio/asio/src/asio.cpp") - -set(COMPONENT_REQUIRES lwip) - -register_component() +idf_component_register(SRCS "asio/asio/src/asio.cpp" + INCLUDE_DIRS "asio/asio/include" "port/include" + REQUIRES lwip) From df51e60ac02a914a5900efd5c030f9cb35008fbb Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Sun, 28 Apr 2019 15:38:46 +0800 Subject: [PATCH 16/60] examples: use new component registration api * Original commit: espressif/esp-idf@6771eead80534c51efb2033c04769ef5893b4838 --- examples/protocols/asio/chat_client/main/CMakeLists.txt | 6 ++---- examples/protocols/asio/chat_server/main/CMakeLists.txt | 6 ++---- examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt | 6 ++---- examples/protocols/asio/udp_echo_server/main/CMakeLists.txt | 6 ++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/examples/protocols/asio/chat_client/main/CMakeLists.txt b/examples/protocols/asio/chat_client/main/CMakeLists.txt index 25419de4a..d92c9a8ae 100644 --- a/examples/protocols/asio/chat_client/main/CMakeLists.txt +++ b/examples/protocols/asio/chat_client/main/CMakeLists.txt @@ -1,4 +1,2 @@ -set(COMPONENT_SRCS "chat_client.cpp") -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() +idf_component_register(SRCS "chat_client.cpp" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/protocols/asio/chat_server/main/CMakeLists.txt b/examples/protocols/asio/chat_server/main/CMakeLists.txt index 7e44a9039..9042b223a 100644 --- a/examples/protocols/asio/chat_server/main/CMakeLists.txt +++ b/examples/protocols/asio/chat_server/main/CMakeLists.txt @@ -1,4 +1,2 @@ -set(COMPONENT_SRCS "chat_server.cpp") -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() +idf_component_register(SRCS "chat_server.cpp" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt index 04c3c94d9..ef518dc72 100644 --- a/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt @@ -1,4 +1,2 @@ -set(COMPONENT_SRCS "echo_server.cpp") -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() +idf_component_register(SRCS "echo_server.cpp" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt index cd24937be..c7a9e3575 100644 --- a/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt @@ -1,4 +1,2 @@ -set(COMPONENT_SRCS "udp_echo_server.cpp") -set(COMPONENT_ADD_INCLUDEDIRS ".") - -register_component() +idf_component_register(SRCS "udp_echo_server.cpp" + INCLUDE_DIRS ".") \ No newline at end of file From c1176ccdcc1e33533c93c26aae22fe9562f51332 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 23 Jun 2019 11:54:31 +1000 Subject: [PATCH 17/60] build system: Use CMake-based build system as default when describing commands * Original commit: espressif/esp-idf@47bbb107a8deaa80692ebc3b9369ae0618c3bc56 --- examples/protocols/asio/chat_client/README.md | 8 ++++---- examples/protocols/asio/chat_server/README.md | 6 +++--- examples/protocols/asio/tcp_echo_server/README.md | 6 +++--- examples/protocols/asio/udp_echo_server/README.md | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/protocols/asio/chat_client/README.md b/examples/protocols/asio/chat_client/README.md index 951afad53..edc4c7189 100644 --- a/examples/protocols/asio/chat_client/README.md +++ b/examples/protocols/asio/chat_client/README.md @@ -5,15 +5,15 @@ Simple Asio chat client using WiFi STA or Ethernet. ## Example workflow - Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio chat client connects to the corresponding server whose port number and IP are defined through `make menuconfig`. -- Chat client receives all messages from other chat clients, also it sends message received from stdin using `make monitor`. +- Asio chat client connects to the corresponding server whose port number and IP are defined through the project configuration menu. +- Chat client receives all messages from other chat clients, also it sends message received from stdin using `idf.py monitor`. ## Running the example -- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - Set server IP address and port number in menuconfig, "Example configuration". - Start chat server either on host machine or as another ESP device running chat_server example. -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. - Wait for the board to connect to WiFi or Ethernet. - Receive and send messages to/from other clients on stdin/stdout via serial terminal. diff --git a/examples/protocols/asio/chat_server/README.md b/examples/protocols/asio/chat_server/README.md index e043cba32..ec8b3e76e 100644 --- a/examples/protocols/asio/chat_server/README.md +++ b/examples/protocols/asio/chat_server/README.md @@ -5,14 +5,14 @@ Simple Asio chat server using WiFi STA or Ethernet. ## Example workflow - Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio chat server is started on port number defined through `make menuconfig`. +- Asio chat server is started on port number defined through the project configuration. - Chat server echoes a message (received from any client) to all connected clients. ## Running the example -- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Open project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - Set server port number in menuconfig, "Example configuration". -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. - Wait for the board to connect to WiFi or Ethernet (note the IP address). - Connect to the server using multiple clients, for example using any option below. - build and run asi chat client on your host machine diff --git a/examples/protocols/asio/tcp_echo_server/README.md b/examples/protocols/asio/tcp_echo_server/README.md index f672027ef..b2443a245 100644 --- a/examples/protocols/asio/tcp_echo_server/README.md +++ b/examples/protocols/asio/tcp_echo_server/README.md @@ -5,14 +5,14 @@ Simple Asio TCP echo server using WiFi STA or Ethernet. ## Example workflow - Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio TCP server is started on port number defined through `make menuconfig`. +- Asio TCP server is started on port number defined through the project configuration. - Server receives and echoes back messages transmitted from client. ## Running the example -- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - Set server port number in menuconfig, "Example configuration". -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. - Wait for the board to connect to WiFi or Ethernet (note the IP address). - You can now send a TCP message and check it is repeated, for example using netcat `nc IP PORT`. diff --git a/examples/protocols/asio/udp_echo_server/README.md b/examples/protocols/asio/udp_echo_server/README.md index cc69fee08..cc8a67e66 100644 --- a/examples/protocols/asio/udp_echo_server/README.md +++ b/examples/protocols/asio/udp_echo_server/README.md @@ -5,14 +5,14 @@ Simple Asio UDP echo server using WiFi STA or Ethernet. ## Example workflow - Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio UDP server is started on port number defined through `make menuconfig` +- Asio UDP server is started on port number defined through the project configuration - Server receives and echoes back messages transmitted from client ## Running the example -- Run `make menuconfig` to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +- Open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. - Set server port number in menuconfig, "Example configuration". -- Run `make flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. - Wait for the board to connect to WiFi or Ethernet (note the IP address). - You can now send a UDP message and check it is repeated, for example using netcat `nc -u IP PORT`. From f3754a36835675aec53cb7c8a28dfaa587cc9d66 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 2 Aug 2019 09:01:20 +0530 Subject: [PATCH 18/60] examples: change default build instructions in docs to CMake * Original commit: espressif/esp-idf@e7dba7d7bc6218eea440dfe6f55592b8c21f6083 --- examples/protocols/asio/chat_client/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/asio/chat_client/README.md b/examples/protocols/asio/chat_client/README.md index edc4c7189..bcc2bd4d5 100644 --- a/examples/protocols/asio/chat_client/README.md +++ b/examples/protocols/asio/chat_client/README.md @@ -6,7 +6,7 @@ Simple Asio chat client using WiFi STA or Ethernet. - Wi-Fi or Ethernet connection is established, and IP address is obtained. - Asio chat client connects to the corresponding server whose port number and IP are defined through the project configuration menu. -- Chat client receives all messages from other chat clients, also it sends message received from stdin using `idf.py monitor`. +- Chat client receives all messages from other chat clients, also it sends message received from stdin using `idf.py -p PORT monitor`. ## Running the example From a14331ad0115e449928c9d921fe858124c69f582 Mon Sep 17 00:00:00 2001 From: Anton Maklakov Date: Tue, 16 Jul 2019 16:33:30 +0700 Subject: [PATCH 19/60] tools: Mass fixing of empty prototypes (for -Wstrict-prototypes) * Original commit: espressif/esp-idf@afbaf74007e89d016dbade4072bf2e7a3874139a --- examples/protocols/asio/chat_client/main/chat_client.cpp | 2 +- examples/protocols/asio/chat_server/main/chat_server.cpp | 2 +- examples/protocols/asio/tcp_echo_server/main/echo_server.cpp | 2 +- .../protocols/asio/udp_echo_server/main/udp_echo_server.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/main/chat_client.cpp b/examples/protocols/asio/chat_client/main/chat_client.cpp index d4a111057..0b0f7097f 100644 --- a/examples/protocols/asio/chat_client/main/chat_client.cpp +++ b/examples/protocols/asio/chat_client/main/chat_client.cpp @@ -134,7 +134,7 @@ private: void read_line(char * line, int max_chars); -extern "C" void app_main() +extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); tcpip_adapter_init(); diff --git a/examples/protocols/asio/chat_server/main/chat_server.cpp b/examples/protocols/asio/chat_server/main/chat_server.cpp index 56a447e05..c1838b53f 100644 --- a/examples/protocols/asio/chat_server/main/chat_server.cpp +++ b/examples/protocols/asio/chat_server/main/chat_server.cpp @@ -202,7 +202,7 @@ private: //---------------------------------------------------------------------- -extern "C" void app_main() +extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); tcpip_adapter_init(); diff --git a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp index 008ec6ed7..d1ed69e05 100644 --- a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp +++ b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp @@ -84,7 +84,7 @@ private: }; -extern "C" void app_main() +extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); tcpip_adapter_init(); diff --git a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp index 06ac3fec9..68adf4148 100644 --- a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp +++ b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp @@ -66,7 +66,7 @@ private: char data_[max_length]; }; -extern "C" void app_main() +extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); tcpip_adapter_init(); From ee6dbbfeaa4ddda3886c31b50d4ecafbf26e4f54 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Thu, 29 Aug 2019 17:54:14 +0800 Subject: [PATCH 20/60] ci: limit example test to ESP32s * Original commit: espressif/esp-idf@63329b169bd1a3bc153bf37a7187f4ea17012852 --- examples/protocols/asio/chat_client/asio_chat_client_test.py | 3 ++- examples/protocols/asio/chat_server/asio_chat_server_test.py | 3 ++- .../protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 3 ++- .../protocols/asio/udp_echo_server/asio_udp_server_test.py | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index 3b141c7d1..f5581796d 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -7,6 +7,7 @@ import time try: import IDF + from IDF.IDFDUT import ESP32DUT except ImportError: # this is a test case write with tiny-test-fw. # to run test cases outside tiny-test-fw, @@ -69,7 +70,7 @@ def test_examples_protocol_asio_chat_client(env, extra_data): global g_client_response global g_msg_to_client test_msg = "ABC" - dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client") + dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client", dut_class=ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_chat_client.bin") bin_size = os.path.getsize(binary_file) diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index ea4702c4e..5d53a8946 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -6,6 +6,7 @@ import socket try: import IDF + from IDF.IDFDUT import ESP32DUT except ImportError: # this is a test case write with tiny-test-fw. # to run test cases outside tiny-test-fw, @@ -27,7 +28,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): 4. Test evaluates received test message from server """ test_msg = b" 4ABC\n" - dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server") + dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server", dut_class=ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") bin_size = os.path.getsize(binary_file) diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index 2cdfd45ae..aeb7faced 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -6,6 +6,7 @@ import socket try: import IDF + from IDF.IDFDUT import ESP32DUT except ImportError: # this is a test case write with tiny-test-fw. # to run test cases outside tiny-test-fw, @@ -29,7 +30,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): 5. Test evaluates received test message on server stdout """ test_msg = b"echo message from client to server" - dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server") + dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server", dut_class=ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") bin_size = os.path.getsize(binary_file) diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index dc2cc78a8..dac320068 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -6,6 +6,7 @@ import socket try: import IDF + from IDF.IDFDUT import ESP32DUT except ImportError: # this is a test case write with tiny-test-fw. # to run test cases outside tiny-test-fw, @@ -29,7 +30,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): 5. Test evaluates received test message on server stdout """ test_msg = b"echo message from client to server" - dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server") + dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server", dut_class=ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") bin_size = os.path.getsize(binary_file) From ff7d214f9c17b60f450fef8b44ba95c2846509b7 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Fri, 1 Nov 2019 09:54:34 +0800 Subject: [PATCH 21/60] ASIO: fixed undefined ref to atomic functions and enabled examples for CI (esp32s2beta) Implemented the atomic functions needed to compile and link the asio examples on esp32s2beta. * Original commit: espressif/esp-idf@845003a1c3c14bfd9309d007cfe209a5b933b408 --- examples/protocols/asio/chat_client/CMakeLists.txt | 1 - examples/protocols/asio/chat_server/CMakeLists.txt | 1 - examples/protocols/asio/tcp_echo_server/CMakeLists.txt | 1 - examples/protocols/asio/udp_echo_server/CMakeLists.txt | 1 - 4 files changed, 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/CMakeLists.txt b/examples/protocols/asio/chat_client/CMakeLists.txt index 38033d943..ddcc068ba 100644 --- a/examples/protocols/asio/chat_client/CMakeLists.txt +++ b/examples/protocols/asio/chat_client/CMakeLists.txt @@ -6,6 +6,5 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) -set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_client) diff --git a/examples/protocols/asio/chat_server/CMakeLists.txt b/examples/protocols/asio/chat_server/CMakeLists.txt index cd6a925f3..182f8d402 100644 --- a/examples/protocols/asio/chat_server/CMakeLists.txt +++ b/examples/protocols/asio/chat_server/CMakeLists.txt @@ -6,6 +6,5 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) -set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat_server) diff --git a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt index cc906e36c..6bf8f4682 100644 --- a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt @@ -6,6 +6,5 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) -set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_tcp_echo_server) diff --git a/examples/protocols/asio/udp_echo_server/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/CMakeLists.txt index 0ebe12f2b..59493277c 100644 --- a/examples/protocols/asio/udp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/CMakeLists.txt @@ -6,6 +6,5 @@ cmake_minimum_required(VERSION 3.5) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) -set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_udp_echo_server) From 98dfb691b6681ee14800718ddf2b2569cd3043df Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 8 Nov 2019 14:56:25 +0100 Subject: [PATCH 22/60] asio: fix asio test code to start the test after ip address received from common example code Previously set to wait until IP address got from tcpip_adapter, but since common example connect code blocks until both IP4 and IPv6 address received it could happen that test code might have started connection to the ASIO counter-part while ESP32 still waiting for IPv6 address * Original commit: espressif/esp-idf@208feef3c99310dc6170a6fe87ce460a8637f7a0 --- examples/protocols/asio/chat_client/asio_chat_client_test.py | 2 +- examples/protocols/asio/chat_server/asio_chat_server_test.py | 2 +- examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 2 +- examples/protocols/asio/udp_echo_server/asio_udp_server_test.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index f5581796d..4325806a3 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -82,7 +82,7 @@ def test_examples_protocol_asio_chat_client(env, extra_data): thread1.start() # 2. start the dut test and wait till client gets IP address dut1.start_app() - dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) # 3. send host's IP to the client i.e. the `dut1` dut1.write(host_ip) # 4. client `dut1` should receive a message diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 5d53a8946..ccdd4a557 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -37,7 +37,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + data = dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index aeb7faced..d5ee5cf07 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -39,7 +39,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + data = dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index dac320068..726a39f4f 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -39,7 +39,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" sta ip: ([^,]+),"), timeout=30) + data = dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) cli.settimeout(30) From 54e3a859837e0245a985bb8a03357249b3a61e44 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Wed, 4 Sep 2019 13:58:29 +0200 Subject: [PATCH 23/60] esp_netif and examples: using wifi driver handle, update examples and tests to pass the CI * Original commit: espressif/esp-idf@3a19bf055d62d7cea4c7a62c8cc5f3b6a7e25b7c --- examples/protocols/asio/chat_client/main/chat_client.cpp | 3 +-- examples/protocols/asio/chat_server/main/chat_server.cpp | 3 +-- examples/protocols/asio/tcp_echo_server/main/echo_server.cpp | 3 +-- .../protocols/asio/udp_echo_server/main/udp_echo_server.cpp | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/examples/protocols/asio/chat_client/main/chat_client.cpp b/examples/protocols/asio/chat_client/main/chat_client.cpp index 0b0f7097f..10ab860c9 100644 --- a/examples/protocols/asio/chat_client/main/chat_client.cpp +++ b/examples/protocols/asio/chat_client/main/chat_client.cpp @@ -16,7 +16,6 @@ #include "chat_message.hpp" #include "protocol_examples_common.h" #include "esp_event.h" -#include "tcpip_adapter.h" #include "nvs_flash.h" using asio::ip::tcp; @@ -137,7 +136,7 @@ void read_line(char * line, int max_chars); extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); - tcpip_adapter_init(); + esp_netif_init(); ESP_ERROR_CHECK(esp_event_loop_create_default()); /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. diff --git a/examples/protocols/asio/chat_server/main/chat_server.cpp b/examples/protocols/asio/chat_server/main/chat_server.cpp index c1838b53f..edcc1278c 100644 --- a/examples/protocols/asio/chat_server/main/chat_server.cpp +++ b/examples/protocols/asio/chat_server/main/chat_server.cpp @@ -19,7 +19,6 @@ #include "chat_message.hpp" #include "protocol_examples_common.h" #include "esp_event.h" -#include "tcpip_adapter.h" #include "nvs_flash.h" @@ -205,7 +204,7 @@ private: extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); - tcpip_adapter_init(); + esp_netif_init(); ESP_ERROR_CHECK(esp_event_loop_create_default()); /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. diff --git a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp index d1ed69e05..1770fa55e 100644 --- a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp +++ b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp @@ -3,7 +3,6 @@ #include #include "protocol_examples_common.h" #include "esp_event.h" -#include "tcpip_adapter.h" #include "nvs_flash.h" using asio::ip::tcp; @@ -87,7 +86,7 @@ private: extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); - tcpip_adapter_init(); + esp_netif_init(); ESP_ERROR_CHECK(esp_event_loop_create_default()); /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. diff --git a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp index 68adf4148..14eef948e 100644 --- a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp +++ b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp @@ -15,7 +15,6 @@ #include "protocol_examples_common.h" #include "esp_event.h" -#include "tcpip_adapter.h" #include "nvs_flash.h" @@ -69,7 +68,7 @@ private: extern "C" void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); - tcpip_adapter_init(); + esp_netif_init(); ESP_ERROR_CHECK(esp_event_loop_create_default()); /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. From 4e4ab0908dcbf88ef576f98eb7ee1ec479502a5c Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Wed, 27 Nov 2019 11:58:07 +0800 Subject: [PATCH 24/60] test: update example and unit tests with new import roles: tiny_test_fw is a python package now. import it using normal way. * Original commit: espressif/esp-idf@c906e2afee9455bf55b7b163815dce69de766879 --- .../asio/chat_client/asio_chat_client_test.py | 22 ++++------------- .../asio/chat_server/asio_chat_server_test.py | 23 ++++-------------- .../tcp_echo_server/asio_tcp_server_test.py | 24 ++++--------------- .../udp_echo_server/asio_udp_server_test.py | 24 ++++--------------- 4 files changed, 20 insertions(+), 73 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index 4325806a3..d59b459c7 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -1,22 +1,10 @@ import re import os -import sys import socket from threading import Thread import time -try: - import IDF - from IDF.IDFDUT import ESP32DUT -except ImportError: - # this is a test case write with tiny-test-fw. - # to run test cases outside tiny-test-fw, - # we need to set environment variable `TEST_FW_PATH`, - # then get and insert `TEST_FW_PATH` to sys path before import FW module - test_fw_path = os.getenv("TEST_FW_PATH") - if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - import IDF +import ttfw_idf global g_client_response global g_msg_to_client @@ -56,7 +44,7 @@ def chat_server_sketch(my_ip): print("server closed") -@IDF.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_asio_chat_client(env, extra_data): """ steps: | @@ -70,12 +58,12 @@ def test_examples_protocol_asio_chat_client(env, extra_data): global g_client_response global g_msg_to_client test_msg = "ABC" - dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client", dut_class=ESP32DUT) + dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client", dut_class=ttfw_idf.ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_chat_client.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_chat_client_size", "{}KB".format(bin_size // 1024)) - IDF.check_performance("asio_chat_client_size", bin_size // 1024) + ttfw_idf.log_performance("asio_chat_client_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.check_performance("asio_chat_client_size", bin_size // 1024) # 1. start a tcp server on the host host_ip = get_my_ip() thread1 = Thread(target=chat_server_sketch, args=(host_ip,)) diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index ccdd4a557..2bfa026fc 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -1,24 +1,11 @@ import re import os -import sys import socket - -try: - import IDF - from IDF.IDFDUT import ESP32DUT -except ImportError: - # this is a test case write with tiny-test-fw. - # to run test cases outside tiny-test-fw, - # we need to set environment variable `TEST_FW_PATH`, - # then get and insert `TEST_FW_PATH` to sys path before import FW module - test_fw_path = os.getenv("TEST_FW_PATH") - if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - import IDF +import ttfw_idf -@IDF.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_asio_chat_server(env, extra_data): """ steps: | @@ -28,12 +15,12 @@ def test_examples_protocol_asio_chat_server(env, extra_data): 4. Test evaluates received test message from server """ test_msg = b" 4ABC\n" - dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server", dut_class=ESP32DUT) + dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server", dut_class=ttfw_idf.ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size // 1024)) - IDF.check_performance("asio_chat_server_size", bin_size // 1024) + ttfw_idf.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.check_performance("asio_chat_server_size", bin_size // 1024) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index d5ee5cf07..b7dc16817 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -1,25 +1,11 @@ import re import os -import sys import socket - -try: - import IDF - from IDF.IDFDUT import ESP32DUT -except ImportError: - # this is a test case write with tiny-test-fw. - # to run test cases outside tiny-test-fw, - # we need to set environment variable `TEST_FW_PATH`, - # then get and insert `TEST_FW_PATH` to sys path before import FW module - test_fw_path = os.getenv("TEST_FW_PATH") - if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - - import IDF +import ttfw_idf -@IDF.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_asio_tcp_server(env, extra_data): """ steps: | @@ -30,12 +16,12 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): 5. Test evaluates received test message on server stdout """ test_msg = b"echo message from client to server" - dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server", dut_class=ESP32DUT) + dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server", dut_class=ttfw_idf.ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) - IDF.check_performance("asio_tcp_echo_server_size", bin_size // 1024) + ttfw_idf.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.check_performance("asio_tcp_echo_server_size", bin_size // 1024) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 726a39f4f..3b6d0bff9 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -1,25 +1,11 @@ import re import os -import sys import socket - -try: - import IDF - from IDF.IDFDUT import ESP32DUT -except ImportError: - # this is a test case write with tiny-test-fw. - # to run test cases outside tiny-test-fw, - # we need to set environment variable `TEST_FW_PATH`, - # then get and insert `TEST_FW_PATH` to sys path before import FW module - test_fw_path = os.getenv("TEST_FW_PATH") - if test_fw_path and test_fw_path not in sys.path: - sys.path.insert(0, test_fw_path) - - import IDF +import ttfw_idf -@IDF.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag="Example_WIFI") def test_examples_protocol_asio_udp_server(env, extra_data): """ steps: | @@ -30,12 +16,12 @@ def test_examples_protocol_asio_udp_server(env, extra_data): 5. Test evaluates received test message on server stdout """ test_msg = b"echo message from client to server" - dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server", dut_class=ESP32DUT) + dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server", dut_class=ttfw_idf.ESP32DUT) # check and log bin size binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") bin_size = os.path.getsize(binary_file) - IDF.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) - IDF.check_performance("asio_udp_echo_server_size", bin_size // 1024) + ttfw_idf.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.check_performance("asio_udp_echo_server_size", bin_size // 1024) # 1. start test dut1.start_app() # 2. get the server IP address From 919091766db314894a8c57db46995b759598fe05 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 7 Nov 2019 12:07:44 +0100 Subject: [PATCH 25/60] asio: updated ASIO port to use latest asio and esp-idf features closes https://github.com/espressif/esp-idf/issues/4296 * Original commit: espressif/esp-idf@13d603e486624380d49f2e89614b10425c208d14 --- components/asio/asio | 2 +- .../asio/port/include/esp_asio_config.h | 12 +++++------ docs/en/api-reference/protocols/asio.rst | 21 +++++++++---------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/components/asio/asio b/components/asio/asio index 55efc179b..3b66e5b05 160000 --- a/components/asio/asio +++ b/components/asio/asio @@ -1 +1 @@ -Subproject commit 55efc179b76139c8f9b44bf22a4aba4803f7a7bd +Subproject commit 3b66e5b051381fb70de9c2791df70a06181c64e3 diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index f8617fcc9..750f4cbe3 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -22,8 +22,12 @@ # define ASIO_NO_EXCEPTIONS # endif // CONFIG_COMPILER_CXX_EXCEPTIONS +# ifndef CONFIG_COMPILER_RTTI +# define ASIO_NO_TYPEID +# endif // CONFIG_COMPILER_RTTI + // -// LWIP compatifility inet and address macros/functions +// LWIP compatibility inet and address macros/functions // # define LWIP_COMPAT_SOCKET_INET 1 # define LWIP_COMPAT_SOCKET_ADDR 1 @@ -34,12 +38,6 @@ # define ASIO_DISABLE_SERIAL_PORT # define ASIO_SEPARATE_COMPILATION # define ASIO_STANDALONE -# define ASIO_NO_TYPEID -# define ASIO_DISABLE_SIGNAL # define ASIO_HAS_PTHREADS -# define ASIO_DISABLE_EPOLL -# define ASIO_DISABLE_EVENTFD -# define ASIO_DISABLE_SIGNAL -# define ASIO_DISABLE_SIGACTION #endif // _ESP_ASIO_CONFIG_H_ diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index 635ef053f..dcf704131 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -15,18 +15,17 @@ Supported features ^^^^^^^^^^^^^^^^^^ ESP platform port currently supports only network asynchronous socket operations; does not support serial port and ssl. Internal asio settings for ESP include -- EXCEPTIONS: Supported, choice in menuconfig -- SIGNAL, SIGACTION: Not supported -- EPOLL, EVENTFD: Not supported -- TYPEID: Disabled by default, but supported in toolchain and asio (provided stdlib recompiled with -frtti) + +- EXCEPTIONS are enabled in ASIO if enabled in menuconfig +- TYPEID is enabled in ASIO if enabled in menuconfig Application Example ------------------- -ESP examples are based on standard asio examples `examples/protocols/asio`: -- udp_echo_server -- tcp_echo_server -- chat_client -- chat_server +ESP examples are based on standard asio :example:`examples/protocols/asio`: + +- :example:`examples/protocols/asio/udp_echo_server` +- :example:`examples/protocols/asio/tcp_echo_server` +- :example:`examples/protocols/asio/chat_client` +- :example:`examples/protocols/asio/chat_server` + Please refer to the specific example README.md for details - - From 131613c5cc957933b6a88ebe8d469d39ab11be0e Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 20 Jan 2020 21:06:06 +0800 Subject: [PATCH 26/60] doc: fix broken example links * Original commit: espressif/esp-idf@f2cb6bd4b6758abe5d522e8ce593ed170a85c635 --- docs/en/api-reference/protocols/asio.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index dcf704131..14f39ae48 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -21,11 +21,11 @@ Internal asio settings for ESP include Application Example ------------------- -ESP examples are based on standard asio :example:`examples/protocols/asio`: +ESP examples are based on standard asio :example:`protocols/asio`: -- :example:`examples/protocols/asio/udp_echo_server` -- :example:`examples/protocols/asio/tcp_echo_server` -- :example:`examples/protocols/asio/chat_client` -- :example:`examples/protocols/asio/chat_server` +- :example:`protocols/asio/udp_echo_server` +- :example:`protocols/asio/tcp_echo_server` +- :example:`protocols/asio/chat_client` +- :example:`protocols/asio/chat_server` Please refer to the specific example README.md for details From 789670e8c516bb7f69873ab926d0b8377d498dc8 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 28 Feb 2020 16:12:11 +0100 Subject: [PATCH 27/60] Add multi-target support for performance tests * Original commit: espressif/esp-idf@15884eccf293dde1916dbc663d6a53758ff5dab0 --- examples/protocols/asio/chat_client/asio_chat_client_test.py | 2 +- examples/protocols/asio/chat_server/asio_chat_server_test.py | 2 +- examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 2 +- examples/protocols/asio/udp_echo_server/asio_udp_server_test.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index d59b459c7..04c1773a0 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -63,7 +63,7 @@ def test_examples_protocol_asio_chat_client(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_chat_client.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_chat_client_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_chat_client_size", bin_size // 1024) + ttfw_idf.check_performance("asio_chat_client_size", bin_size // 1024, dut1.TARGET) # 1. start a tcp server on the host host_ip = get_my_ip() thread1 = Thread(target=chat_server_sketch, args=(host_ip,)) diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 2bfa026fc..e319c4467 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -20,7 +20,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_chat_server_size", bin_size // 1024) + ttfw_idf.check_performance("asio_chat_server_size", bin_size // 1024, dut1.TARGET) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index b7dc16817..bc5185af2 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -21,7 +21,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_tcp_echo_server_size", bin_size // 1024) + ttfw_idf.check_performance("asio_tcp_echo_server_size", bin_size // 1024, dut1.TARGET) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 3b6d0bff9..9eef125f4 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -21,7 +21,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_udp_echo_server_size", bin_size // 1024) + ttfw_idf.check_performance("asio_udp_echo_server_size", bin_size // 1024, dut1.TARGET) # 1. start test dut1.start_app() # 2. get the server IP address From dab12309e26104dac1a07312e647a3347b0c014c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 5 Jun 2020 16:17:01 +0200 Subject: [PATCH 28/60] asio: Basic SSL/TLS support in asio port for ESP platform This port employs IDF port of OpenSSL for most common features, others are discouraged or not supported. The port also introduces several stubs for OpenSSL functions which ASIO needs to get compiled and linked. Upstream ASIO supports WolfSSL as SSL/TLS stack, as well, which is another option for SSL support in ASIO on ESP platform. * Original commit: espressif/esp-idf@9459c0dd432fdd0fccb49ea65bb5c72d1849e1ba --- components/asio/CMakeLists.txt | 4 +- components/asio/asio | 2 +- components/asio/component.mk | 3 +- components/asio/port/include/openssl/conf.h | 20 ++ .../include/openssl/esp_asio_openssl_stubs.h | 185 ++++++++++++++++++ .../asio/port/src/esp_asio_openssl_stubs.c | 60 ++++++ docs/en/api-reference/protocols/asio.rst | 14 +- 7 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 components/asio/port/include/openssl/conf.h create mode 100644 components/asio/port/include/openssl/esp_asio_openssl_stubs.h create mode 100644 components/asio/port/src/esp_asio_openssl_stubs.c diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt index f2038278d..b55dc56ab 100644 --- a/components/asio/CMakeLists.txt +++ b/components/asio/CMakeLists.txt @@ -1,3 +1,5 @@ idf_component_register(SRCS "asio/asio/src/asio.cpp" + "asio/asio/src/asio_ssl.cpp" + "port/src/esp_asio_openssl_stubs.c" INCLUDE_DIRS "asio/asio/include" "port/include" - REQUIRES lwip) + REQUIRES lwip openssl) diff --git a/components/asio/asio b/components/asio/asio index 3b66e5b05..61702cd13 160000 --- a/components/asio/asio +++ b/components/asio/asio @@ -1 +1 @@ -Subproject commit 3b66e5b051381fb70de9c2791df70a06181c64e3 +Subproject commit 61702cd13be0b8c9800a9793daae72768ede26af diff --git a/components/asio/component.mk b/components/asio/component.mk index e024df3f3..0c2919e24 100644 --- a/components/asio/component.mk +++ b/components/asio/component.mk @@ -1,6 +1,5 @@ COMPONENT_ADD_INCLUDEDIRS := asio/asio/include port/include COMPONENT_PRIV_INCLUDEDIRS := private_include -COMPONENT_SRCDIRS := asio/asio/src -COMPONENT_OBJEXCLUDE := asio/asio/src/asio_ssl.o +COMPONENT_SRCDIRS := asio/asio/src port/src COMPONENT_SUBMODULES += asio diff --git a/components/asio/port/include/openssl/conf.h b/components/asio/port/include/openssl/conf.h new file mode 100644 index 000000000..9c46bd14a --- /dev/null +++ b/components/asio/port/include/openssl/conf.h @@ -0,0 +1,20 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_ASIO_OPENSSL_CONF_H +#define _ESP_ASIO_OPENSSL_CONF_H + +#include "openssl/esp_asio_openssl_stubs.h" + +#endif // _ESP_ASIO_OPENSSL_CONF_H diff --git a/components/asio/port/include/openssl/esp_asio_openssl_stubs.h b/components/asio/port/include/openssl/esp_asio_openssl_stubs.h new file mode 100644 index 000000000..611b4e784 --- /dev/null +++ b/components/asio/port/include/openssl/esp_asio_openssl_stubs.h @@ -0,0 +1,185 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_ASIO_OPENSSL_STUBS_H +#define _ESP_ASIO_OPENSSL_STUBS_H + +#include "internal/ssl_x509.h" +#include "internal/ssl_pkey.h" +#include "mbedtls/pem.h" +#include + +/** + * @note This header contains openssl API which are NOT implemented, and are only provided + * as stubs or no-operations to get the ASIO library compiled and working with most + * practical use cases as an embedded application on ESP platform + */ + +#ifdef __cplusplus +extern "C" { +#endif + +// The most applicable OpenSSL version wrtt ASIO usage +#define OPENSSL_VERSION_NUMBER 0x10100001L +// SSLv2 methods not supported +// OpenSSL port supports: TLS_ANY, TLS_1, TLS_1_1, TLS_1_2, SSL_3 +#define OPENSSL_NO_SSL2 +#define SSL2_VERSION 0x0002 + +#define SSL_R_SHORT_READ 219 +#define SSL_OP_ALL 0 +#define SSL_OP_SINGLE_DH_USE 0 +//#define OPENSSL_VERSION_NUMBER 0x10001000L +#define SSL_OP_NO_COMPRESSION 0 +//#define LIBRESSL_VERSION_NUMBER 1 +//#define PEM_R_NO_START_LINE 110 +// Translates mbedTLS PEM parse error, used by ASIO +#define PEM_R_NO_START_LINE -MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT + +#define SSL_OP_NO_SSLv2 0x01000000L +#define SSL_OP_NO_SSLv3 0x02000000L +#define SSL_OP_NO_TLSv1 0x04000000L + +#define X509_FILETYPE_PEM 1 +#define X509_FILETYPE_ASN1 2 +#define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 +#define SSL_FILETYPE_PEM X509_FILETYPE_PEM + +#define NID_subject_alt_name 85 + +#define SSL_MODE_RELEASE_BUFFERS 0x00000000L +#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L +#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L + +#define GEN_DNS 2 +#define GEN_IPADD 7 +#define V_ASN1_OCTET_STRING 4 +#define V_ASN1_IA5STRING 22 +#define NID_commonName 13 + +#define SSL_CTX_get_app_data(ctx) ((void*)SSL_CTX_get_ex_data(ctx, 0)) + +/** +* @brief Frees DH object -- not implemented +* +* Current implementation calls SSL_ASSERT +* +* @param r DH object +*/ +void DH_free(DH *r); + +/** + * @brief Frees GENERAL_NAMES -- not implemented + * + * Current implementation calls SSL_ASSERT + * + * @param r GENERAL_NAMES object + */ +void GENERAL_NAMES_free(GENERAL_NAMES * gens); + +/** + * @brief Returns subject name from X509 -- not implemented + * + * Current implementation calls SSL_ASSERT + * + * @param r X509 object + */ +X509_NAME *X509_get_subject_name(X509 *a); + +/** + * @brief API provaded as declaration only + * + */ +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); + +/** + * @brief API provaded as declaration only + * + */ +int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos); + +/** + * @brief API provaded as declaration only + * + */ +X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); + +/** + * @brief API provaded as declaration only + * + */ +ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); + +/** + * @brief API provaded as declaration only + * + */ +void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); + +/** + * @brief API provaded as declaration only + * + */ +X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); + +/** + * @brief Reads DH params from a bio object -- not implemented + * + * Current implementation calls SSL_ASSERT + */ +DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u); + +/** + * @brief API provaded as declaration only + * + */ +void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); + +/** + * @brief Sets DH params to ssl ctx -- not implemented + * + * Current implementation calls SSL_ASSERT + */ +int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh); + +/** + * @brief Sets SSL mode -- not implemented + * + * Current implementation is no-op + */ +uint32_t SSL_set_mode(SSL *ssl, uint32_t mode); + +/** + * @brief API provaded as declaration only + * + */ +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data); + +/** + * @brief API provaded as declaration only + * + */ +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); + +/** + * @brief Clears any existing chain associated with the current certificate of ctx. + * + */ +int SSL_CTX_clear_chain_certs(SSL_CTX *ctx); + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* _ESP_ASIO_OPENSSL_STUBS_H */ diff --git a/components/asio/port/src/esp_asio_openssl_stubs.c b/components/asio/port/src/esp_asio_openssl_stubs.c new file mode 100644 index 000000000..9fdf53d0d --- /dev/null +++ b/components/asio/port/src/esp_asio_openssl_stubs.c @@ -0,0 +1,60 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "esp_asio_config.h" +#include "internal/ssl_dbg.h" +#include "openssl/esp_asio_openssl_stubs.h" + +// Unsupported features as macros to make the assertions more readable +#define ESP_OPENSSL_DH_IS_SUPPORTED 0 +#define ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED 0 + +void DH_free (DH *r) +{ + SSL_ASSERT3(ESP_OPENSSL_DH_IS_SUPPORTED); +} + +DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) +{ + SSL_ASSERT2(ESP_OPENSSL_DH_IS_SUPPORTED); + return NULL; +} + +int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) +{ + SSL_ASSERT1(ESP_OPENSSL_DH_IS_SUPPORTED); + return -1; +} + +void GENERAL_NAMES_free(GENERAL_NAMES * gens) +{ + SSL_ASSERT3(ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED); +} + +X509_NAME *X509_get_subject_name(X509 *a) +{ + SSL_ASSERT2(ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED); + return NULL; +} + +uint32_t SSL_set_mode(SSL *ssl, uint32_t mode) +{ + return 0; +} + +int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) +{ + return 1; +} diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index 14f39ae48..cd6a40ec3 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -13,7 +13,18 @@ Asio also comes with a number of examples which could be find under Documentatio Supported features ^^^^^^^^^^^^^^^^^^ -ESP platform port currently supports only network asynchronous socket operations; does not support serial port and ssl. +ESP platform port currently supports only network asynchronous socket operations; does not support serial port. +SSL/TLS support if disabled by default and could be enabled in component configuration menu and choosing TLS library from + +- mbedTLS with OpenSSL translation layer (default option) +- wolfSSL + +SSL support is very basic at this stage, not including + +- Verification callbacks +- DH property files +- Certificates/private keys file APIs + Internal asio settings for ESP include - EXCEPTIONS are enabled in ASIO if enabled in menuconfig @@ -27,5 +38,6 @@ ESP examples are based on standard asio :example:`protocols/asio`: - :example:`protocols/asio/tcp_echo_server` - :example:`protocols/asio/chat_client` - :example:`protocols/asio/chat_server` +- :example:`protocols/asio/ssl_client_server` Please refer to the specific example README.md for details From c0c1a655988fedcff7b9e8a60b844195f8e09fd4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 5 Jun 2020 16:19:10 +0200 Subject: [PATCH 29/60] examples: asio ssl example demonstrating both server and client By default it uses simple client connecting to https address. It is possible to configure both server and client. As for example test the configuration of both server and client connecting to each other on * Original commit: espressif/esp-idf@213bbe51fcde53099b1a6e72381ad8c48afdfcc9 --- .../asio/ssl_client_server/CMakeLists.txt | 10 + .../protocols/asio/ssl_client_server/Makefile | 9 + .../asio/ssl_client_server/README.md | 85 ++++++ .../asio/ssl_client_server/example_test.py | 15 + .../ssl_client_server/main/CMakeLists.txt | 3 + .../ssl_client_server/main/Kconfig.projbuild | 28 ++ .../ssl_client_server/main/asio_ssl_main.cpp | 283 ++++++++++++++++++ .../asio/ssl_client_server/main/cacert.pem | 21 ++ .../asio/ssl_client_server/main/component.mk | 11 + .../asio/ssl_client_server/main/prvtkey.pem | 27 ++ .../asio/ssl_client_server/partitions.csv | 5 + .../asio/ssl_client_server/sdkconfig.ci | 6 + .../asio/ssl_client_server/sdkconfig.defaults | 3 + 13 files changed, 506 insertions(+) create mode 100644 examples/protocols/asio/ssl_client_server/CMakeLists.txt create mode 100644 examples/protocols/asio/ssl_client_server/Makefile create mode 100644 examples/protocols/asio/ssl_client_server/README.md create mode 100644 examples/protocols/asio/ssl_client_server/example_test.py create mode 100644 examples/protocols/asio/ssl_client_server/main/CMakeLists.txt create mode 100644 examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp create mode 100644 examples/protocols/asio/ssl_client_server/main/cacert.pem create mode 100644 examples/protocols/asio/ssl_client_server/main/component.mk create mode 100644 examples/protocols/asio/ssl_client_server/main/prvtkey.pem create mode 100644 examples/protocols/asio/ssl_client_server/partitions.csv create mode 100644 examples/protocols/asio/ssl_client_server/sdkconfig.ci create mode 100644 examples/protocols/asio/ssl_client_server/sdkconfig.defaults diff --git a/examples/protocols/asio/ssl_client_server/CMakeLists.txt b/examples/protocols/asio/ssl_client_server/CMakeLists.txt new file mode 100644 index 000000000..fcdac1488 --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/CMakeLists.txt @@ -0,0 +1,10 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(asio_ssl_client_server) diff --git a/examples/protocols/asio/ssl_client_server/Makefile b/examples/protocols/asio/ssl_client_server/Makefile new file mode 100644 index 000000000..af59f284f --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# +PROJECT_NAME := asio_ssl_client_server + +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common + +include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/ssl_client_server/README.md b/examples/protocols/asio/ssl_client_server/README.md new file mode 100644 index 000000000..e99ccfe11 --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/README.md @@ -0,0 +1,85 @@ +# Asio SSL client/server example + +Simple Asio client and server with SSL/TLS transport + +## How to Use Example + +### Hardware Required + +This example can be executed on any ESP platform board. No external connection is required, it is recommended though +to connect to internet or a local network via WiFi or Ethernet to easily exercise features of this example. + +### Configure the project + +* Open the project configuration menu (`idf.py menuconfig`) +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. +* Enable the ASIO client and set server's host name to examine client's functionality. +The ASIO client connects to the configured server and sends default payload string "GET / HTTP/1.1" +* Enable the ASIO server to examine server's functionality. The ASIO server listens to connection and echos back what was received. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +### Client connecting to public server + +The below output illustrates the client connecting to a public https server. + +``` +I (1267) example_connect: Waiting for IP(s) +I (2587) wifi:new:<11,0>, old:<1,0>, ap:<255,255>, sta:<11,0>, prof:1 +I (3367) wifi:state: init -> auth (b0) +I (3377) wifi:state: auth -> assoc (0) +I (3387) wifi:state: assoc -> run (10) +I (3397) wifi:security type: 3, phy: bgn, rssi: -49 +I (3397) wifi:pm start, type: 1 +I (3457) wifi:AP's beacon interval = 102400 us, DTIM period = 1 +I (4747) example_connect: Got IPv6 event: Interface "example_connect: sta" address: fe80:0000:0000:0000:260a:xxxx:xxxx:xxxx, type: ESP_IP6_ADDR_IS_LINK_LOCAL +I (5247) esp_netif_handlers: example_connect: sta ip: 192.168.32.69, mask: 255.255.252.0, gw: 192.168.32.3 +I (5247) example_connect: Got IPv4 event: Interface "example_connect: sta" address: 192.168.32.69 +I (5257) example_connect: Connected to example_connect: sta +I (5257) example_connect: - IPv4 address: 192.168.32.69 +I (5267) example_connect: - IPv6 address: fe80:0000:0000:0000:260a:xxxx:xxxx:xxxx, type: ESP_IP6_ADDR_IS_LINK_LOCAL +W (5277) esp32_asio_pthread: pthread_condattr_setclock: not yet supported! +W (5297) esp32_asio_pthread: pthread_condattr_setclock: not yet supported! +Reply: HTTP/1.1 200 OK +D +``` +### Both server and client enabled + +The below output demonstrates the client connecting to the ASIO server via loopback interface, so no WiFi, nor Ethernet connection +was established. +``` +I (0) cpu_start: App cpu up. +I (495) heap_init: Initializing. RAM available for dynamic allocation: +I (502) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM +I (508) heap_init: At 3FFB5400 len 0002AC00 (171 KiB): DRAM +I (515) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM +I (521) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM +I (527) heap_init: At 4008BB80 len 00014480 (81 KiB): IRAM +I (534) cpu_start: Pro cpu start user code +I (556) spi_flash: detected chip: gd +I (556) spi_flash: flash io: dio +W (556) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header. +I (566) cpu_start: Starting scheduler on PRO CPU. +I (0) cpu_start: Starting scheduler on APP CPU. +I (600) example_connect: Waiting for IP(s) +W (600) esp32_asio_pthread: pthread_condattr_setclock: not yet supported! +W (1610) esp32_asio_pthread: pthread_condattr_setclock: not yet supported! +W (1610) esp32_asio_pthread: pthread_condattr_setclock: not yet supported! +Server received: GET / HTTP/1.1 + + +Reply: GET / HTTP/1.1 +``` +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/ssl_client_server/example_test.py b/examples/protocols/asio/ssl_client_server/example_test.py new file mode 100644 index 000000000..876eb01b6 --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/example_test.py @@ -0,0 +1,15 @@ +from __future__ import unicode_literals +import ttfw_idf + + +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC') +def test_examples_asio_ssl(env, extra_data): + + dut = env.get_dut('asio_ssl_client_server', 'examples/protocols/asio/ssl_client_server') + dut.start_app() + + dut.expect('Reply: GET / HTTP/1.1') + + +if __name__ == '__main__': + test_examples_asio_ssl() diff --git a/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt b/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt new file mode 100644 index 000000000..5fd4fe15e --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "asio_ssl_main.cpp" + INCLUDE_DIRS "." + EMBED_TXTFILES cacert.pem prvtkey.pem) diff --git a/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild b/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild new file mode 100644 index 000000000..a5996f708 --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild @@ -0,0 +1,28 @@ +menu "Example Configuration" + + config EXAMPLE_CLIENT + bool "Enable TLS client" + default y + help + Choose this option to use ASIO TLS/SSL client functionality + + config EXAMPLE_PORT + string "ASIO port number" + default "443" + help + Port number used by ASIO example. + + config EXAMPLE_SERVER + bool "Enable TLS server" + default n + help + Choose this option to use ASIO TLS/SSL server functionality + + config EXAMPLE_SERVER_NAME + string "ASIO server name or IP" + default "www.google.com" + depends on EXAMPLE_CLIENT + help + Asio example server ip for the ASIO client to connect to. + +endmenu diff --git a/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp b/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp new file mode 100644 index 000000000..8209b680d --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp @@ -0,0 +1,283 @@ +#include +#include "protocol_examples_common.h" +#include "esp_event.h" +#include "nvs_flash.h" +#include +#include +#include +#include +#include "asio.hpp" +#include "asio/ssl.hpp" +#include "asio/buffer.hpp" +#include "esp_pthread.h" + +extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start"); +extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end"); + +extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); +extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); + +const asio::const_buffer cert_chain(cacert_pem_start, cacert_pem_end - cacert_pem_start); +const asio::const_buffer privkey(prvtkey_pem_start, prvtkey_pem_end - prvtkey_pem_start); + +using asio::ip::tcp; + +using asio::ip::tcp; + +enum { max_length = 1024 }; + +class client +{ +public: + client(asio::io_context& io_context, + asio::ssl::context& context, + const tcp::resolver::results_type& endpoints) + : socket_(io_context, context) + { + socket_.set_verify_mode(asio::ssl::verify_peer); + + connect(endpoints); + } + +private: + void connect(const tcp::resolver::results_type& endpoints) + { + asio::async_connect(socket_.lowest_layer(), endpoints, + [this](const std::error_code& error, + const tcp::endpoint& /*endpoint*/) + { + if (!error) + { + handshake(); + } + else + { + std::cout << "Connect failed: " << error.message() << "\n"; + } + }); + } + + void handshake() + { + socket_.async_handshake(asio::ssl::stream_base::client, + [this](const std::error_code& error) + { + if (!error) + { + send_request(); + } + else + { + std::cout << "Handshake failed: " << error.message() << "\n"; + } + }); + } + + void send_request() + { + size_t request_length = std::strlen(request_); + + asio::async_write(socket_, + asio::buffer(request_, request_length), + [this](const std::error_code& error, std::size_t length) + { + if (!error) + { + receive_response(length); + } + else + { + std::cout << "Write failed: " << error.message() << "\n"; + } + }); + } + + void receive_response(std::size_t length) + { + asio::async_read(socket_, + asio::buffer(reply_, length), + [this](const std::error_code& error, std::size_t length) + { + if (!error) + { + std::cout << "Reply: "; + std::cout.write(reply_, length); + std::cout << "\n"; + } + else + { + std::cout << "Read failed: " << error.message() << "\n"; + } + }); + + } + + asio::ssl::stream socket_; + char request_[max_length] = "GET / HTTP/1.1\r\n\r\n"; + char reply_[max_length]; +}; + +class session : public std::enable_shared_from_this +{ +public: + session(tcp::socket socket, asio::ssl::context& context) + : socket_(std::move(socket), context) + { + } + + void start() + { + do_handshake(); + } + +private: + void do_handshake() + { + auto self(shared_from_this()); + socket_.async_handshake(asio::ssl::stream_base::server, + [this, self](const std::error_code& error) + { + if (!error) + { + do_read(); + } + }); + } + + void do_read() + { + auto self(shared_from_this()); + socket_.async_read_some(asio::buffer(data_), + [this, self](const std::error_code& ec, std::size_t length) + { + if (!ec) + { + data_[length] = 0; + std::cout << "Server received: " << data_ << std::endl; + do_write(length); + } + }); + } + + void do_write(std::size_t length) + { + auto self(shared_from_this()); + asio::async_write(socket_, asio::buffer(data_, length), + [this, self](const std::error_code& ec, + std::size_t /*length*/) + { + if (!ec) + { + do_read(); + } + }); + } + + asio::ssl::stream socket_; + char data_[1024]; +}; + +class server +{ +public: + server(asio::io_context& io_context, unsigned short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), + context_(asio::ssl::context::tls_server) + { + context_.set_options( + asio::ssl::context::default_workarounds + | asio::ssl::context::no_sslv2); + context_.use_certificate_chain(cert_chain); + context_.use_private_key(privkey, asio::ssl::context::pem); + + do_accept(); + } + +private: + void do_accept() + { + acceptor_.async_accept( + [this](const std::error_code& error, tcp::socket socket) + { + if (!error) + { + std::make_shared(std::move(socket), context_)->start(); + } + + do_accept(); + }); + } + + tcp::acceptor acceptor_; + asio::ssl::context context_; +}; + +void set_thread_config(const char *name, int stack, int prio) +{ + auto cfg = esp_pthread_get_default_config(); + cfg.thread_name = name; + cfg.stack_size = stack; + cfg.prio = prio; + esp_pthread_set_cfg(&cfg); +} + +void ssl_server_thread() +{ + asio::io_context io_context; + + server s(io_context, 443); + + io_context.run(); +} + +void ssl_client_thread() +{ + asio::io_context io_context; + + tcp::resolver resolver(io_context); + std::string server_ip = CONFIG_EXAMPLE_SERVER_NAME; + std::string server_port = CONFIG_EXAMPLE_PORT; + auto endpoints = resolver.resolve(server_ip, server_port); + + asio::ssl::context ctx(asio::ssl::context::tls_client); + ctx.use_certificate_chain(cert_chain); + + client c(io_context, ctx, endpoints); + + io_context.run(); + +} + + +extern "C" void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + esp_netif_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + /* This helper function configures blocking UART I/O */ + ESP_ERROR_CHECK(example_configure_stdin_stdout()); + std::vector work_threads; + +#if CONFIG_EXAMPLE_SERVER + set_thread_config("Server", 16 * 1024, 5); + work_threads.emplace_back(std::thread(ssl_server_thread)); + std::this_thread::sleep_for(std::chrono::seconds(1)); +#endif // CONFIG_EXAMPLE_SERVER + +#if CONFIG_EXAMPLE_CLIENT + set_thread_config("Client", 16 * 1024, 5); + work_threads.emplace_back(ssl_client_thread); +#endif // CONFIG_EXAMPLE_CLIENT + + for (auto & t : work_threads) { + t.join(); + } + +} diff --git a/examples/protocols/asio/ssl_client_server/main/cacert.pem b/examples/protocols/asio/ssl_client_server/main/cacert.pem new file mode 100644 index 000000000..e09c3989c --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/cacert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIJAPMMNobNczaUMA0GCSqGSIb3DQEBBAUAMHQxEzARBgNV +BAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEcMBoGCSqG +SIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNjExMTUwNTA0MThaFw0xOTExMTUwNTA0MThaMHQx +EzARBgNVBAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEc +MBoGCSqGSIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0 +aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALDjSPDlomepHCzbw4MUrquQAU0xTV4/Npb27k9I5TRVTjIoOs/5hNI2LPFW +e4CREx09ZrT8K3NFOBoSy7bhPAsjGaFxCYYWc9tiX1m5gq3ToVRSmbZ65fE3kvnI +8E/d5VyzA0OMmWbfaolBSTMoWgqRynEaT+z1Eh2yDTzVFy9eov1DdQFUqGDqbH5b +QYvTY5Fyem7UcKWAe2yS0j3H4dVtVBKNY7qV3Px08yGAs5fQFgUwhyB5+qwhvkeL +JdgapGaSTwLgoQKWHbe/lA3NiBIB9hznFUGKo3hmniAvYZbrQcn3tc0l/J4I39v2 +Pm29FAyjWvQyBkGktz2q4elOZYkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq +hkiG9w0BAQQFAAOCAQEAJCJ+97oae/FcOLbPpjCpUQnWqYydgSChgalkZNvr4fVp +TnuNg471l0Y2oTJLoWn2YcbPSFVOEeKkU47mpjMzucHHp0zGaW9SdzhZalWwmbgK +q2ijecIbuFHFNedYTk/03K7eaAcjVhD8e0oOJImeLOL6DAFivA1LUnSgXsdGPDtD +zhISsCPTu+cL1j0yP6HBvLeAyb8kaCWJ05RtiVLRANNHQn/keHajJYpMwnEEbJdG +cqN3whfJoGVbZ6isEf2RQJ0pYRnP7uGLW3wGkLWxfdto8uER8HVDx7fZpevLIqGd +1OoSEi3cIJXWBAjx0TLzzhtb6aeIxBJWQqHThtkKdg== +-----END CERTIFICATE----- diff --git a/examples/protocols/asio/ssl_client_server/main/component.mk b/examples/protocols/asio/ssl_client_server/main/component.mk new file mode 100644 index 000000000..656f72d7b --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/component.mk @@ -0,0 +1,11 @@ +# +# Main component makefile. +# +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a +# in the build directory. This behaviour is entirely configurable, +# please read the ESP-IDF documents if you need to do this. +# + +COMPONENT_EMBED_TXTFILES := cacert.pem +COMPONENT_EMBED_TXTFILES += prvtkey.pem diff --git a/examples/protocols/asio/ssl_client_server/main/prvtkey.pem b/examples/protocols/asio/ssl_client_server/main/prvtkey.pem new file mode 100644 index 000000000..4ead61f6f --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/prvtkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAsONI8OWiZ6kcLNvDgxSuq5ABTTFNXj82lvbuT0jlNFVOMig6 +z/mE0jYs8VZ7gJETHT1mtPwrc0U4GhLLtuE8CyMZoXEJhhZz22JfWbmCrdOhVFKZ +tnrl8TeS+cjwT93lXLMDQ4yZZt9qiUFJMyhaCpHKcRpP7PUSHbINPNUXL16i/UN1 +AVSoYOpsfltBi9NjkXJ6btRwpYB7bJLSPcfh1W1UEo1jupXc/HTzIYCzl9AWBTCH +IHn6rCG+R4sl2BqkZpJPAuChApYdt7+UDc2IEgH2HOcVQYqjeGaeIC9hlutByfe1 +zSX8ngjf2/Y+bb0UDKNa9DIGQaS3Parh6U5liQIDAQABAoIBAB9K9jp3xXVlO3DM +KBhmbkg3n6NSV4eW00d9w8cO9E1/0eeZql3knJS7tNO1IwApqiIAHM1j1yP7WONz +88oUqpSlzwD6iF7KVhC3pHqxEOdDi0Tpn/viXg+Ab2X1IF5guRTfLnKiyviiCazi +edqtBtDb3d6Icx9Oc7gBKcpbQFDGt++wSOb5L+xhRm9B5B4l/6byikiPeKqIK5tC +SoP9Zr1mvpNoGm1P4LvEunFJcRBqVI010VNwfO9P98oVyzJu9/FZZrQxXoY9JdXF +OM6nbl+hMDM3TkEOda9NvBhImozEAvuc97CaaXyR3XivxMqNqNIb4+syUPa2PCS3 +ZztI5qECgYEA1gbVG6ifpvpbBkDPi3Im8fM3F7FLLrQc48FdFjdMvDhHD9lVKucD +Uaa8PF9dbbvlu2cwMyfBOKSuWaXxRxRsiqiPmTunS1MvPzQcSrGwUrL2AogGucn6 ++NrLQf5P4H5IpkDQ9ih3zwjO6xKFK1WeYnYpHM8qUBtl6q0YFyVBPu0CgYEA05Pn +StWA4D7VSbNnVi6lvFyEOUsTrK3v419598TFiq4eXLq6aV8/CQYzKsSzoG+aOZhX +Li+0uyT5cNzUcXYhTsW1hA/pNhMfxMrYiB1x14zlLp2WRGg4vd/+SxX6d9Yd3acX +7QzPKgdDicXs9QN8ozJOICKvNbUI53AJdATVEY0CgYEAwvpGeoQLrdq1weSZLrg3 +soOX1QW3MDz1dKdbXjnStkWut0mOxR7fbysuoPFf8/ARQcCnsHKvHCMqkpESVWbN +2yPkbfxiU8Tcbf/TJljqAOz4ISY6ula/RKZONTixHBrvpEW4GAiV3Q5xMsYUe33s +ZFaw7YXtTj0ng7tdDvjpj6ECgYEApHdUU9ejVq2BHslWiqe4LbO9FMxHfvO2hgix +xugupp6y+2Irhb2EQn+PRq+g8hXOzPaezkhHNTKItDL08T3iplkJwJ6dqmszRsZn +i2dYFzZu8M2PAZ4CfZahFbz/9id7D9HTx3EtmH4NAgvZJpyPRkzUbiaIDDettDpj +Hsyi1AECgYAPLvjBzQj4kPF8Zo9pQEUcz4pmupRVfv3aRfjnahDK4qZHEePDRj+J +W7pzayrs1dyN9QLB8pTc424z7f8MB3llCICN+ohs8CR/eW0NEobE9ldDOeoCr1Vh +NhNSbrN1iZ8U4oLkRTMaDKkVngGffvjGi/q0tOU7hJdZOqNlk2Iahg== +-----END RSA PRIVATE KEY----- diff --git a/examples/protocols/asio/ssl_client_server/partitions.csv b/examples/protocols/asio/ssl_client_server/partitions.csv new file mode 100644 index 000000000..d01414b8a --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 1200000, diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.ci b/examples/protocols/asio/ssl_client_server/sdkconfig.ci new file mode 100644 index 000000000..958aa45d4 --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/sdkconfig.ci @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CLIENT=y +CONFIG_EXAMPLE_SERVER=y +CONFIG_EXAMPLE_SERVER_NAME="localhost" +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=n + diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.defaults b/examples/protocols/asio/ssl_client_server/sdkconfig.defaults new file mode 100644 index 000000000..8ff365b19 --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" From c05558ba28e649dfbdeb589511ba9f0331621775 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 5 Jun 2020 17:17:55 +0200 Subject: [PATCH 30/60] asio: option to use wolfSSL as TLS stack for ASIO Plus other minor update, make openssl aware of current modes (SSL_set_mode) Update coding style in examples and tests, including copyright notices * Original commit: espressif/esp-idf@1c8171c3e8d5a67e47dc8d6abac27ad2989470c3 --- components/asio/CMakeLists.txt | 36 +++++++++-- components/asio/Kconfig | 25 ++++++++ components/asio/asio | 2 +- components/asio/component.mk | 4 ++ .../asio/port/include/esp_asio_config.h | 7 +++ components/asio/port/include/openssl/conf.h | 8 ++- components/asio/port/include/openssl/dh.h | 23 +++++++ .../include/openssl/esp_asio_openssl_stubs.h | 60 +++++++++++++------ components/asio/port/include/openssl/rsa.h | 23 +++++++ components/asio/port/include/openssl/x509v3.h | 23 +++++++ .../asio/port/src/esp_asio_openssl_stubs.c | 5 -- docs/en/api-reference/protocols/asio.rst | 4 +- .../ssl_client_server/main/CMakeLists.txt | 2 +- .../ssl_client_server/main/Kconfig.projbuild | 8 +++ .../ssl_client_server/main/asio_ssl_main.cpp | 55 ++++++++++------- .../asio/ssl_client_server/main/ca.crt | 22 +++++++ .../asio/ssl_client_server/main/cacert.pem | 21 ------- .../asio/ssl_client_server/main/component.mk | 5 +- .../asio/ssl_client_server/main/prvtkey.pem | 27 --------- .../asio/ssl_client_server/main/server.key | 27 +++++++++ .../asio/ssl_client_server/main/srv.crt | 18 ++++++ .../asio/ssl_client_server/partitions.csv | 2 +- .../asio/ssl_client_server/sdkconfig.ci | 2 +- .../asio/ssl_client_server/sdkconfig.defaults | 1 + 24 files changed, 305 insertions(+), 105 deletions(-) create mode 100644 components/asio/Kconfig create mode 100644 components/asio/port/include/openssl/dh.h create mode 100644 components/asio/port/include/openssl/rsa.h create mode 100644 components/asio/port/include/openssl/x509v3.h create mode 100644 examples/protocols/asio/ssl_client_server/main/ca.crt delete mode 100644 examples/protocols/asio/ssl_client_server/main/cacert.pem delete mode 100644 examples/protocols/asio/ssl_client_server/main/prvtkey.pem create mode 100644 examples/protocols/asio/ssl_client_server/main/server.key create mode 100644 examples/protocols/asio/ssl_client_server/main/srv.crt diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt index b55dc56ab..e45f2c95f 100644 --- a/components/asio/CMakeLists.txt +++ b/components/asio/CMakeLists.txt @@ -1,5 +1,33 @@ -idf_component_register(SRCS "asio/asio/src/asio.cpp" - "asio/asio/src/asio_ssl.cpp" - "port/src/esp_asio_openssl_stubs.c" +set(asio_sources "asio/asio/src/asio.cpp") + +if (CONFIG_ASIO_SSL_SUPPORT) + if(CONFIG_ASIO_USE_ESP_OPENSSL) + list(APPEND asio_sources + "asio/asio/src/asio_ssl.cpp" + "port/src/esp_asio_openssl_stubs.c") + endif() + + if(CONFIG_ASIO_USE_ESP_WOLFSSL) + list(APPEND asio_sources + "asio/asio/src/asio_ssl.cpp") + endif() +endif() + +idf_component_register(SRCS ${asio_sources} INCLUDE_DIRS "asio/asio/include" "port/include" - REQUIRES lwip openssl) + REQUIRES lwip) + +if (CONFIG_ASIO_SSL_SUPPORT) + if(CONFIG_ASIO_USE_ESP_WOLFSSL) + idf_component_get_property(wolflib esp-wolfssl COMPONENT_LIB) + idf_component_get_property(wolfdir esp-wolfssl COMPONENT_DIR) + + target_link_libraries(${COMPONENT_LIB} PUBLIC ${wolflib}) + target_include_directories(${COMPONENT_LIB} PUBLIC ${wolfdir}/wolfssl/wolfssl) + endif() + + if(CONFIG_ASIO_USE_ESP_OPENSSL) + idf_component_get_property(esp_openssl openssl COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${esp_openssl}) + endif() +endif() diff --git a/components/asio/Kconfig b/components/asio/Kconfig new file mode 100644 index 000000000..582410e7c --- /dev/null +++ b/components/asio/Kconfig @@ -0,0 +1,25 @@ +menu "ESP-ASIO" + config ASIO_SSL_SUPPORT + bool "Enable SSL/TLS support of ASIO" + default n + help + Enable support for basic SSL/TLS features, available for mbedTLS/OpenSSL + as well as wolfSSL TLS library. + + choice ASIO_SSL_LIBRARY_CHOICE + prompt "Choose SSL/TLS library for ESP-TLS (See help for more Info)" + default ASIO_USE_ESP_OPENSSL + depends on ASIO_SSL_SUPPORT + help + The ASIO support multiple backend TLS libraries. Currently the mbedTLS with a thin ESP-OpenSSL + port layer (default choice) and WolfSSL are supported. + Different TLS libraries may support different features and have different resource + usage. Consult the ESP-TLS documentation in ESP-IDF Programming guide for more details. + config ASIO_USE_ESP_OPENSSL + bool "esp-openssl" + config ASIO_USE_ESP_WOLFSSL + depends on TLS_STACK_WOLFSSL + bool "wolfSSL (License info in wolfSSL directory README)" + endchoice + +endmenu diff --git a/components/asio/asio b/components/asio/asio index 61702cd13..f31694c9f 160000 --- a/components/asio/asio +++ b/components/asio/asio @@ -1 +1 @@ -Subproject commit 61702cd13be0b8c9800a9793daae72768ede26af +Subproject commit f31694c9f1746ba189a4bcae2e34db15135ddb22 diff --git a/components/asio/component.mk b/components/asio/component.mk index 0c2919e24..30b2907bb 100644 --- a/components/asio/component.mk +++ b/components/asio/component.mk @@ -2,4 +2,8 @@ COMPONENT_ADD_INCLUDEDIRS := asio/asio/include port/include COMPONENT_PRIV_INCLUDEDIRS := private_include COMPONENT_SRCDIRS := asio/asio/src port/src +ifeq ($(CONFIG_ASIO_SSL_SUPPORT), ) +COMPONENT_OBJEXCLUDE := asio/asio/src/asio_ssl.o port/src/esp_asio_openssl_stubs.o +endif + COMPONENT_SUBMODULES += asio diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index 750f4cbe3..bcf8c38d4 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -40,4 +40,11 @@ # define ASIO_STANDALONE # define ASIO_HAS_PTHREADS +# ifdef CONFIG_ASIO_USE_ESP_OPENSSL +# define ASIO_USE_ESP_OPENSSL +# define OPENSSL_NO_ENGINE +# elif CONFIG_ASIO_USE_ESP_WOLFSSL +# define ASIO_USE_WOLFSSL +# endif // CONFIG_ASIO_USE_ESP_OPENSSL + #endif // _ESP_ASIO_CONFIG_H_ diff --git a/components/asio/port/include/openssl/conf.h b/components/asio/port/include/openssl/conf.h index 9c46bd14a..f125c3e6c 100644 --- a/components/asio/port/include/openssl/conf.h +++ b/components/asio/port/include/openssl/conf.h @@ -14,7 +14,13 @@ #ifndef _ESP_ASIO_OPENSSL_CONF_H #define _ESP_ASIO_OPENSSL_CONF_H - +#include "esp_asio_config.h" #include "openssl/esp_asio_openssl_stubs.h" +#if defined(ASIO_USE_WOLFSSL) +// SSLv3 Methods not present in current wolfSSL library +#define OPENSSL_NO_SSL3 +#include_next "openssl/conf.h" +#endif // ASIO_USE_WOLFSSL + #endif // _ESP_ASIO_OPENSSL_CONF_H diff --git a/components/asio/port/include/openssl/dh.h b/components/asio/port/include/openssl/dh.h new file mode 100644 index 000000000..def713cfd --- /dev/null +++ b/components/asio/port/include/openssl/dh.h @@ -0,0 +1,23 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_ASIO_OPENSSL_DH_STUB_H +#define _ESP_ASIO_OPENSSL_DH_STUB_H +// Dummy header needed for ASIO compilation with esp-openssl + +#if defined(ASIO_USE_WOLFSSL) +#include_next "openssl/dh.h" +#endif // ASIO_USE_WOLFSSL + +#endif // _ESP_ASIO_OPENSSL_DH_STUB_H diff --git a/components/asio/port/include/openssl/esp_asio_openssl_stubs.h b/components/asio/port/include/openssl/esp_asio_openssl_stubs.h index 611b4e784..fde523172 100644 --- a/components/asio/port/include/openssl/esp_asio_openssl_stubs.h +++ b/components/asio/port/include/openssl/esp_asio_openssl_stubs.h @@ -15,21 +15,57 @@ #ifndef _ESP_ASIO_OPENSSL_STUBS_H #define _ESP_ASIO_OPENSSL_STUBS_H -#include "internal/ssl_x509.h" -#include "internal/ssl_pkey.h" -#include "mbedtls/pem.h" -#include - /** * @note This header contains openssl API which are NOT implemented, and are only provided * as stubs or no-operations to get the ASIO library compiled and working with most * practical use cases as an embedded application on ESP platform */ +#if defined(ASIO_USE_WOLFSSL) + +#include "wolfssl/ssl.h" +// esp-wolfssl disables filesystem by default, but the ssl filesystem functions are needed for the ASIO to compile +// - so we could either configure wolfSSL to use filesystem +// - or use the default wolfSSL and declare the filesystem functions -- preferred option, as whenever +// the filesystem functions are used from app code (potential security impact if private keys in a filesystem) +// compilation fails with linking errors. + +#if defined(NO_FILESYSTEM) +// WolfSSL methods that are not included in standard esp-wolfssl config, must be defined here +// as function stubs, so ASIO compiles, but would get link errors, if these functions were used. + #ifdef __cplusplus extern "C" { #endif +typedef struct WOLFSSL_CTX WOLFSSL_CTX; + +void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +int SSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, const char*); +int SSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int); +int SSL_CTX_use_certificate_chain_file(WOLFSSL_CTX*, const char*); +int SSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int); +int SSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int); + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif // NO_FILESYSTEM + +#elif defined(ASIO_USE_ESP_OPENSSL) + +#include "internal/ssl_x509.h" +#include "internal/ssl_pkey.h" +#include "mbedtls/pem.h" +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + // The most applicable OpenSSL version wrtt ASIO usage #define OPENSSL_VERSION_NUMBER 0x10100001L // SSLv2 methods not supported @@ -40,10 +76,7 @@ extern "C" { #define SSL_R_SHORT_READ 219 #define SSL_OP_ALL 0 #define SSL_OP_SINGLE_DH_USE 0 -//#define OPENSSL_VERSION_NUMBER 0x10001000L #define SSL_OP_NO_COMPRESSION 0 -//#define LIBRESSL_VERSION_NUMBER 1 -//#define PEM_R_NO_START_LINE 110 // Translates mbedTLS PEM parse error, used by ASIO #define PEM_R_NO_START_LINE -MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT @@ -58,9 +91,6 @@ extern "C" { #define NID_subject_alt_name 85 -#define SSL_MODE_RELEASE_BUFFERS 0x00000000L -#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L -#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L #define GEN_DNS 2 #define GEN_IPADD 7 @@ -153,13 +183,6 @@ void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); */ int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh); -/** - * @brief Sets SSL mode -- not implemented - * - * Current implementation is no-op - */ -uint32_t SSL_set_mode(SSL *ssl, uint32_t mode); - /** * @brief API provaded as declaration only * @@ -182,4 +205,5 @@ int SSL_CTX_clear_chain_certs(SSL_CTX *ctx); } /* extern C */ #endif +#endif /* ASIO_USE_ESP_OPENSSL, ASIO_USE_WOLFSSL */ #endif /* _ESP_ASIO_OPENSSL_STUBS_H */ diff --git a/components/asio/port/include/openssl/rsa.h b/components/asio/port/include/openssl/rsa.h new file mode 100644 index 000000000..5d9d10e82 --- /dev/null +++ b/components/asio/port/include/openssl/rsa.h @@ -0,0 +1,23 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_ASIO_OPENSSL_RSA_STUB_H +#define _ESP_ASIO_OPENSSL_RSA_STUB_H +// Dummy header needed for ASIO compilation with esp-openssl + +#if defined(ASIO_USE_WOLFSSL) +#include_next "openssl/rsa.h" +#endif // ASIO_USE_WOLFSSL + +#endif // _ESP_ASIO_OPENSSL_RSA_STUB_H diff --git a/components/asio/port/include/openssl/x509v3.h b/components/asio/port/include/openssl/x509v3.h new file mode 100644 index 000000000..5ae8e7843 --- /dev/null +++ b/components/asio/port/include/openssl/x509v3.h @@ -0,0 +1,23 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_ASIO_OPENSSL_X509V3_STUB_H +#define _ESP_ASIO_OPENSSL_X509V3_STUB_H +// Dummy header needed for ASIO compilation with esp-openssl + +#if defined(ASIO_USE_WOLFSSL) +#include_next "openssl/x509v3.h" +#endif // ASIO_USE_WOLFSSL + +#endif // _ESP_ASIO_OPENSSL_X509V3_STUB_H diff --git a/components/asio/port/src/esp_asio_openssl_stubs.c b/components/asio/port/src/esp_asio_openssl_stubs.c index 9fdf53d0d..6deb099ca 100644 --- a/components/asio/port/src/esp_asio_openssl_stubs.c +++ b/components/asio/port/src/esp_asio_openssl_stubs.c @@ -49,11 +49,6 @@ X509_NAME *X509_get_subject_name(X509 *a) return NULL; } -uint32_t SSL_set_mode(SSL *ssl, uint32_t mode) -{ - return 0; -} - int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) { return 1; diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index cd6a40ec3..559759e9e 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -14,12 +14,12 @@ Asio also comes with a number of examples which could be find under Documentatio Supported features ^^^^^^^^^^^^^^^^^^ ESP platform port currently supports only network asynchronous socket operations; does not support serial port. -SSL/TLS support if disabled by default and could be enabled in component configuration menu and choosing TLS library from +SSL/TLS support is disabled by default and could be enabled in component configuration menu by choosing TLS library from - mbedTLS with OpenSSL translation layer (default option) - wolfSSL -SSL support is very basic at this stage, not including +SSL support is very basic at this stage and it does include following features: - Verification callbacks - DH property files diff --git a/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt b/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt index 5fd4fe15e..f962b470c 100644 --- a/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt +++ b/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "asio_ssl_main.cpp" INCLUDE_DIRS "." - EMBED_TXTFILES cacert.pem prvtkey.pem) + EMBED_TXTFILES ca.crt server.key srv.crt) diff --git a/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild b/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild index a5996f708..1d03a2af4 100644 --- a/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild +++ b/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild @@ -25,4 +25,12 @@ menu "Example Configuration" help Asio example server ip for the ASIO client to connect to. + config EXAMPLE_CLIENT_VERIFY_PEER + bool "Client to verify peer" + default n + depends on EXAMPLE_CLIENT + help + This option sets client's mode to verify peer, default is + verify-none + endmenu diff --git a/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp b/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp index 8209b680d..1959f1870 100644 --- a/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp +++ b/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp @@ -1,3 +1,10 @@ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + #include #include "protocol_examples_common.h" #include "esp_event.h" @@ -11,30 +18,36 @@ #include "asio/buffer.hpp" #include "esp_pthread.h" -extern const unsigned char cacert_pem_start[] asm("_binary_cacert_pem_start"); -extern const unsigned char cacert_pem_end[] asm("_binary_cacert_pem_end"); +extern const unsigned char server_pem_start[] asm("_binary_srv_crt_start"); +extern const unsigned char server_pem_end[] asm("_binary_srv_crt_end"); -extern const unsigned char prvtkey_pem_start[] asm("_binary_prvtkey_pem_start"); -extern const unsigned char prvtkey_pem_end[] asm("_binary_prvtkey_pem_end"); +extern const unsigned char cacert_pem_start[] asm("_binary_ca_crt_start"); +extern const unsigned char cacert_pem_end[] asm("_binary_ca_crt_end"); + +extern const unsigned char prvtkey_pem_start[] asm("_binary_server_key_start"); +extern const unsigned char prvtkey_pem_end[] asm("_binary_server_key_end"); const asio::const_buffer cert_chain(cacert_pem_start, cacert_pem_end - cacert_pem_start); const asio::const_buffer privkey(prvtkey_pem_start, prvtkey_pem_end - prvtkey_pem_start); - -using asio::ip::tcp; +const asio::const_buffer server_cert(server_pem_start, server_pem_end - server_pem_start); using asio::ip::tcp; enum { max_length = 1024 }; -class client -{ +class Client { public: - client(asio::io_context& io_context, + Client(asio::io_context& io_context, asio::ssl::context& context, const tcp::resolver::results_type& endpoints) : socket_(io_context, context) { + +#if CONFIG_EXAMPLE_CLIENT_VERIFY_PEER socket_.set_verify_mode(asio::ssl::verify_peer); +#else + socket_.set_verify_mode(asio::ssl::verify_none); +#endif // CONFIG_EXAMPLE_CLIENT_VERIFY_PEER connect(endpoints); } @@ -117,10 +130,9 @@ private: char reply_[max_length]; }; -class session : public std::enable_shared_from_this -{ +class Session : public std::enable_shared_from_this { public: - session(tcp::socket socket, asio::ssl::context& context) + Session(tcp::socket socket, asio::ssl::context& context) : socket_(std::move(socket), context) { } @@ -174,20 +186,19 @@ private: } asio::ssl::stream socket_; - char data_[1024]; + char data_[max_length]; }; -class server -{ +class Server { public: - server(asio::io_context& io_context, unsigned short port) + Server(asio::io_context& io_context, unsigned short port) : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), context_(asio::ssl::context::tls_server) { context_.set_options( asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2); - context_.use_certificate_chain(cert_chain); + context_.use_certificate_chain(server_cert); context_.use_private_key(privkey, asio::ssl::context::pem); do_accept(); @@ -201,7 +212,7 @@ private: { if (!error) { - std::make_shared(std::move(socket), context_)->start(); + std::make_shared(std::move(socket), context_)->start(); } do_accept(); @@ -225,7 +236,7 @@ void ssl_server_thread() { asio::io_context io_context; - server s(io_context, 443); + Server s(io_context, 443); io_context.run(); } @@ -240,9 +251,11 @@ void ssl_client_thread() auto endpoints = resolver.resolve(server_ip, server_port); asio::ssl::context ctx(asio::ssl::context::tls_client); - ctx.use_certificate_chain(cert_chain); +#if CONFIG_EXAMPLE_CLIENT_VERIFY_PEER + ctx.add_certificate_authority(cert_chain); +#endif // CONFIG_EXAMPLE_CLIENT_VERIFY_PEER - client c(io_context, ctx, endpoints); + Client c(io_context, ctx, endpoints); io_context.run(); diff --git a/examples/protocols/asio/ssl_client_server/main/ca.crt b/examples/protocols/asio/ssl_client_server/main/ca.crt new file mode 100644 index 000000000..894f2959b --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDkzCCAnugAwIBAgIUNI5wldYysh6rtCzYmda6H414aRswDQYJKoZIhvcNAQEL +BQAwWTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJRXNwcmVzc2lmMB4X +DTIwMDEyMTA5MDk0NloXDTI1MDEyMDA5MDk0NlowWTELMAkGA1UEBhMCQVUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5 +IEx0ZDESMBAGA1UEAwwJRXNwcmVzc2lmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAyadSpRnIQBVbEAsbpkrKrOMlBOMIUmA8AfNyOYPLfv0Oa5lBiMAV +3OQDu5tYyFYKwkCUqq65iAm50fPbSH71w1tkja6nZ1yAIM+TvpMlM/WiFGrhY+Tc +kAcLcKUJyPxrv/glzoVslbqUgIhuhCSKA8uk1+ILcn3nWzPcbcowLx31+AHeZj8h +bIAdj6vjqxMCFStp4IcA+ikmCk75LCN4vkkifdkebb/ZDNYCZZhpCBnCHyFAjPc4 +7C+FDVGT3/UUeeTy+Mtn+MqUAhB+W0sPDm1n2h59D4Z/MFm0hl6GQCAKeMJPzssU +BBsRm6zoyPQ4VTqG0uwfNNbORyIfKONMUwIDAQABo1MwUTAdBgNVHQ4EFgQUGYLV +EkgWzxjpltE6texha7zZVxowHwYDVR0jBBgwFoAUGYLVEkgWzxjpltE6texha7zZ +VxowDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAb2EF4Zg2XWNb +eZHnzupCDd9jAhwPqkt7F1OXvxJa/RFUSB9+2izGvikGGhuKY4f0iLuqF+bhExD9 +sapDcdFO2Suh4J3onbwEvmKvsv56K3xhapYg8WwPofpkVirnkwFjpQXGzrYxPujg +BPmSy3psQrhvOr/WH7SefJv2qr4ikaugfE+3enY4PL+C1dSQAuNo1QGgWsZIu0c8 +TZybNZ13vNVMA+tgj2CM8FR3Etaabwtu3TTcAnO7aoBTix/bLBTuZoczhN8/MhG3 +GylmDzFI8a6aKxQL3Fi4PsM82hRKWu3gfs39sR1Ci4V22v8uO5EWBPK0QZvDSc1a +KwwxI4zA0w== +-----END CERTIFICATE----- diff --git a/examples/protocols/asio/ssl_client_server/main/cacert.pem b/examples/protocols/asio/ssl_client_server/main/cacert.pem deleted file mode 100644 index e09c3989c..000000000 --- a/examples/protocols/asio/ssl_client_server/main/cacert.pem +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDezCCAmOgAwIBAgIJAPMMNobNczaUMA0GCSqGSIb3DQEBBAUAMHQxEzARBgNV -BAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEcMBoGCSqG -SIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0aWZpY2F0 -aW9uIEF1dGhvcml0eTAeFw0xNjExMTUwNTA0MThaFw0xOTExMTUwNTA0MThaMHQx -EzARBgNVBAMTCk15IFRlc3QgQ0ExCzAJBgNVBAgTAkhaMQswCQYDVQQGEwJDTjEc -MBoGCSqGSIb3DQEJARYNdGVzdEBjZXJ0LmNvbTElMCMGA1UEChMcUm9vdCBDZXJ0 -aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBALDjSPDlomepHCzbw4MUrquQAU0xTV4/Npb27k9I5TRVTjIoOs/5hNI2LPFW -e4CREx09ZrT8K3NFOBoSy7bhPAsjGaFxCYYWc9tiX1m5gq3ToVRSmbZ65fE3kvnI -8E/d5VyzA0OMmWbfaolBSTMoWgqRynEaT+z1Eh2yDTzVFy9eov1DdQFUqGDqbH5b -QYvTY5Fyem7UcKWAe2yS0j3H4dVtVBKNY7qV3Px08yGAs5fQFgUwhyB5+qwhvkeL -JdgapGaSTwLgoQKWHbe/lA3NiBIB9hznFUGKo3hmniAvYZbrQcn3tc0l/J4I39v2 -Pm29FAyjWvQyBkGktz2q4elOZYkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq -hkiG9w0BAQQFAAOCAQEAJCJ+97oae/FcOLbPpjCpUQnWqYydgSChgalkZNvr4fVp -TnuNg471l0Y2oTJLoWn2YcbPSFVOEeKkU47mpjMzucHHp0zGaW9SdzhZalWwmbgK -q2ijecIbuFHFNedYTk/03K7eaAcjVhD8e0oOJImeLOL6DAFivA1LUnSgXsdGPDtD -zhISsCPTu+cL1j0yP6HBvLeAyb8kaCWJ05RtiVLRANNHQn/keHajJYpMwnEEbJdG -cqN3whfJoGVbZ6isEf2RQJ0pYRnP7uGLW3wGkLWxfdto8uER8HVDx7fZpevLIqGd -1OoSEi3cIJXWBAjx0TLzzhtb6aeIxBJWQqHThtkKdg== ------END CERTIFICATE----- diff --git a/examples/protocols/asio/ssl_client_server/main/component.mk b/examples/protocols/asio/ssl_client_server/main/component.mk index 656f72d7b..71869b0a3 100644 --- a/examples/protocols/asio/ssl_client_server/main/component.mk +++ b/examples/protocols/asio/ssl_client_server/main/component.mk @@ -7,5 +7,6 @@ # please read the ESP-IDF documents if you need to do this. # -COMPONENT_EMBED_TXTFILES := cacert.pem -COMPONENT_EMBED_TXTFILES += prvtkey.pem +COMPONENT_EMBED_TXTFILES := ca.crt +COMPONENT_EMBED_TXTFILES += server.key +COMPONENT_EMBED_TXTFILES += srv.crt diff --git a/examples/protocols/asio/ssl_client_server/main/prvtkey.pem b/examples/protocols/asio/ssl_client_server/main/prvtkey.pem deleted file mode 100644 index 4ead61f6f..000000000 --- a/examples/protocols/asio/ssl_client_server/main/prvtkey.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAsONI8OWiZ6kcLNvDgxSuq5ABTTFNXj82lvbuT0jlNFVOMig6 -z/mE0jYs8VZ7gJETHT1mtPwrc0U4GhLLtuE8CyMZoXEJhhZz22JfWbmCrdOhVFKZ -tnrl8TeS+cjwT93lXLMDQ4yZZt9qiUFJMyhaCpHKcRpP7PUSHbINPNUXL16i/UN1 -AVSoYOpsfltBi9NjkXJ6btRwpYB7bJLSPcfh1W1UEo1jupXc/HTzIYCzl9AWBTCH -IHn6rCG+R4sl2BqkZpJPAuChApYdt7+UDc2IEgH2HOcVQYqjeGaeIC9hlutByfe1 -zSX8ngjf2/Y+bb0UDKNa9DIGQaS3Parh6U5liQIDAQABAoIBAB9K9jp3xXVlO3DM -KBhmbkg3n6NSV4eW00d9w8cO9E1/0eeZql3knJS7tNO1IwApqiIAHM1j1yP7WONz -88oUqpSlzwD6iF7KVhC3pHqxEOdDi0Tpn/viXg+Ab2X1IF5guRTfLnKiyviiCazi -edqtBtDb3d6Icx9Oc7gBKcpbQFDGt++wSOb5L+xhRm9B5B4l/6byikiPeKqIK5tC -SoP9Zr1mvpNoGm1P4LvEunFJcRBqVI010VNwfO9P98oVyzJu9/FZZrQxXoY9JdXF -OM6nbl+hMDM3TkEOda9NvBhImozEAvuc97CaaXyR3XivxMqNqNIb4+syUPa2PCS3 -ZztI5qECgYEA1gbVG6ifpvpbBkDPi3Im8fM3F7FLLrQc48FdFjdMvDhHD9lVKucD -Uaa8PF9dbbvlu2cwMyfBOKSuWaXxRxRsiqiPmTunS1MvPzQcSrGwUrL2AogGucn6 -+NrLQf5P4H5IpkDQ9ih3zwjO6xKFK1WeYnYpHM8qUBtl6q0YFyVBPu0CgYEA05Pn -StWA4D7VSbNnVi6lvFyEOUsTrK3v419598TFiq4eXLq6aV8/CQYzKsSzoG+aOZhX -Li+0uyT5cNzUcXYhTsW1hA/pNhMfxMrYiB1x14zlLp2WRGg4vd/+SxX6d9Yd3acX -7QzPKgdDicXs9QN8ozJOICKvNbUI53AJdATVEY0CgYEAwvpGeoQLrdq1weSZLrg3 -soOX1QW3MDz1dKdbXjnStkWut0mOxR7fbysuoPFf8/ARQcCnsHKvHCMqkpESVWbN -2yPkbfxiU8Tcbf/TJljqAOz4ISY6ula/RKZONTixHBrvpEW4GAiV3Q5xMsYUe33s -ZFaw7YXtTj0ng7tdDvjpj6ECgYEApHdUU9ejVq2BHslWiqe4LbO9FMxHfvO2hgix -xugupp6y+2Irhb2EQn+PRq+g8hXOzPaezkhHNTKItDL08T3iplkJwJ6dqmszRsZn -i2dYFzZu8M2PAZ4CfZahFbz/9id7D9HTx3EtmH4NAgvZJpyPRkzUbiaIDDettDpj -Hsyi1AECgYAPLvjBzQj4kPF8Zo9pQEUcz4pmupRVfv3aRfjnahDK4qZHEePDRj+J -W7pzayrs1dyN9QLB8pTc424z7f8MB3llCICN+ohs8CR/eW0NEobE9ldDOeoCr1Vh -NhNSbrN1iZ8U4oLkRTMaDKkVngGffvjGi/q0tOU7hJdZOqNlk2Iahg== ------END RSA PRIVATE KEY----- diff --git a/examples/protocols/asio/ssl_client_server/main/server.key b/examples/protocols/asio/ssl_client_server/main/server.key new file mode 100644 index 000000000..2a4d650ea --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAlUCywNhVv4RO2y9h/XGKZ1azzk3jzHpSBzIGO9LoiA8trC/p +1ykGaUfYPJllYK4HMhC4fUyE3J7tVL2Eskzl26LNPLbEoaBWZM9NhV3iA1/1EtOu +p6umLx+y3sDfvK35YAOUbjdAlBfhnJ4r8h7oTsxl3J5jZ18zgjJnJi2NEFq/yTpO +MiwHLWPjy25fDFixfV9UzSvbgt1JaGPmC7c4QkhHzjyp0+ikuvRIw0p9BBNeqBV2 +da3qBMB5FtodUJTAz6o6OKWbTalLjQi6C1H6z9TnY7IrJBUOy/FWkQH/sEsLdscD +hHa1Dz2oT203QjhzyOSfnNF95D/1MdNcMt6l0wIDAQABAoIBAC1JJTOoMFRc48RT +myrYQYNbZlEphv3q+2qdfhC2zMFDwbrmCtCy7PQSzYSNkpoEE8DYG/JAvmtmeWJl +4pZrCK9ctWM/nWfhC3WpBL97nfEiM20T94F+bn0L5Cz8XqaULv839th+QUTt/hGU +WIctY5VNJXcMQ+MAmtNdUbjex1d3iuxiKHUo4nDoZ8digKFNdtdP5B5nlMq5chCL +mxNRcsGsx2dDAxbGUapdTVPWHPJKpLOBoSkluDsfd2KZADFU2R1SJpAX9+RYh3HM +5FTUdHTUaISxbKkgeDKlEM0lqk2TtGUwCyEj098ewi7Wzsu9w60IplPPUJx5FRG6 +jp3wzLkCgYEAxKp5T20rf/7ysX7x053I7VCjDXUxAaWOEj1uS3AhOkl0NaZg7Di+ +y53fWNkcHdkt2n2LqMt/43UgMYq3TVVcq2eunPNF11e1bJw8CjDafwDs4omwwyVn +lYhPuB4dK2OAib+vU5Zqpp0kZMoxk2MZVgon8z+s8DW/zmB6aFqAWeUCgYEAwkhC +OgmXKMdjOCVy5t2f5UbY8Y9rV3w8eUATuJ47MMwLr4pGYnKoEn9JB4ltWrHv/u5S +fOv3tIrrCEvnCoCbOILwCsY5LqTNXgqova8FB6RpMUQCzhDd8LHuvdHv0WMnMzX1 +3PKuqwh8JS55m4WqZRhzr5BFKG4fHPVs4IcaJVcCgYAzzCaJSdqUKqTnJOUydDNQ +ddWMHNqccWs62J0tF0pZHLGT089hSAzQejMyJnSmU+Ykzr4y5e44DUg+ZCelIZ93 +saYmxlgVwI8THQ8fLADQRIEfpV4996MRmkZM2vmZzOo03Zyi6lIKsga82Rg3lnk8 +1Q3ynknBNpbfF0AGLhfyFQKBgBYlxJ73HutAJ5hr9HhLBYJOnEaVUehMOlycKGNg +bmD2sdJWEgYBChXpurqIORYguLo4EuE4ySkkuPxeIr14wbkkfBbOWBBwKxUwY+IT +xKAFZxR9q1AwbgyVTCEJgKw/AGX/HcMNS0omEnjunmBTUYRq0C1QZgHg490aQUor +PJjLAoGAevzdTpFlVeuKeYh1oDubGO1LinyXpBv7fPFjl+zu4AVbjojcU6yC4OO6 +QvqopE6SyAECKy8kAOFcESPsGc9Lta2XUvI203z7pIVlNVEcJ0+90mQh3Mn1U46l +sZ49PdRvNwNb5wvkh1UqNsMlGFbRlzMbIk45ou4311kCobowZek= +-----END RSA PRIVATE KEY----- diff --git a/examples/protocols/asio/ssl_client_server/main/srv.crt b/examples/protocols/asio/ssl_client_server/main/srv.crt new file mode 100644 index 000000000..29bfa1664 --- /dev/null +++ b/examples/protocols/asio/ssl_client_server/main/srv.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC9DCCAdwCFA1lSIcHwYKdB2UqOrZxZnVgPObTMA0GCSqGSIb3DQEBCwUAMFkx +CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl +cm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCUVzcHJlc3NpZjAeFw0yMDA2 +MTIwNjA0MTNaFw0yMjA2MDIwNjA0MTNaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJVAssDYVb+ETtsvYf1ximdW +s85N48x6UgcyBjvS6IgPLawv6dcpBmlH2DyZZWCuBzIQuH1MhNye7VS9hLJM5dui +zTy2xKGgVmTPTYVd4gNf9RLTrqerpi8fst7A37yt+WADlG43QJQX4ZyeK/Ie6E7M +ZdyeY2dfM4IyZyYtjRBav8k6TjIsBy1j48tuXwxYsX1fVM0r24LdSWhj5gu3OEJI +R848qdPopLr0SMNKfQQTXqgVdnWt6gTAeRbaHVCUwM+qOjilm02pS40IugtR+s/U +52OyKyQVDsvxVpEB/7BLC3bHA4R2tQ89qE9tN0I4c8jkn5zRfeQ/9THTXDLepdMC +AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAnMYGW+idt37bEE4WPgrRorKWuplR+zHD +wJFz53DQzyIZJHmJ2hR5U0jNcHy/nMq7tbdz9LZPrVF4lZJ3TJhnmkOKjMFPCQE8 +YcmsP3il6eXgtGqg53InOi/uJqEQ9TfM54cbpp6xKbnmpwk4uprISBRQt7u2ZLk2 +40ED6zgjFPDTYmSjSpb2AN6KUB6PflgVs+4p9ViHNq4U3AlYV/BM0+3G4aMX2wNl +ZIpQfOyuaYD5MU50mY+O+gDiiypkpYf6a6S4YJ1sMbavDsP7bW5UMnP0jKYR549q +5hF1fdkXq52DfJ9ya2kl3mANFkKssQV+1KCBMxGoeqfakmJfa03xXA== +-----END CERTIFICATE----- diff --git a/examples/protocols/asio/ssl_client_server/partitions.csv b/examples/protocols/asio/ssl_client_server/partitions.csv index d01414b8a..f3aa8e2b4 100644 --- a/examples/protocols/asio/ssl_client_server/partitions.csv +++ b/examples/protocols/asio/ssl_client_server/partitions.csv @@ -2,4 +2,4 @@ # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 1200000, +factory, app, factory, 0x10000, 1400000, diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.ci b/examples/protocols/asio/ssl_client_server/sdkconfig.ci index 958aa45d4..f1c43e8ac 100644 --- a/examples/protocols/asio/ssl_client_server/sdkconfig.ci +++ b/examples/protocols/asio/ssl_client_server/sdkconfig.ci @@ -3,4 +3,4 @@ CONFIG_EXAMPLE_SERVER=y CONFIG_EXAMPLE_SERVER_NAME="localhost" CONFIG_EXAMPLE_CONNECT_WIFI=n CONFIG_EXAMPLE_CONNECT_ETHERNET=n - +CONFIG_EXAMPLE_CLIENT_VERIFY_PEER=y diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.defaults b/examples/protocols/asio/ssl_client_server/sdkconfig.defaults index 8ff365b19..7340a4467 100644 --- a/examples/protocols/asio/ssl_client_server/sdkconfig.defaults +++ b/examples/protocols/asio/ssl_client_server/sdkconfig.defaults @@ -1,3 +1,4 @@ +CONFIG_ASIO_SSL_SUPPORT=y CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" From f00c3be139d7998bf76c1b2ccefc97ad5028627d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C4=8Cerm=C3=A1k?= Date: Thu, 18 Jun 2020 16:16:41 +0800 Subject: [PATCH 31/60] asio: make the example code conform to Espressif C++ standards * Original commit: espressif/esp-idf@b2150f86a502f6df063ed1e09d146a487db9f6c8 --- .../ssl_client_server/main/asio_ssl_main.cpp | 170 ++++++++---------- 1 file changed, 73 insertions(+), 97 deletions(-) diff --git a/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp b/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp index 1959f1870..8356dc716 100644 --- a/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp +++ b/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp @@ -27,20 +27,20 @@ extern const unsigned char cacert_pem_end[] asm("_binary_ca_crt_end"); extern const unsigned char prvtkey_pem_start[] asm("_binary_server_key_start"); extern const unsigned char prvtkey_pem_end[] asm("_binary_server_key_end"); -const asio::const_buffer cert_chain(cacert_pem_start, cacert_pem_end - cacert_pem_start); -const asio::const_buffer privkey(prvtkey_pem_start, prvtkey_pem_end - prvtkey_pem_start); -const asio::const_buffer server_cert(server_pem_start, server_pem_end - server_pem_start); +static const asio::const_buffer cert_chain(cacert_pem_start, cacert_pem_end - cacert_pem_start); +static const asio::const_buffer privkey(prvtkey_pem_start, prvtkey_pem_end - prvtkey_pem_start); +static const asio::const_buffer server_cert(server_pem_start, server_pem_end - server_pem_start); using asio::ip::tcp; -enum { max_length = 1024 }; +static const std::size_t max_length = 1024; class Client { public: - Client(asio::io_context& io_context, - asio::ssl::context& context, - const tcp::resolver::results_type& endpoints) - : socket_(io_context, context) + Client(asio::io_context &io_context, + asio::ssl::context &context, + const tcp::resolver::results_type &endpoints) + : socket_(io_context, context) { #if CONFIG_EXAMPLE_CLIENT_VERIFY_PEER @@ -53,37 +53,29 @@ public: } private: - void connect(const tcp::resolver::results_type& endpoints) + void connect(const tcp::resolver::results_type &endpoints) { asio::async_connect(socket_.lowest_layer(), endpoints, - [this](const std::error_code& error, - const tcp::endpoint& /*endpoint*/) - { - if (!error) - { - handshake(); - } - else - { - std::cout << "Connect failed: " << error.message() << "\n"; - } - }); + [this](const std::error_code & error, + const tcp::endpoint & /*endpoint*/) { + if (!error) { + handshake(); + } else { + std::cout << "Connect failed: " << error.message() << "\n"; + } + }); } void handshake() { socket_.async_handshake(asio::ssl::stream_base::client, - [this](const std::error_code& error) - { - if (!error) - { - send_request(); - } - else - { - std::cout << "Handshake failed: " << error.message() << "\n"; - } - }); + [this](const std::error_code & error) { + if (!error) { + send_request(); + } else { + std::cout << "Handshake failed: " << error.message() << "\n"; + } + }); } void send_request() @@ -92,37 +84,28 @@ private: asio::async_write(socket_, asio::buffer(request_, request_length), - [this](const std::error_code& error, std::size_t length) - { - if (!error) - { - receive_response(length); - } - else - { - std::cout << "Write failed: " << error.message() << "\n"; - } - }); + [this](const std::error_code & error, std::size_t length) { + if (!error) { + receive_response(length); + } else { + std::cout << "Write failed: " << error.message() << "\n"; + } + }); } void receive_response(std::size_t length) { asio::async_read(socket_, asio::buffer(reply_, length), - [this](const std::error_code& error, std::size_t length) - { - if (!error) - { - std::cout << "Reply: "; - std::cout.write(reply_, length); - std::cout << "\n"; - } - else - { - std::cout << "Read failed: " << error.message() << "\n"; - } - }); - + [this](const std::error_code & error, std::size_t length) { + if (!error) { + std::cout << "Reply: "; + std::cout.write(reply_, length); + std::cout << "\n"; + } else { + std::cout << "Read failed: " << error.message() << "\n"; + } + }); } asio::ssl::stream socket_; @@ -132,8 +115,8 @@ private: class Session : public std::enable_shared_from_this { public: - Session(tcp::socket socket, asio::ssl::context& context) - : socket_(std::move(socket), context) + Session(tcp::socket socket, asio::ssl::context &context) + : socket_(std::move(socket), context) { } @@ -147,42 +130,37 @@ private: { auto self(shared_from_this()); socket_.async_handshake(asio::ssl::stream_base::server, - [this, self](const std::error_code& error) - { - if (!error) - { - do_read(); - } - }); + [this, self](const std::error_code & error) { + if (!error) { + do_read(); + } + }); } void do_read() { auto self(shared_from_this()); socket_.async_read_some(asio::buffer(data_), - [this, self](const std::error_code& ec, std::size_t length) - { - if (!ec) - { - data_[length] = 0; - std::cout << "Server received: " << data_ << std::endl; - do_write(length); - } - }); + [this, self](const std::error_code & ec, std::size_t length) { + if (!ec) { + std::cout << "Server received: "; + std::cout.write(data_, length); + std::cout << std::endl; + do_write(length); + } + }); } void do_write(std::size_t length) { auto self(shared_from_this()); asio::async_write(socket_, asio::buffer(data_, length), - [this, self](const std::error_code& ec, - std::size_t /*length*/) - { - if (!ec) - { - do_read(); - } - }); + [this, self](const std::error_code & ec, + std::size_t /*length*/) { + if (!ec) { + do_read(); + } + }); } asio::ssl::stream socket_; @@ -191,13 +169,13 @@ private: class Server { public: - Server(asio::io_context& io_context, unsigned short port) - : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), - context_(asio::ssl::context::tls_server) + Server(asio::io_context &io_context, unsigned short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)), + context_(asio::ssl::context::tls_server) { context_.set_options( - asio::ssl::context::default_workarounds - | asio::ssl::context::no_sslv2); + asio::ssl::context::default_workarounds + | asio::ssl::context::no_sslv2); context_.use_certificate_chain(server_cert); context_.use_private_key(privkey, asio::ssl::context::pem); @@ -208,15 +186,13 @@ private: void do_accept() { acceptor_.async_accept( - [this](const std::error_code& error, tcp::socket socket) - { - if (!error) - { - std::make_shared(std::move(socket), context_)->start(); - } + [this](const std::error_code & error, tcp::socket socket) { + if (!error) { + std::make_shared(std::move(socket), context_)->start(); + } - do_accept(); - }); + do_accept(); + }); } tcp::acceptor acceptor_; @@ -289,7 +265,7 @@ extern "C" void app_main(void) work_threads.emplace_back(ssl_client_thread); #endif // CONFIG_EXAMPLE_CLIENT - for (auto & t : work_threads) { + for (auto &t : work_threads) { t.join(); } From 4358c3ceabb18488c2bfba58aa89657fe5e94f1b Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 10 Nov 2020 17:51:08 +1100 Subject: [PATCH 32/60] cmake: Apply cmakelint fixes * Original commit: espressif/esp-idf@e82eac4354b8b4111697656f3acce7450eeff366 --- components/asio/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt index e45f2c95f..c088644f9 100644 --- a/components/asio/CMakeLists.txt +++ b/components/asio/CMakeLists.txt @@ -1,6 +1,6 @@ set(asio_sources "asio/asio/src/asio.cpp") -if (CONFIG_ASIO_SSL_SUPPORT) +if(CONFIG_ASIO_SSL_SUPPORT) if(CONFIG_ASIO_USE_ESP_OPENSSL) list(APPEND asio_sources "asio/asio/src/asio_ssl.cpp" @@ -17,7 +17,7 @@ idf_component_register(SRCS ${asio_sources} INCLUDE_DIRS "asio/asio/include" "port/include" REQUIRES lwip) -if (CONFIG_ASIO_SSL_SUPPORT) +if(CONFIG_ASIO_SSL_SUPPORT) if(CONFIG_ASIO_USE_ESP_WOLFSSL) idf_component_get_property(wolflib esp-wolfssl COMPONENT_LIB) idf_component_get_property(wolfdir esp-wolfssl COMPONENT_DIR) From 622a360e970c4e7293085ce3e61ed86820524eeb Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 10 Nov 2020 18:40:01 +1100 Subject: [PATCH 33/60] Whitespace: Automated whitespace fixes (large commit) Apply the pre-commit hook whitespace fixes to all files in the repo. (Line endings, blank lines at end of file, trailing whitespace) * Original commit: espressif/esp-idf@66fb5a29bbdc2482d67c52e6f66b303378c9b789 --- components/asio/port/include/esp_exception.h | 2 +- examples/protocols/asio/chat_client/main/CMakeLists.txt | 2 +- examples/protocols/asio/chat_client/main/component.mk | 4 ++-- examples/protocols/asio/chat_server/main/CMakeLists.txt | 2 +- examples/protocols/asio/chat_server/main/component.mk | 4 ++-- examples/protocols/asio/ssl_client_server/main/component.mk | 4 ++-- examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt | 2 +- examples/protocols/asio/tcp_echo_server/main/component.mk | 5 ++--- examples/protocols/asio/tcp_echo_server/main/echo_server.cpp | 2 +- examples/protocols/asio/udp_echo_server/main/CMakeLists.txt | 2 +- examples/protocols/asio/udp_echo_server/main/component.mk | 4 ++-- 11 files changed, 16 insertions(+), 17 deletions(-) diff --git a/components/asio/port/include/esp_exception.h b/components/asio/port/include/esp_exception.h index a4a316013..cbf20d7a6 100644 --- a/components/asio/port/include/esp_exception.h +++ b/components/asio/port/include/esp_exception.h @@ -30,7 +30,7 @@ namespace detail { template void throw_exception(const Exception& e) { - ESP_LOGE("esp32_asio_exception", "Caught exception: %s!", e.what()); + ESP_LOGE("esp32_asio_exception", "Caught exception: %s!", e.what()); abort(); } }} diff --git a/examples/protocols/asio/chat_client/main/CMakeLists.txt b/examples/protocols/asio/chat_client/main/CMakeLists.txt index d92c9a8ae..02529cb54 100644 --- a/examples/protocols/asio/chat_client/main/CMakeLists.txt +++ b/examples/protocols/asio/chat_client/main/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "chat_client.cpp" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/chat_client/main/component.mk b/examples/protocols/asio/chat_client/main/component.mk index 61f8990c3..0adf45649 100644 --- a/examples/protocols/asio/chat_client/main/component.mk +++ b/examples/protocols/asio/chat_client/main/component.mk @@ -1,8 +1,8 @@ # # Main component makefile. # -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a # in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. # diff --git a/examples/protocols/asio/chat_server/main/CMakeLists.txt b/examples/protocols/asio/chat_server/main/CMakeLists.txt index 9042b223a..c16daff3d 100644 --- a/examples/protocols/asio/chat_server/main/CMakeLists.txt +++ b/examples/protocols/asio/chat_server/main/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "chat_server.cpp" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/chat_server/main/component.mk b/examples/protocols/asio/chat_server/main/component.mk index 61f8990c3..0adf45649 100644 --- a/examples/protocols/asio/chat_server/main/component.mk +++ b/examples/protocols/asio/chat_server/main/component.mk @@ -1,8 +1,8 @@ # # Main component makefile. # -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a # in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. # diff --git a/examples/protocols/asio/ssl_client_server/main/component.mk b/examples/protocols/asio/ssl_client_server/main/component.mk index 71869b0a3..36ed173b9 100644 --- a/examples/protocols/asio/ssl_client_server/main/component.mk +++ b/examples/protocols/asio/ssl_client_server/main/component.mk @@ -1,8 +1,8 @@ # # Main component makefile. # -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a # in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. # diff --git a/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt index ef518dc72..fcd492bca 100644 --- a/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "echo_server.cpp" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/tcp_echo_server/main/component.mk b/examples/protocols/asio/tcp_echo_server/main/component.mk index 8c8d52abc..0adf45649 100644 --- a/examples/protocols/asio/tcp_echo_server/main/component.mk +++ b/examples/protocols/asio/tcp_echo_server/main/component.mk @@ -1,9 +1,8 @@ # # Main component makefile. # -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a # in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. # - diff --git a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp index 1770fa55e..f8929bb47 100644 --- a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp +++ b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp @@ -103,4 +103,4 @@ extern "C" void app_main(void) server s(io_context, std::atoi(CONFIG_EXAMPLE_PORT)); io_context.run(); -} \ No newline at end of file +} diff --git a/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt index c7a9e3575..c692c0905 100644 --- a/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt @@ -1,2 +1,2 @@ idf_component_register(SRCS "udp_echo_server.cpp" - INCLUDE_DIRS ".") \ No newline at end of file + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/udp_echo_server/main/component.mk b/examples/protocols/asio/udp_echo_server/main/component.mk index 61f8990c3..0adf45649 100644 --- a/examples/protocols/asio/udp_echo_server/main/component.mk +++ b/examples/protocols/asio/udp_echo_server/main/component.mk @@ -1,8 +1,8 @@ # # Main component makefile. # -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a +# This Makefile can be left empty. By default, it will take the sources in the +# src/ directory, compile them and link them into lib(subdirectory_name).a # in the build directory. This behaviour is entirely configurable, # please read the ESP-IDF documents if you need to do this. # From 88d3eda156535f2893c7d344bdefda4b5bfaed8b Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Tue, 24 Nov 2020 16:40:15 +0800 Subject: [PATCH 34/60] test: remove fake binary size check in example test: the binary size check in example test was removed long time ago. Now we have updated ttfw_idf to raise exception when performance standard is not found. These fake performance check will be regarded as error. Remove them now. * Original commit: espressif/esp-idf@a908174c06fd493dfada08606eb9d8ff314f7939 --- examples/protocols/asio/chat_client/asio_chat_client_test.py | 1 - examples/protocols/asio/chat_server/asio_chat_server_test.py | 1 - examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 1 - examples/protocols/asio/udp_echo_server/asio_udp_server_test.py | 1 - 4 files changed, 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index 04c1773a0..c906beae8 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -63,7 +63,6 @@ def test_examples_protocol_asio_chat_client(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_chat_client.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_chat_client_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_chat_client_size", bin_size // 1024, dut1.TARGET) # 1. start a tcp server on the host host_ip = get_my_ip() thread1 = Thread(target=chat_server_sketch, args=(host_ip,)) diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index e319c4467..eae8f0cb4 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -20,7 +20,6 @@ def test_examples_protocol_asio_chat_server(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_chat_server_size", bin_size // 1024, dut1.TARGET) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index bc5185af2..a2fa883ef 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -21,7 +21,6 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_tcp_echo_server_size", bin_size // 1024, dut1.TARGET) # 1. start test dut1.start_app() # 2. get the server IP address diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 9eef125f4..b83d3cce2 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -21,7 +21,6 @@ def test_examples_protocol_asio_udp_server(env, extra_data): binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") bin_size = os.path.getsize(binary_file) ttfw_idf.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) - ttfw_idf.check_performance("asio_udp_echo_server_size", bin_size // 1024, dut1.TARGET) # 1. start test dut1.start_app() # 2. get the server IP address From 0d1d73eb35a9689e6464ea35d1941d4584ce7aa7 Mon Sep 17 00:00:00 2001 From: Fu Hanxi Date: Tue, 26 Jan 2021 10:49:01 +0800 Subject: [PATCH 35/60] style: format python files with isort and double-quote-string-fixer * Original commit: espressif/esp-idf@0146f258d7c8bdbc59ba6d40e8798500a30eb4ce --- .../asio/chat_client/asio_chat_client_test.py | 34 +++++++++---------- .../asio/chat_server/asio_chat_server_test.py | 18 +++++----- .../asio/ssl_client_server/example_test.py | 1 + .../tcp_echo_server/asio_tcp_server_test.py | 18 +++++----- .../udp_echo_server/asio_udp_server_test.py | 18 +++++----- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index c906beae8..a161e9436 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -1,21 +1,21 @@ -import re import os +import re import socket -from threading import Thread import time +from threading import Thread import ttfw_idf global g_client_response global g_msg_to_client -g_client_response = b"" -g_msg_to_client = b" 3XYZ" +g_client_response = b'' +g_msg_to_client = b' 3XYZ' def get_my_ip(): s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s1.connect(("8.8.8.8", 80)) + s1.connect(('8.8.8.8', 80)) my_ip = s1.getsockname()[0] s1.close() return my_ip @@ -23,14 +23,14 @@ def get_my_ip(): def chat_server_sketch(my_ip): global g_client_response - print("Starting the server on {}".format(my_ip)) + print('Starting the server on {}'.format(my_ip)) port = 2222 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(600) s.bind((my_ip, port)) s.listen(1) q,addr = s.accept() - print("connection accepted") + print('connection accepted') q.settimeout(30) q.send(g_msg_to_client) data = q.recv(1024) @@ -39,12 +39,12 @@ def chat_server_sketch(my_ip): g_client_response = data else: g_client_response = q.recv(1024) - print("received from client {}".format(g_client_response)) + print('received from client {}'.format(g_client_response)) s.close() - print("server closed") + print('server closed') -@ttfw_idf.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag='Example_WIFI') def test_examples_protocol_asio_chat_client(env, extra_data): """ steps: | @@ -57,19 +57,19 @@ def test_examples_protocol_asio_chat_client(env, extra_data): """ global g_client_response global g_msg_to_client - test_msg = "ABC" - dut1 = env.get_dut("chat_client", "examples/protocols/asio/chat_client", dut_class=ttfw_idf.ESP32DUT) + test_msg = 'ABC' + dut1 = env.get_dut('chat_client', 'examples/protocols/asio/chat_client', dut_class=ttfw_idf.ESP32DUT) # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_chat_client.bin") + binary_file = os.path.join(dut1.app.binary_path, 'asio_chat_client.bin') bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance("asio_chat_client_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.log_performance('asio_chat_client_size', '{}KB'.format(bin_size // 1024)) # 1. start a tcp server on the host host_ip = get_my_ip() thread1 = Thread(target=chat_server_sketch, args=(host_ip,)) thread1.start() # 2. start the dut test and wait till client gets IP address dut1.start_app() - dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) + dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) # 3. send host's IP to the client i.e. the `dut1` dut1.write(host_ip) # 4. client `dut1` should receive a message @@ -82,10 +82,10 @@ def test_examples_protocol_asio_chat_client(env, extra_data): print(g_client_response) # 6. evaluate host_server received this message if (g_client_response[4:7] == test_msg): - print("PASS: Received correct message") + print('PASS: Received correct message') pass else: - print("Failure!") + print('Failure!') raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(g_client_response[4:7], test_msg)) thread1.join() diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index eae8f0cb4..6577aba06 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -1,11 +1,11 @@ -import re import os +import re import socket import ttfw_idf -@ttfw_idf.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag='Example_WIFI') def test_examples_protocol_asio_chat_server(env, extra_data): """ steps: | @@ -14,16 +14,16 @@ def test_examples_protocol_asio_chat_server(env, extra_data): 3. Test connects to server and sends a test message 4. Test evaluates received test message from server """ - test_msg = b" 4ABC\n" - dut1 = env.get_dut("chat_server", "examples/protocols/asio/chat_server", dut_class=ttfw_idf.ESP32DUT) + test_msg = b' 4ABC\n' + dut1 = env.get_dut('chat_server', 'examples/protocols/asio/chat_server', dut_class=ttfw_idf.ESP32DUT) # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_chat_server.bin") + binary_file = os.path.join(dut1.app.binary_path, 'asio_chat_server.bin') bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance("asio_chat_server_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.log_performance('asio_chat_server_bin_size', '{}KB'.format(bin_size // 1024)) # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) + data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) @@ -32,10 +32,10 @@ def test_examples_protocol_asio_chat_server(env, extra_data): data = cli.recv(1024) # 4. check the message received back from the server if (data == test_msg): - print("PASS: Received correct message {}".format(data)) + print('PASS: Received correct message {}'.format(data)) pass else: - print("Failure!") + print('Failure!') raise ValueError('Wrong data received from asi tcp server: {} (expoected:{})'.format(data, test_msg)) diff --git a/examples/protocols/asio/ssl_client_server/example_test.py b/examples/protocols/asio/ssl_client_server/example_test.py index 876eb01b6..975adb850 100644 --- a/examples/protocols/asio/ssl_client_server/example_test.py +++ b/examples/protocols/asio/ssl_client_server/example_test.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals + import ttfw_idf diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index a2fa883ef..135efcd36 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -1,11 +1,11 @@ -import re import os +import re import socket import ttfw_idf -@ttfw_idf.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag='Example_WIFI') def test_examples_protocol_asio_tcp_server(env, extra_data): """ steps: | @@ -15,16 +15,16 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): 4. Test evaluates received test message from server 5. Test evaluates received test message on server stdout """ - test_msg = b"echo message from client to server" - dut1 = env.get_dut("tcp_echo_server", "examples/protocols/asio/tcp_echo_server", dut_class=ttfw_idf.ESP32DUT) + test_msg = b'echo message from client to server' + dut1 = env.get_dut('tcp_echo_server', 'examples/protocols/asio/tcp_echo_server', dut_class=ttfw_idf.ESP32DUT) # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_tcp_echo_server.bin") + binary_file = os.path.join(dut1.app.binary_path, 'asio_tcp_echo_server.bin') bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance("asio_tcp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.log_performance('asio_tcp_echo_server_bin_size', '{}KB'.format(bin_size // 1024)) # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) + data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) @@ -33,10 +33,10 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): data = cli.recv(1024) # 4. check the message received back from the server if (data == test_msg): - print("PASS: Received correct message") + print('PASS: Received correct message') pass else: - print("Failure!") + print('Failure!') raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(data, test_msg)) # 5. check the client message appears also on server terminal dut1.expect(test_msg.decode()) diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index b83d3cce2..73b15a720 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -1,11 +1,11 @@ -import re import os +import re import socket import ttfw_idf -@ttfw_idf.idf_example_test(env_tag="Example_WIFI") +@ttfw_idf.idf_example_test(env_tag='Example_WIFI') def test_examples_protocol_asio_udp_server(env, extra_data): """ steps: | @@ -15,16 +15,16 @@ def test_examples_protocol_asio_udp_server(env, extra_data): 4. Test evaluates received test message from server 5. Test evaluates received test message on server stdout """ - test_msg = b"echo message from client to server" - dut1 = env.get_dut("udp_echo_server", "examples/protocols/asio/udp_echo_server", dut_class=ttfw_idf.ESP32DUT) + test_msg = b'echo message from client to server' + dut1 = env.get_dut('udp_echo_server', 'examples/protocols/asio/udp_echo_server', dut_class=ttfw_idf.ESP32DUT) # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, "asio_udp_echo_server.bin") + binary_file = os.path.join(dut1.app.binary_path, 'asio_udp_echo_server.bin') bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance("asio_udp_echo_server_bin_size", "{}KB".format(bin_size // 1024)) + ttfw_idf.log_performance('asio_udp_echo_server_bin_size', '{}KB'.format(bin_size // 1024)) # 1. start test dut1.start_app() # 2. get the server IP address - data = dut1.expect(re.compile(r" IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"), timeout=30) + data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) # 3. create tcp client and connect to server cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) cli.settimeout(30) @@ -33,10 +33,10 @@ def test_examples_protocol_asio_udp_server(env, extra_data): data = cli.recv(1024) # 4. check the message received back from the server if (data == test_msg): - print("PASS: Received correct message") + print('PASS: Received correct message') pass else: - print("Failure!") + print('Failure!') raise ValueError('Wrong data received from asio udp server: {} (expected:{})'.format(data, test_msg)) # 5. check the client message appears also on server terminal dut1.expect(test_msg.decode()) From 9b76388163646180b892c3e8dc216ca18fa47ce2 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Fri, 12 Mar 2021 14:05:17 +0800 Subject: [PATCH 36/60] ci: run Example_GENERIC for C3 Add support for running example_GENERIC tests for C3 on label. Fix examples that fail. * Original commit: espressif/esp-idf@c85d949c1fc865d7e079554240be1144237baeb8 --- examples/protocols/asio/ssl_client_server/example_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/asio/ssl_client_server/example_test.py b/examples/protocols/asio/ssl_client_server/example_test.py index 975adb850..e819380e3 100644 --- a/examples/protocols/asio/ssl_client_server/example_test.py +++ b/examples/protocols/asio/ssl_client_server/example_test.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import ttfw_idf -@ttfw_idf.idf_example_test(env_tag='Example_GENERIC') +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3']) def test_examples_asio_ssl(env, extra_data): dut = env.get_dut('asio_ssl_client_server', 'examples/protocols/asio/ssl_client_server') From 55f95fb790a3f305e61926e59fa06a101a34b934 Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Fri, 9 Apr 2021 14:23:09 +0800 Subject: [PATCH 37/60] example_tests: CI uses ECO0 for esp32c3 tests * Original commit: espressif/esp-idf@ec4de4fe5cc9d083ea983e9a0f630c1174efaa8a --- examples/protocols/asio/ssl_client_server/sdkconfig.ci | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.ci b/examples/protocols/asio/ssl_client_server/sdkconfig.ci index f1c43e8ac..fdf00fcf6 100644 --- a/examples/protocols/asio/ssl_client_server/sdkconfig.ci +++ b/examples/protocols/asio/ssl_client_server/sdkconfig.ci @@ -4,3 +4,6 @@ CONFIG_EXAMPLE_SERVER_NAME="localhost" CONFIG_EXAMPLE_CONNECT_WIFI=n CONFIG_EXAMPLE_CONNECT_ETHERNET=n CONFIG_EXAMPLE_CLIENT_VERIFY_PEER=y +# IDF-3090 +CONFIG_ESP32C3_REV_MIN_0=y +CONFIG_ESP32C3_REV_MIN=0 From a165452ca1be096f6cfb2015d1fa48b2f600da43 Mon Sep 17 00:00:00 2001 From: Shubham Kulkarni Date: Thu, 25 Mar 2021 15:20:30 +0530 Subject: [PATCH 38/60] Split example_tests with Example_WIFI tag group into Example_OTA and Example_Protocols * Original commit: espressif/esp-idf@0a395134d45caa0cba1bebdfd2ddb6fb2cf93d75 --- examples/protocols/asio/chat_client/asio_chat_client_test.py | 2 +- examples/protocols/asio/chat_server/asio_chat_server_test.py | 2 +- examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 2 +- examples/protocols/asio/udp_echo_server/asio_udp_server_test.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py index a161e9436..eab725433 100644 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ b/examples/protocols/asio/chat_client/asio_chat_client_test.py @@ -44,7 +44,7 @@ def chat_server_sketch(my_ip): print('server closed') -@ttfw_idf.idf_example_test(env_tag='Example_WIFI') +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') def test_examples_protocol_asio_chat_client(env, extra_data): """ steps: | diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 6577aba06..82cc4c25c 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -5,7 +5,7 @@ import socket import ttfw_idf -@ttfw_idf.idf_example_test(env_tag='Example_WIFI') +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') def test_examples_protocol_asio_chat_server(env, extra_data): """ steps: | diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index 135efcd36..1b174df07 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -5,7 +5,7 @@ import socket import ttfw_idf -@ttfw_idf.idf_example_test(env_tag='Example_WIFI') +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') def test_examples_protocol_asio_tcp_server(env, extra_data): """ steps: | diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index 73b15a720..f702253ef 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -5,7 +5,7 @@ import socket import ttfw_idf -@ttfw_idf.idf_example_test(env_tag='Example_WIFI') +@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') def test_examples_protocol_asio_udp_server(env, extra_data): """ steps: | From 278b7bef3c2af29cc69988bdeaa863d794af23d6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 12 Apr 2021 17:29:49 +1000 Subject: [PATCH 39/60] partition_table: Add a "single factory app (large)" option for 1.5MB app size Needed to build some examples in their default configurations (especially ESP32-C3). Wasn't noticed until the CI checks for partition size were added. * Original commit: espressif/esp-idf@920edd4e73f4013e65917f139b3cf37c40d93b41 --- examples/protocols/asio/chat_client/sdkconfig.defaults | 6 ++++++ examples/protocols/asio/chat_server/sdkconfig.defaults | 6 ++++++ .../protocols/asio/ssl_client_server/sdkconfig.defaults | 6 ++++++ examples/protocols/asio/tcp_echo_server/sdkconfig.defaults | 6 ++++++ examples/protocols/asio/udp_echo_server/sdkconfig.defaults | 6 ++++++ 5 files changed, 30 insertions(+) diff --git a/examples/protocols/asio/chat_client/sdkconfig.defaults b/examples/protocols/asio/chat_client/sdkconfig.defaults index ce53d73ec..b02a3a3ef 100644 --- a/examples/protocols/asio/chat_client/sdkconfig.defaults +++ b/examples/protocols/asio/chat_client/sdkconfig.defaults @@ -1 +1,7 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 + +# +# Partition Table +# +# Leave some room for larger apps without needing to reduce other features +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/asio/chat_server/sdkconfig.defaults b/examples/protocols/asio/chat_server/sdkconfig.defaults index ce53d73ec..b02a3a3ef 100644 --- a/examples/protocols/asio/chat_server/sdkconfig.defaults +++ b/examples/protocols/asio/chat_server/sdkconfig.defaults @@ -1 +1,7 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 + +# +# Partition Table +# +# Leave some room for larger apps without needing to reduce other features +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.defaults b/examples/protocols/asio/ssl_client_server/sdkconfig.defaults index 7340a4467..30bba61d4 100644 --- a/examples/protocols/asio/ssl_client_server/sdkconfig.defaults +++ b/examples/protocols/asio/ssl_client_server/sdkconfig.defaults @@ -2,3 +2,9 @@ CONFIG_ASIO_SSL_SUPPORT=y CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" + +# +# Partition Table +# +# Leave some room for larger apps without needing to reduce other features +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults b/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults index ce53d73ec..b02a3a3ef 100644 --- a/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults +++ b/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults @@ -1 +1,7 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 + +# +# Partition Table +# +# Leave some room for larger apps without needing to reduce other features +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/asio/udp_echo_server/sdkconfig.defaults b/examples/protocols/asio/udp_echo_server/sdkconfig.defaults index ce53d73ec..b02a3a3ef 100644 --- a/examples/protocols/asio/udp_echo_server/sdkconfig.defaults +++ b/examples/protocols/asio/udp_echo_server/sdkconfig.defaults @@ -1 +1,7 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 + +# +# Partition Table +# +# Leave some room for larger apps without needing to reduce other features +CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y From 47d57a5b1427e9059753381ede5859527604ce1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Brudn=C3=BD?= Date: Mon, 17 May 2021 02:56:33 +0200 Subject: [PATCH 40/60] asio: update copyright notice * Original commit: espressif/esp-idf@2d0895e9a98bc7846d0ac7321f2b86b47346bf21 --- components/asio/port/include/esp_asio_config.h | 18 +++++------------- components/asio/port/include/esp_exception.h | 18 +++++------------- components/asio/port/include/openssl/conf.h | 18 +++++------------- components/asio/port/include/openssl/dh.h | 18 +++++------------- .../include/openssl/esp_asio_openssl_stubs.h | 18 +++++------------- components/asio/port/include/openssl/rsa.h | 18 +++++------------- components/asio/port/include/openssl/x509v3.h | 18 +++++------------- .../asio/port/src/esp_asio_openssl_stubs.c | 18 +++++------------- 8 files changed, 40 insertions(+), 104 deletions(-) diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index bcf8c38d4..cba316527 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -1,16 +1,8 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_ASIO_CONFIG_H_ #define _ESP_ASIO_CONFIG_H_ diff --git a/components/asio/port/include/esp_exception.h b/components/asio/port/include/esp_exception.h index cbf20d7a6..6f88866a4 100644 --- a/components/asio/port/include/esp_exception.h +++ b/components/asio/port/include/esp_exception.h @@ -1,17 +1,9 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_EXCEPTION_H_ #define _ESP_EXCEPTION_H_ diff --git a/components/asio/port/include/openssl/conf.h b/components/asio/port/include/openssl/conf.h index f125c3e6c..1ed025d93 100644 --- a/components/asio/port/include/openssl/conf.h +++ b/components/asio/port/include/openssl/conf.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_ASIO_OPENSSL_CONF_H #define _ESP_ASIO_OPENSSL_CONF_H diff --git a/components/asio/port/include/openssl/dh.h b/components/asio/port/include/openssl/dh.h index def713cfd..af72e083a 100644 --- a/components/asio/port/include/openssl/dh.h +++ b/components/asio/port/include/openssl/dh.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_ASIO_OPENSSL_DH_STUB_H #define _ESP_ASIO_OPENSSL_DH_STUB_H diff --git a/components/asio/port/include/openssl/esp_asio_openssl_stubs.h b/components/asio/port/include/openssl/esp_asio_openssl_stubs.h index fde523172..506277410 100644 --- a/components/asio/port/include/openssl/esp_asio_openssl_stubs.h +++ b/components/asio/port/include/openssl/esp_asio_openssl_stubs.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_ASIO_OPENSSL_STUBS_H #define _ESP_ASIO_OPENSSL_STUBS_H diff --git a/components/asio/port/include/openssl/rsa.h b/components/asio/port/include/openssl/rsa.h index 5d9d10e82..53018a33a 100644 --- a/components/asio/port/include/openssl/rsa.h +++ b/components/asio/port/include/openssl/rsa.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_ASIO_OPENSSL_RSA_STUB_H #define _ESP_ASIO_OPENSSL_RSA_STUB_H diff --git a/components/asio/port/include/openssl/x509v3.h b/components/asio/port/include/openssl/x509v3.h index 5ae8e7843..dad747542 100644 --- a/components/asio/port/include/openssl/x509v3.h +++ b/components/asio/port/include/openssl/x509v3.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _ESP_ASIO_OPENSSL_X509V3_STUB_H #define _ESP_ASIO_OPENSSL_X509V3_STUB_H diff --git a/components/asio/port/src/esp_asio_openssl_stubs.c b/components/asio/port/src/esp_asio_openssl_stubs.c index 6deb099ca..c766fb0d7 100644 --- a/components/asio/port/src/esp_asio_openssl_stubs.c +++ b/components/asio/port/src/esp_asio_openssl_stubs.c @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ // #include "esp_asio_config.h" From cc0f2b3cf002a35dfb4df3a08fe70c77be0d9d6e Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 20 May 2021 18:50:02 +1000 Subject: [PATCH 41/60] asio coap: If LWIP IPV6 is disabled, automatically don't build asio & coap - Removes need to manually exclude these components as shown at https://github.com/espressif/esp-idf/issues/3781#issuecomment-825742378 - Hide the config for these components if IPV6 is disabled - The components are still included in the build, but with no source files * Original commit: espressif/esp-idf@e305f2938278c2a39e75c21a3ed59d8f4d4e62fa --- components/asio/CMakeLists.txt | 8 ++++++++ components/asio/Kconfig | 2 ++ components/asio/component.mk | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt index c088644f9..e2421fead 100644 --- a/components/asio/CMakeLists.txt +++ b/components/asio/CMakeLists.txt @@ -1,3 +1,11 @@ +if(NOT CONFIG_LWIP_IPV6 AND NOT CMAKE_BUILD_EARLY_EXPANSION) + # note: the component is still included in the build so it can become visible again in config + # without needing to re-run CMake. However no source or header files are built. + message(STATUS "IPV6 support is disabled so the asio component will not be built") + idf_component_register() + return() +endif() + set(asio_sources "asio/asio/src/asio.cpp") if(CONFIG_ASIO_SSL_SUPPORT) diff --git a/components/asio/Kconfig b/components/asio/Kconfig index 582410e7c..3b488a0c3 100644 --- a/components/asio/Kconfig +++ b/components/asio/Kconfig @@ -1,4 +1,6 @@ menu "ESP-ASIO" + visible if LWIP_IPV6 + config ASIO_SSL_SUPPORT bool "Enable SSL/TLS support of ASIO" default n diff --git a/components/asio/component.mk b/components/asio/component.mk index 30b2907bb..c93c8dbb9 100644 --- a/components/asio/component.mk +++ b/components/asio/component.mk @@ -1,3 +1,5 @@ +ifdef CONFIG_LWIP_IPV6 + COMPONENT_ADD_INCLUDEDIRS := asio/asio/include port/include COMPONENT_PRIV_INCLUDEDIRS := private_include COMPONENT_SRCDIRS := asio/asio/src port/src @@ -7,3 +9,5 @@ COMPONENT_OBJEXCLUDE := asio/asio/src/asio_ssl.o port/src/esp_asio_openssl_stubs endif COMPONENT_SUBMODULES += asio + +endif # CONFIG_LWIP_IPV6 From cb2375827bdb78e561d96e7458259b7c17171a56 Mon Sep 17 00:00:00 2001 From: Chen Yudong Date: Tue, 25 May 2021 15:02:47 +0800 Subject: [PATCH 42/60] CI: fix connection failures in asio example tests * Original commit: espressif/esp-idf@b3b71bc8abab24e97471e8369c7d851141d56260 --- examples/protocols/asio/chat_server/asio_chat_server_test.py | 1 + examples/protocols/asio/chat_server/main/chat_server.cpp | 2 ++ examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py | 1 + examples/protocols/asio/tcp_echo_server/main/echo_server.cpp | 2 ++ examples/protocols/asio/udp_echo_server/asio_udp_server_test.py | 1 + .../protocols/asio/udp_echo_server/main/udp_echo_server.cpp | 2 ++ 6 files changed, 9 insertions(+) diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py index 82cc4c25c..5e92ea00e 100644 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ b/examples/protocols/asio/chat_server/asio_chat_server_test.py @@ -25,6 +25,7 @@ def test_examples_protocol_asio_chat_server(env, extra_data): # 2. get the server IP address data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) # 3. create tcp client and connect to server + dut1.expect('ASIO engine is up and running', timeout=1) cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) cli.connect((data[0], 2222)) diff --git a/examples/protocols/asio/chat_server/main/chat_server.cpp b/examples/protocols/asio/chat_server/main/chat_server.cpp index edcc1278c..6ea7c7be4 100644 --- a/examples/protocols/asio/chat_server/main/chat_server.cpp +++ b/examples/protocols/asio/chat_server/main/chat_server.cpp @@ -225,5 +225,7 @@ extern "C" void app_main(void) servers.emplace_back(io_context, endpoint); } + std::cout << "ASIO engine is up and running" << std::endl; + io_context.run(); } diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py index 1b174df07..0293350ab 100644 --- a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py +++ b/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py @@ -26,6 +26,7 @@ def test_examples_protocol_asio_tcp_server(env, extra_data): # 2. get the server IP address data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) # 3. create tcp client and connect to server + dut1.expect('ASIO engine is up and running', timeout=1) cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli.settimeout(30) cli.connect((data[0], 2222)) diff --git a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp index f8929bb47..5c520aeac 100644 --- a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp +++ b/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp @@ -102,5 +102,7 @@ extern "C" void app_main(void) server s(io_context, std::atoi(CONFIG_EXAMPLE_PORT)); + std::cout << "ASIO engine is up and running" << std::endl; + io_context.run(); } diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py index f702253ef..b2c2a5f75 100644 --- a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py +++ b/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py @@ -26,6 +26,7 @@ def test_examples_protocol_asio_udp_server(env, extra_data): # 2. get the server IP address data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) # 3. create tcp client and connect to server + dut1.expect('ASIO engine is up and running', timeout=1) cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) cli.settimeout(30) cli.connect((data[0], 2222)) diff --git a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp index 14eef948e..5e21d5100 100644 --- a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp +++ b/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp @@ -84,5 +84,7 @@ extern "C" void app_main(void) server s(io_context, std::atoi(CONFIG_EXAMPLE_PORT)); + std::cout << "ASIO engine is up and running" << std::endl; + io_context.run(); } From 91262baede0f9dcd3ef67dba0e3554f467c319d8 Mon Sep 17 00:00:00 2001 From: Suren Gabrielyan Date: Fri, 2 Jul 2021 08:58:47 +0400 Subject: [PATCH 43/60] examples: Asio tests consolidation to use loopback interface Closes IDF-3072 * Original commit: espressif/esp-idf@a06357ab62e479ee29eab4cad134b9a2fc43f65c --- .../{chat_client => asio_chat}/CMakeLists.txt | 2 +- .../asio/{chat_server => asio_chat}/Makefile | 2 +- examples/protocols/asio/asio_chat/README.md | 62 ++++++ .../protocols/asio/asio_chat/example_test.py | 29 +++ .../asio/asio_chat/main/CMakeLists.txt | 2 + .../asio/asio_chat/main/Kconfig.projbuild | 39 ++++ .../asio/asio_chat/main/asio_chat.cpp | 119 ++++++++++++ .../main/chat_message.hpp | 0 .../protocols/asio/asio_chat/main/client.hpp | 126 ++++++++++++ .../main/component.mk | 0 .../main/server.hpp} | 169 +++++++--------- .../protocols/asio/asio_chat/sdkconfig.ci | 6 + .../asio/asio_chat/sdkconfig.defaults | 2 + examples/protocols/asio/chat_client/Makefile | 9 - examples/protocols/asio/chat_client/README.md | 20 -- .../asio/chat_client/asio_chat_client_test.py | 94 --------- .../asio/chat_client/main/CMakeLists.txt | 2 - .../asio/chat_client/main/Kconfig.projbuild | 16 -- .../asio/chat_client/main/chat_client.cpp | 183 ------------------ .../asio/chat_client/sdkconfig.defaults | 7 - .../protocols/asio/chat_server/CMakeLists.txt | 10 - examples/protocols/asio/chat_server/README.md | 23 --- .../asio/chat_server/asio_chat_server_test.py | 44 ----- .../asio/chat_server/main/CMakeLists.txt | 2 - .../asio/chat_server/main/Kconfig.projbuild | 9 - .../asio/chat_server/main/chat_message.hpp | 91 --------- .../asio/chat_server/main/component.mk | 8 - .../asio/chat_server/sdkconfig.defaults | 7 - 28 files changed, 457 insertions(+), 626 deletions(-) rename examples/protocols/asio/{chat_client => asio_chat}/CMakeLists.txt (94%) rename examples/protocols/asio/{chat_server => asio_chat}/Makefile (87%) create mode 100644 examples/protocols/asio/asio_chat/README.md create mode 100644 examples/protocols/asio/asio_chat/example_test.py create mode 100644 examples/protocols/asio/asio_chat/main/CMakeLists.txt create mode 100644 examples/protocols/asio/asio_chat/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/asio_chat/main/asio_chat.cpp rename examples/protocols/asio/{chat_client => asio_chat}/main/chat_message.hpp (100%) create mode 100644 examples/protocols/asio/asio_chat/main/client.hpp rename examples/protocols/asio/{chat_client => asio_chat}/main/component.mk (100%) rename examples/protocols/asio/{chat_server/main/chat_server.cpp => asio_chat/main/server.hpp} (52%) create mode 100644 examples/protocols/asio/asio_chat/sdkconfig.ci create mode 100644 examples/protocols/asio/asio_chat/sdkconfig.defaults delete mode 100644 examples/protocols/asio/chat_client/Makefile delete mode 100644 examples/protocols/asio/chat_client/README.md delete mode 100644 examples/protocols/asio/chat_client/asio_chat_client_test.py delete mode 100644 examples/protocols/asio/chat_client/main/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_client/main/Kconfig.projbuild delete mode 100644 examples/protocols/asio/chat_client/main/chat_client.cpp delete mode 100644 examples/protocols/asio/chat_client/sdkconfig.defaults delete mode 100644 examples/protocols/asio/chat_server/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_server/README.md delete mode 100644 examples/protocols/asio/chat_server/asio_chat_server_test.py delete mode 100644 examples/protocols/asio/chat_server/main/CMakeLists.txt delete mode 100644 examples/protocols/asio/chat_server/main/Kconfig.projbuild delete mode 100644 examples/protocols/asio/chat_server/main/chat_message.hpp delete mode 100644 examples/protocols/asio/chat_server/main/component.mk delete mode 100644 examples/protocols/asio/chat_server/sdkconfig.defaults diff --git a/examples/protocols/asio/chat_client/CMakeLists.txt b/examples/protocols/asio/asio_chat/CMakeLists.txt similarity index 94% rename from examples/protocols/asio/chat_client/CMakeLists.txt rename to examples/protocols/asio/asio_chat/CMakeLists.txt index ddcc068ba..483b43d70 100644 --- a/examples/protocols/asio/chat_client/CMakeLists.txt +++ b/examples/protocols/asio/asio_chat/CMakeLists.txt @@ -7,4 +7,4 @@ cmake_minimum_required(VERSION 3.5) set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(asio_chat_client) +project(asio_chat) diff --git a/examples/protocols/asio/chat_server/Makefile b/examples/protocols/asio/asio_chat/Makefile similarity index 87% rename from examples/protocols/asio/chat_server/Makefile rename to examples/protocols/asio/asio_chat/Makefile index a7656889f..93950cb9a 100644 --- a/examples/protocols/asio/chat_server/Makefile +++ b/examples/protocols/asio/asio_chat/Makefile @@ -2,7 +2,7 @@ # This is a project Makefile. It is assumed the directory this Makefile resides in is a # project subdirectory. # -PROJECT_NAME := asio_chat_server +PROJECT_NAME := asio_chat EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common diff --git a/examples/protocols/asio/asio_chat/README.md b/examples/protocols/asio/asio_chat/README.md new file mode 100644 index 000000000..4848b457b --- /dev/null +++ b/examples/protocols/asio/asio_chat/README.md @@ -0,0 +1,62 @@ + +# Asio chat client and server examples + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +The application aims to demonstrate a simple use of Asio library in different modes. +In project settings it could be configured to run either a Asio chat server, a Asio chat client, or both. + +## How to use example + +The example is configured by default as an Asio chat client. + +Note that the example uses string representation of IP addresses and ports. + +You can find the upstream asio chat implementation [here] https://github.com/chriskohlhoff/asio/tree/master/asio/src/examples/cpp11/chat + +### Asio Client + +In the client mode, the example connects to the configured address, sends the message, which was inserted as an input in the terminal, and receives a response. + +### Asio Server + +In the server mode, Asio chat server with a specified port number is created and being polled till a connection request from the client arrives. +Chat server echoes a message (received from any client) to all connected clients. + +## Configure the project + +``` +idf.py menuconfig +``` + +Set following parameters under Example Configuration Options: + +* Set `EXAMPLE_CHAT_SERVER` to use the example as an ASIO chat server + * Configure `EXAMPLE_CHAT_SERVER_BIND_PORT` to the port number. + +* Set `EXAMPLE_CHAT_CLIENT` to use the example as an ASIO chat client + * Configure `EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS` to a string representation of the address to connect the client to. + * Configure `EXAMPLE_CHAT_CLIENT_CONNECT_PORT` to the port number. + +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more d etails. + +## Running the example in server mode + +- Configure the example according "Configure the project" section. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet (note the IP address). +- Connect to the server using multiple clients, for example using any option below. + - build and run asio chat client on your host machine + - run chat_client asio example on ESP platform + - since chat messages consists of ASCII size and message, it is possible to + netcat `nc IP PORT` and type for example ` 4ABC` to transmit 'ABC\n' + +## Running the example in client mode + +- Configure the example according "Configure the project" section. +- Start chat server either on host machine or as another ESP device running chat_server example. +- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. +- Wait for the board to connect to WiFi or Ethernet. +- Receive and send messages to/from other clients on stdin/stdout via serial terminal. + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/asio_chat/example_test.py b/examples/protocols/asio/asio_chat/example_test.py new file mode 100644 index 000000000..7dc5c7c2b --- /dev/null +++ b/examples/protocols/asio/asio_chat/example_test.py @@ -0,0 +1,29 @@ +# This example code is in the Public Domain (or CC0 licensed, at your option.) + +# Unless required by applicable law or agreed to in writing, this +# software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. + +# -*- coding: utf-8 -*- + +from __future__ import print_function, unicode_literals + +import re + +import ttfw_idf + + +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC') +def test_examples_asio_chat(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None + msg = 'asio-chat: received hi' + dut = env.get_dut('asio_chat', 'examples/protocols/asio/asio_chat') + # start the test and expect the client to receive back it's original data + dut.start_app() + dut.expect(re.compile(r'{}'.format('Waiting for input')), timeout=30) + dut.write(msg) + dut.write('exit') + dut.expect(re.compile(r'{}'.format(msg)), timeout=30) + + +if __name__ == '__main__': + test_examples_asio_chat() diff --git a/examples/protocols/asio/asio_chat/main/CMakeLists.txt b/examples/protocols/asio/asio_chat/main/CMakeLists.txt new file mode 100644 index 000000000..8f1954423 --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "asio_chat.cpp" + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/asio_chat/main/Kconfig.projbuild b/examples/protocols/asio/asio_chat/main/Kconfig.projbuild new file mode 100644 index 000000000..99f08cdbd --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/Kconfig.projbuild @@ -0,0 +1,39 @@ +menu "Example Configuration" + + config EXAMPLE_CHAT_SERVER + bool "Asio example chat server" + default n + help + This example will setup a chat server, binds it to the specified address + and starts listening. + + if EXAMPLE_CHAT_SERVER + config EXAMPLE_CHAT_SERVER_BIND_PORT + string "Asio example server bind port" + default "3344" + help + Server listener's socket would be bound to this port. + endif + + config EXAMPLE_CHAT_CLIENT + bool "Asio example chat client" + default y + help + This example will setup an asio chat client. + and sends the data. + + if EXAMPLE_CHAT_CLIENT + config EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS + string "Client connection address" + default "192.168.0.1" + help + Client's socket would connect to this address/host. + + config EXAMPLE_CHAT_CLIENT_CONNECT_PORT + string "Client connection port" + default "3344" + help + Client's connection port. + endif + +endmenu diff --git a/examples/protocols/asio/asio_chat/main/asio_chat.cpp b/examples/protocols/asio/asio_chat/main/asio_chat.cpp new file mode 100644 index 000000000..be2329d15 --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/asio_chat.cpp @@ -0,0 +1,119 @@ +/* ASIO chat server client example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "protocol_examples_common.h" +#include "esp_log.h" +#include "esp_event.h" +#include "nvs_flash.h" +#include "server.hpp" +#include "client.hpp" +#include +#include + +using asio::ip::tcp; + +static const char *TAG = "asio-chat"; + +// This variable is necessary for `python test` execution, it provides synchronisation between server/client(as server should be started before client) +std::mutex server_ready; + +#ifdef CONFIG_EXAMPLE_CHAT_CLIENT +static void get_string(char *line, size_t size) +{ + int count = 0; + while (count < size) { + int c = fgetc(stdin); + if (c == '\n') { + line[count] = '\0'; + break; + } else if (c > 0 && c < 127) { + line[count] = c; + ++count; + } + vTaskDelay(10 / portTICK_PERIOD_MS); + } +} + +void start_client(void) +{ + const std::string port(CONFIG_EXAMPLE_CHAT_CLIENT_CONNECT_PORT); + const std::string name(CONFIG_EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS); + asio::io_context io_context; + char line[128]; + + tcp::resolver resolver(io_context); + auto endpoints = resolver.resolve(name, port); + chat_client c(io_context, endpoints); +#ifdef CONFIG_EXAMPLE_CHAT_SERVER + std::lock_guard guard(server_ready); +#endif + std::thread t([&io_context]() { try { + io_context.run(); + } catch (const std::exception &e) { + ESP_LOGE(TAG, "Exception occured during client thread execution %s", e.what()); + } + catch (...) { + ESP_LOGE(TAG, "Unknown exception"); + }}); + do { + ESP_LOGI(TAG, "CLIENT: Waiting for input"); + get_string(line, sizeof(line)); + + chat_message msg; + msg.body_length(std::strlen(line)); + std::memcpy(msg.body(), line, msg.body_length()); + msg.encode_header(); + c.write(msg); + sleep(1); + } while (strcmp(line, "exit") != 0); + + c.close(); + t.join(); +} +#endif // CONFIG_EXAMPLE_CHAT_CLIENT + +extern "C" void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + esp_netif_init(); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + try { +#ifdef CONFIG_EXAMPLE_CHAT_SERVER + asio::io_context io_context; + chat_server server(io_context, tcp::endpoint(tcp::v4(), std::atoi(CONFIG_EXAMPLE_CHAT_SERVER_BIND_PORT))); + std::thread t = std::thread([&io_context]() { // Chat server starting here + try { + io_context.run(); + } catch (const std::exception &e) { + ESP_LOGE(TAG, "Exception occured during server thread execution %s", e.what()); + } + catch (...) { + ESP_LOGE(TAG, "Unknown exception"); + }});; +#endif +#ifdef CONFIG_EXAMPLE_CHAT_CLIENT + start_client(); +#endif +#ifdef CONFIG_EXAMPLE_CHAT_SERVER + t.join(); +#endif + } catch (const std::exception &e) { + ESP_LOGE(TAG, "Exception occured during run %s", e.what()); + } catch (...) { + ESP_LOGE(TAG, "Unknown exception"); + } + ESP_ERROR_CHECK(example_disconnect()); +} diff --git a/examples/protocols/asio/chat_client/main/chat_message.hpp b/examples/protocols/asio/asio_chat/main/chat_message.hpp similarity index 100% rename from examples/protocols/asio/chat_client/main/chat_message.hpp rename to examples/protocols/asio/asio_chat/main/chat_message.hpp diff --git a/examples/protocols/asio/asio_chat/main/client.hpp b/examples/protocols/asio/asio_chat/main/client.hpp new file mode 100644 index 000000000..09baece98 --- /dev/null +++ b/examples/protocols/asio/asio_chat/main/client.hpp @@ -0,0 +1,126 @@ +// +// client.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef CHAT_CLIENT_HPP +#define CHAT_CLIENT_HPP + +#include +#include "asio.hpp" +#include "chat_message.hpp" + +typedef std::deque chat_message_queue; + +class chat_client +{ +public: + chat_client(asio::io_context& io_context, + const asio::ip::tcp::resolver::results_type& endpoints) + : io_context_(io_context), + socket_(io_context) + { + do_connect(endpoints); + } + + void write(const chat_message& msg) + { + asio::post(io_context_, + [this, msg]() + { + bool write_in_progress = !write_msgs_.empty(); + write_msgs_.push_back(msg); + if (!write_in_progress) + { + do_write(); + } + }); + } + + void close() + { + asio::post(io_context_, [this]() { socket_.close(); }); + } + +private: +void do_connect(const asio::ip::tcp::resolver::results_type& endpoints) + { + asio::async_connect(socket_, endpoints, + [this](std::error_code ec, asio::ip::tcp::endpoint) + { + if (!ec) + { + do_read_header(); + } + }); + } + + void do_read_header() + { + asio::async_read(socket_, + asio::buffer(read_msg_.data(), chat_message::header_length), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec && read_msg_.decode_header()) + { + do_read_body(); + } + else + { + socket_.close(); + } + }); + } + + void do_read_body() + { + asio::async_read(socket_, + asio::buffer(read_msg_.body(), read_msg_.body_length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + do_read_header(); + } + else + { + socket_.close(); + } + }); + } + + void do_write() + { + asio::async_write(socket_, + asio::buffer(write_msgs_.front().data(), + write_msgs_.front().length()), + [this](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + write_msgs_.pop_front(); + if (!write_msgs_.empty()) + { + do_write(); + } + } + else + { + socket_.close(); + } + }); + } + +private: + asio::io_context& io_context_; + asio::ip::tcp::socket socket_; + chat_message read_msg_; + chat_message_queue write_msgs_; +}; + +#endif // CHAT_CLIENT_HPP diff --git a/examples/protocols/asio/chat_client/main/component.mk b/examples/protocols/asio/asio_chat/main/component.mk similarity index 100% rename from examples/protocols/asio/chat_client/main/component.mk rename to examples/protocols/asio/asio_chat/main/component.mk diff --git a/examples/protocols/asio/chat_server/main/chat_server.cpp b/examples/protocols/asio/asio_chat/main/server.hpp similarity index 52% rename from examples/protocols/asio/chat_server/main/chat_server.cpp rename to examples/protocols/asio/asio_chat/main/server.hpp index 6ea7c7be4..450e255a4 100644 --- a/examples/protocols/asio/chat_server/main/chat_server.cpp +++ b/examples/protocols/asio/asio_chat/main/server.hpp @@ -1,5 +1,5 @@ // -// chat_server.cpp +// server.hpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) @@ -8,28 +8,25 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include -#include -#include +#ifndef CHAT_SERVER_HPP +#define CHAT_SERVER_HPP + #include -#include #include +#include #include #include "asio.hpp" #include "chat_message.hpp" -#include "protocol_examples_common.h" -#include "esp_event.h" -#include "nvs_flash.h" - - -using asio::ip::tcp; //---------------------------------------------------------------------- typedef std::deque chat_message_queue; +extern std::mutex server_ready; + //---------------------------------------------------------------------- + class chat_participant { public: @@ -74,12 +71,13 @@ private: //---------------------------------------------------------------------- + class chat_session : public chat_participant, public std::enable_shared_from_this { public: - chat_session(tcp::socket socket, chat_room& room) + chat_session(asio::ip::tcp::socket socket, chat_room& room) : socket_(std::move(socket)), room_(room) { @@ -117,56 +115,57 @@ private: { room_.leave(shared_from_this()); } - }); - } + }); + } - void do_read_body() - { - auto self(shared_from_this()); - asio::async_read(socket_, - asio::buffer(read_msg_.body(), read_msg_.body_length()), - [this, self](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - room_.deliver(read_msg_); - do_read_header(); - } - else - { - room_.leave(shared_from_this()); - } - }); - } + void do_read_body() + { + auto self(shared_from_this()); + asio::async_read(socket_, + asio::buffer(read_msg_.body(), read_msg_.body_length()), + [this, self](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + ESP_LOGD("asio-chat:", "%s", read_msg_.body()); + room_.deliver(read_msg_); + do_read_header(); + } + else + { + room_.leave(shared_from_this()); + } + }); + } - void do_write() - { - auto self(shared_from_this()); - asio::async_write(socket_, - asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - [this, self](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - do_write(); - } - } - else - { - room_.leave(shared_from_this()); - } - }); - } + void do_write() + { + auto self(shared_from_this()); + asio::async_write(socket_, + asio::buffer(write_msgs_.front().data(), + write_msgs_.front().length()), + [this, self](std::error_code ec, std::size_t /*length*/) + { + if (!ec) + { + write_msgs_.pop_front(); + if (!write_msgs_.empty()) + { + do_write(); + } + } + else + { + room_.leave(shared_from_this()); + } + }); + } - tcp::socket socket_; - chat_room& room_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; + asio::ip::tcp::socket socket_; + chat_room& room_; + chat_message read_msg_; + chat_message_queue write_msgs_; + }; //---------------------------------------------------------------------- @@ -174,7 +173,7 @@ class chat_server { public: chat_server(asio::io_context& io_context, - const tcp::endpoint& endpoint) + const asio::ip::tcp::endpoint& endpoint) : acceptor_(io_context, endpoint) { do_accept(); @@ -183,49 +182,21 @@ public: private: void do_accept() { + std::lock_guard guard(server_ready); acceptor_.async_accept( - [this](std::error_code ec, tcp::socket socket) - { - if (!ec) - { - std::make_shared(std::move(socket), room_)->start(); - } + [this](std::error_code ec, asio::ip::tcp::socket socket) + { + if (!ec) + { + std::make_shared(std::move(socket), room_)->start(); + } - do_accept(); - }); + do_accept(); + }); } - tcp::acceptor acceptor_; + asio::ip::tcp::acceptor acceptor_; chat_room room_; }; -//---------------------------------------------------------------------- - -extern "C" void app_main(void) -{ - ESP_ERROR_CHECK(nvs_flash_init()); - esp_netif_init(); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - /* This helper function configures blocking UART I/O */ - ESP_ERROR_CHECK(example_configure_stdin_stdout()); - - asio::io_context io_context; - - std::list servers; - - { - tcp::endpoint endpoint(tcp::v4(), std::atoi(CONFIG_EXAMPLE_PORT)); - servers.emplace_back(io_context, endpoint); - } - - std::cout << "ASIO engine is up and running" << std::endl; - - io_context.run(); -} +#endif // CHAT_SERVER_HPP diff --git a/examples/protocols/asio/asio_chat/sdkconfig.ci b/examples/protocols/asio/asio_chat/sdkconfig.ci new file mode 100644 index 000000000..4829992d0 --- /dev/null +++ b/examples/protocols/asio/asio_chat/sdkconfig.ci @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=n +CONFIG_EXAMPLE_CHAT_CLIENT=y +CONFIG_EXAMPLE_CHAT_SERVER=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y +CONFIG_EXAMPLE_CHAT_CLIENT_CONNECT_ADDRESS="localhost" diff --git a/examples/protocols/asio/asio_chat/sdkconfig.defaults b/examples/protocols/asio/asio_chat/sdkconfig.defaults new file mode 100644 index 000000000..3a66e33fd --- /dev/null +++ b/examples/protocols/asio/asio_chat/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 +CONFIG_COMPILER_CXX_EXCEPTIONS=y diff --git a/examples/protocols/asio/chat_client/Makefile b/examples/protocols/asio/chat_client/Makefile deleted file mode 100644 index 90197676a..000000000 --- a/examples/protocols/asio/chat_client/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# -PROJECT_NAME := asio_chat_client - -EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/chat_client/README.md b/examples/protocols/asio/chat_client/README.md deleted file mode 100644 index bcc2bd4d5..000000000 --- a/examples/protocols/asio/chat_client/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Asio chat client example - -Simple Asio chat client using WiFi STA or Ethernet. - -## Example workflow - -- Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio chat client connects to the corresponding server whose port number and IP are defined through the project configuration menu. -- Chat client receives all messages from other chat clients, also it sends message received from stdin using `idf.py -p PORT monitor`. - -## Running the example - -- Open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. -- Set server IP address and port number in menuconfig, "Example configuration". -- Start chat server either on host machine or as another ESP device running chat_server example. -- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. -- Wait for the board to connect to WiFi or Ethernet. -- Receive and send messages to/from other clients on stdin/stdout via serial terminal. - -See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/chat_client/asio_chat_client_test.py b/examples/protocols/asio/chat_client/asio_chat_client_test.py deleted file mode 100644 index eab725433..000000000 --- a/examples/protocols/asio/chat_client/asio_chat_client_test.py +++ /dev/null @@ -1,94 +0,0 @@ -import os -import re -import socket -import time -from threading import Thread - -import ttfw_idf - -global g_client_response -global g_msg_to_client - -g_client_response = b'' -g_msg_to_client = b' 3XYZ' - - -def get_my_ip(): - s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s1.connect(('8.8.8.8', 80)) - my_ip = s1.getsockname()[0] - s1.close() - return my_ip - - -def chat_server_sketch(my_ip): - global g_client_response - print('Starting the server on {}'.format(my_ip)) - port = 2222 - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(600) - s.bind((my_ip, port)) - s.listen(1) - q,addr = s.accept() - print('connection accepted') - q.settimeout(30) - q.send(g_msg_to_client) - data = q.recv(1024) - # check if received initial empty message - if (len(data) > 4): - g_client_response = data - else: - g_client_response = q.recv(1024) - print('received from client {}'.format(g_client_response)) - s.close() - print('server closed') - - -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') -def test_examples_protocol_asio_chat_client(env, extra_data): - """ - steps: | - 1. Test to start simple tcp server - 2. `dut1` joins AP - 3. Test injects server IP to `dut1`via stdin - 4. Test evaluates `dut1` receives a message server placed - 5. Test injects a message to `dut1` to be sent as chat_client message - 6. Test evaluates received test message in host server - """ - global g_client_response - global g_msg_to_client - test_msg = 'ABC' - dut1 = env.get_dut('chat_client', 'examples/protocols/asio/chat_client', dut_class=ttfw_idf.ESP32DUT) - # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, 'asio_chat_client.bin') - bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance('asio_chat_client_size', '{}KB'.format(bin_size // 1024)) - # 1. start a tcp server on the host - host_ip = get_my_ip() - thread1 = Thread(target=chat_server_sketch, args=(host_ip,)) - thread1.start() - # 2. start the dut test and wait till client gets IP address - dut1.start_app() - dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) - # 3. send host's IP to the client i.e. the `dut1` - dut1.write(host_ip) - # 4. client `dut1` should receive a message - dut1.expect(g_msg_to_client[4:].decode()) # Strip out the front 4 bytes of message len (see chat_message protocol) - # 5. write test message from `dut1` chat_client to the server - dut1.write(test_msg) - while len(g_client_response) == 0: - time.sleep(1) - g_client_response = g_client_response.decode() - print(g_client_response) - # 6. evaluate host_server received this message - if (g_client_response[4:7] == test_msg): - print('PASS: Received correct message') - pass - else: - print('Failure!') - raise ValueError('Wrong data received from asi tcp server: {} (expected:{})'.format(g_client_response[4:7], test_msg)) - thread1.join() - - -if __name__ == '__main__': - test_examples_protocol_asio_chat_client() diff --git a/examples/protocols/asio/chat_client/main/CMakeLists.txt b/examples/protocols/asio/chat_client/main/CMakeLists.txt deleted file mode 100644 index 02529cb54..000000000 --- a/examples/protocols/asio/chat_client/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "chat_client.cpp" - INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/chat_client/main/Kconfig.projbuild b/examples/protocols/asio/chat_client/main/Kconfig.projbuild deleted file mode 100644 index 34d9e93cf..000000000 --- a/examples/protocols/asio/chat_client/main/Kconfig.projbuild +++ /dev/null @@ -1,16 +0,0 @@ -menu "Example Configuration" - - config EXAMPLE_PORT - string "Asio example server port number" - default "2222" - help - Port number used by Asio example. - - config EXAMPLE_SERVER_IP - string "Asio example server ip" - default "FROM_STDIN" - help - Asio example server ip for this client to connect to. - Leave default "FROM_STDIN" to enter the server address via serial terminal. - -endmenu diff --git a/examples/protocols/asio/chat_client/main/chat_client.cpp b/examples/protocols/asio/chat_client/main/chat_client.cpp deleted file mode 100644 index 10ab860c9..000000000 --- a/examples/protocols/asio/chat_client/main/chat_client.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// -// chat_client.cpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include -#include -#include -#include "asio.hpp" -#include "chat_message.hpp" -#include "protocol_examples_common.h" -#include "esp_event.h" -#include "nvs_flash.h" - -using asio::ip::tcp; - -typedef std::deque chat_message_queue; - -class chat_client -{ -public: - chat_client(asio::io_context& io_context, - const tcp::resolver::results_type& endpoints) - : io_context_(io_context), - socket_(io_context) - { - do_connect(endpoints); - } - - void write(const chat_message& msg) - { - asio::post(io_context_, - [this, msg]() - { - bool write_in_progress = !write_msgs_.empty(); - write_msgs_.push_back(msg); - if (!write_in_progress) - { - do_write(); - } - }); - } - - void close() - { - asio::post(io_context_, [this]() { socket_.close(); }); - } - -private: - void do_connect(const tcp::resolver::results_type& endpoints) - { - asio::async_connect(socket_, endpoints, - [this](std::error_code ec, tcp::endpoint) - { - if (!ec) - { - do_read_header(); - } - }); - } - - void do_read_header() - { - asio::async_read(socket_, - asio::buffer(read_msg_.data(), chat_message::header_length), - [this](std::error_code ec, std::size_t /*length*/) - { - if (!ec && read_msg_.decode_header()) - { - do_read_body(); - } - else - { - socket_.close(); - } - }); - } - - void do_read_body() - { - asio::async_read(socket_, - asio::buffer(read_msg_.body(), read_msg_.body_length()), - [this](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - std::cout.write(read_msg_.body(), read_msg_.body_length()); - std::cout << "\n"; - do_read_header(); - } - else - { - socket_.close(); - } - }); - } - - void do_write() - { - asio::async_write(socket_, - asio::buffer(write_msgs_.front().data(), - write_msgs_.front().length()), - [this](std::error_code ec, std::size_t /*length*/) - { - if (!ec) - { - write_msgs_.pop_front(); - if (!write_msgs_.empty()) - { - do_write(); - } - } - else - { - socket_.close(); - } - }); - } - -private: - asio::io_context& io_context_; - tcp::socket socket_; - chat_message read_msg_; - chat_message_queue write_msgs_; -}; - -void read_line(char * line, int max_chars); - - -extern "C" void app_main(void) -{ - ESP_ERROR_CHECK(nvs_flash_init()); - esp_netif_init(); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. - * Read "Establishing Wi-Fi or Ethernet Connection" section in - * examples/protocols/README.md for more information about this function. - */ - ESP_ERROR_CHECK(example_connect()); - - /* This helper function configures blocking UART I/O */ - ESP_ERROR_CHECK(example_configure_stdin_stdout()); - - std::string name(CONFIG_EXAMPLE_SERVER_IP); - std::string port(CONFIG_EXAMPLE_PORT); - char line[chat_message::max_body_length + 1] = { 0 }; - - if (name == "FROM_STDIN") { - std::cout << "Please enter ip address of chat server" << std::endl; - if (std::cin.getline(line, chat_message::max_body_length + 1)) { - name = line; - std::cout << "Chat server IP:" << name << std::endl; - } - } - - asio::io_context io_context; - tcp::resolver resolver(io_context); - auto endpoints = resolver.resolve(name, port); - - chat_client c(io_context, endpoints); - - std::thread t([&io_context](){ io_context.run(); }); - - while (std::cin.getline(line, chat_message::max_body_length + 1) && std::string(line) != "exit") { - chat_message msg; - msg.body_length(std::strlen(line)); - std::memcpy(msg.body(), line, msg.body_length()); - msg.encode_header(); - c.write(msg); - } - - c.close(); - t.join(); - - ESP_ERROR_CHECK(example_disconnect()); -} diff --git a/examples/protocols/asio/chat_client/sdkconfig.defaults b/examples/protocols/asio/chat_client/sdkconfig.defaults deleted file mode 100644 index b02a3a3ef..000000000 --- a/examples/protocols/asio/chat_client/sdkconfig.defaults +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 - -# -# Partition Table -# -# Leave some room for larger apps without needing to reduce other features -CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y diff --git a/examples/protocols/asio/chat_server/CMakeLists.txt b/examples/protocols/asio/chat_server/CMakeLists.txt deleted file mode 100644 index 182f8d402..000000000 --- a/examples/protocols/asio/chat_server/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -# The following lines of boilerplate have to be in your project's CMakeLists -# in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -# (Not part of the boilerplate) -# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(asio_chat_server) diff --git a/examples/protocols/asio/chat_server/README.md b/examples/protocols/asio/chat_server/README.md deleted file mode 100644 index ec8b3e76e..000000000 --- a/examples/protocols/asio/chat_server/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Asio chat server example - -Simple Asio chat server using WiFi STA or Ethernet. - -## Example workflow - -- Wi-Fi or Ethernet connection is established, and IP address is obtained. -- Asio chat server is started on port number defined through the project configuration. -- Chat server echoes a message (received from any client) to all connected clients. - -## Running the example - -- Open project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. -- Set server port number in menuconfig, "Example configuration". -- Run `idf.py -p PORT flash monitor` to build and upload the example to your board and connect to it's serial terminal. -- Wait for the board to connect to WiFi or Ethernet (note the IP address). -- Connect to the server using multiple clients, for example using any option below. - - build and run asi chat client on your host machine - - run chat_client asio example on ESP platform - - since chat message consist of ascii size and message, it is possible to - netcat `nc IP PORT` and type for example ` 4ABC` to transmit 'ABC\n' - -See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/asio/chat_server/asio_chat_server_test.py b/examples/protocols/asio/chat_server/asio_chat_server_test.py deleted file mode 100644 index 5e92ea00e..000000000 --- a/examples/protocols/asio/chat_server/asio_chat_server_test.py +++ /dev/null @@ -1,44 +0,0 @@ -import os -import re -import socket - -import ttfw_idf - - -@ttfw_idf.idf_example_test(env_tag='Example_WIFI_Protocols') -def test_examples_protocol_asio_chat_server(env, extra_data): - """ - steps: | - 1. join AP - 2. Start server - 3. Test connects to server and sends a test message - 4. Test evaluates received test message from server - """ - test_msg = b' 4ABC\n' - dut1 = env.get_dut('chat_server', 'examples/protocols/asio/chat_server', dut_class=ttfw_idf.ESP32DUT) - # check and log bin size - binary_file = os.path.join(dut1.app.binary_path, 'asio_chat_server.bin') - bin_size = os.path.getsize(binary_file) - ttfw_idf.log_performance('asio_chat_server_bin_size', '{}KB'.format(bin_size // 1024)) - # 1. start test - dut1.start_app() - # 2. get the server IP address - data = dut1.expect(re.compile(r' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), timeout=30) - # 3. create tcp client and connect to server - dut1.expect('ASIO engine is up and running', timeout=1) - cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - cli.settimeout(30) - cli.connect((data[0], 2222)) - cli.send(test_msg) - data = cli.recv(1024) - # 4. check the message received back from the server - if (data == test_msg): - print('PASS: Received correct message {}'.format(data)) - pass - else: - print('Failure!') - raise ValueError('Wrong data received from asi tcp server: {} (expoected:{})'.format(data, test_msg)) - - -if __name__ == '__main__': - test_examples_protocol_asio_chat_server() diff --git a/examples/protocols/asio/chat_server/main/CMakeLists.txt b/examples/protocols/asio/chat_server/main/CMakeLists.txt deleted file mode 100644 index c16daff3d..000000000 --- a/examples/protocols/asio/chat_server/main/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "chat_server.cpp" - INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/chat_server/main/Kconfig.projbuild b/examples/protocols/asio/chat_server/main/Kconfig.projbuild deleted file mode 100644 index c1f397b9c..000000000 --- a/examples/protocols/asio/chat_server/main/Kconfig.projbuild +++ /dev/null @@ -1,9 +0,0 @@ -menu "Example Configuration" - - config EXAMPLE_PORT - string "Asio example server port number" - default "2222" - help - Port number used by Asio example - -endmenu diff --git a/examples/protocols/asio/chat_server/main/chat_message.hpp b/examples/protocols/asio/chat_server/main/chat_message.hpp deleted file mode 100644 index 629105b05..000000000 --- a/examples/protocols/asio/chat_server/main/chat_message.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// chat_message.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef CHAT_MESSAGE_HPP -#define CHAT_MESSAGE_HPP - -#include -#include -#include - -class chat_message -{ -public: - enum { header_length = 4 }; - enum { max_body_length = 512 }; - - chat_message() - : body_length_(0) - { - } - - const char* data() const - { - return data_; - } - - char* data() - { - return data_; - } - - std::size_t length() const - { - return header_length + body_length_; - } - - const char* body() const - { - return data_ + header_length; - } - - char* body() - { - return data_ + header_length; - } - - std::size_t body_length() const - { - return body_length_; - } - - void body_length(std::size_t new_length) - { - body_length_ = new_length; - if (body_length_ > max_body_length) - body_length_ = max_body_length; - } - - bool decode_header() - { - char header[header_length + 1] = ""; - std::strncat(header, data_, header_length); - body_length_ = std::atoi(header); - if (body_length_ > max_body_length) - { - body_length_ = 0; - return false; - } - return true; - } - - void encode_header() - { - char header[header_length + 1] = ""; - std::sprintf(header, "%4d", static_cast(body_length_)); - std::memcpy(data_, header, header_length); - } - -private: - char data_[header_length + max_body_length]; - std::size_t body_length_; -}; - -#endif // CHAT_MESSAGE_HPP diff --git a/examples/protocols/asio/chat_server/main/component.mk b/examples/protocols/asio/chat_server/main/component.mk deleted file mode 100644 index 0adf45649..000000000 --- a/examples/protocols/asio/chat_server/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# diff --git a/examples/protocols/asio/chat_server/sdkconfig.defaults b/examples/protocols/asio/chat_server/sdkconfig.defaults deleted file mode 100644 index b02a3a3ef..000000000 --- a/examples/protocols/asio/chat_server/sdkconfig.defaults +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 - -# -# Partition Table -# -# Leave some room for larger apps without needing to reduce other features -CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y From f0d06985827e1fa0eff350b8ee5bac6cc6072616 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Wed, 1 Sep 2021 16:53:07 +0800 Subject: [PATCH 44/60] docs: update asio docs with new example paths after refactor. * Original commit: espressif/esp-idf@37d549916bd74f2128f6ce35f842914dfb8b9ba1 --- docs/en/api-reference/protocols/asio.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index 559759e9e..0306a5ae1 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -36,8 +36,7 @@ ESP examples are based on standard asio :example:`protocols/asio`: - :example:`protocols/asio/udp_echo_server` - :example:`protocols/asio/tcp_echo_server` -- :example:`protocols/asio/chat_client` -- :example:`protocols/asio/chat_server` +- :example:`protocols/asio/asio_chat` - :example:`protocols/asio/ssl_client_server` Please refer to the specific example README.md for details From 3bcc46276afd4c7f679ddbc568d111b386b48b9f Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 4 Aug 2021 13:40:03 +0500 Subject: [PATCH 45/60] example_tests: Deletes usage esp32c3 ECO0 in CI (by default ECO3) * Original commit: espressif/esp-idf@709abee65c5be93a1013c9bd4379b57ea45fbaac --- examples/protocols/asio/ssl_client_server/sdkconfig.ci | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.ci b/examples/protocols/asio/ssl_client_server/sdkconfig.ci index fdf00fcf6..f1c43e8ac 100644 --- a/examples/protocols/asio/ssl_client_server/sdkconfig.ci +++ b/examples/protocols/asio/ssl_client_server/sdkconfig.ci @@ -4,6 +4,3 @@ CONFIG_EXAMPLE_SERVER_NAME="localhost" CONFIG_EXAMPLE_CONNECT_WIFI=n CONFIG_EXAMPLE_CONNECT_ETHERNET=n CONFIG_EXAMPLE_CLIENT_VERIFY_PEER=y -# IDF-3090 -CONFIG_ESP32C3_REV_MIN_0=y -CONFIG_ESP32C3_REV_MIN=0 From a0297743dd073526b8a9b652bca8e19895d4391c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 21 Sep 2021 13:51:11 +0200 Subject: [PATCH 46/60] openssl: Add deprecation warning to ssl.h OpenSSL component will be discontinued in ESP-IDF v5.x. The only official TLS API will be esp-tls Add docs warning about deprecation in v5.x Removed all examples demonstrating usage of openssl in IDF * Original commit: espressif/esp-idf@cfc001870c5e0afed7b42b6bf8c326eae053fe96 --- components/asio/port/include/esp_asio_config.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index cba316527..3f3a9b03e 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -18,6 +18,11 @@ # define ASIO_NO_TYPEID # endif // CONFIG_COMPILER_RTTI +// +// Supress OpenSSL deprecation warning, when building ASIO +// +#define ESP_OPENSSL_SUPPRESS_LEGACY_WARNING + // // LWIP compatibility inet and address macros/functions // From abbc8d9c5a11f172506eb4844bcf0acc0e51c8f3 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 5 Nov 2021 15:38:25 +0100 Subject: [PATCH 47/60] Build & config: Remove leftover files from the unsupported "make" build system * Original commit: espressif/esp-idf@766aa5708443099f3f033b739cda0e1de101cca6 --- components/asio/component.mk | 13 ------------- examples/protocols/asio/asio_chat/Makefile | 9 --------- examples/protocols/asio/asio_chat/main/component.mk | 8 -------- examples/protocols/asio/ssl_client_server/Makefile | 9 --------- .../asio/ssl_client_server/main/component.mk | 12 ------------ examples/protocols/asio/tcp_echo_server/Makefile | 9 --------- .../asio/tcp_echo_server/main/component.mk | 8 -------- examples/protocols/asio/udp_echo_server/Makefile | 9 --------- .../asio/udp_echo_server/main/component.mk | 8 -------- 9 files changed, 85 deletions(-) delete mode 100644 components/asio/component.mk delete mode 100644 examples/protocols/asio/asio_chat/Makefile delete mode 100644 examples/protocols/asio/asio_chat/main/component.mk delete mode 100644 examples/protocols/asio/ssl_client_server/Makefile delete mode 100644 examples/protocols/asio/ssl_client_server/main/component.mk delete mode 100644 examples/protocols/asio/tcp_echo_server/Makefile delete mode 100644 examples/protocols/asio/tcp_echo_server/main/component.mk delete mode 100644 examples/protocols/asio/udp_echo_server/Makefile delete mode 100644 examples/protocols/asio/udp_echo_server/main/component.mk diff --git a/components/asio/component.mk b/components/asio/component.mk deleted file mode 100644 index c93c8dbb9..000000000 --- a/components/asio/component.mk +++ /dev/null @@ -1,13 +0,0 @@ -ifdef CONFIG_LWIP_IPV6 - -COMPONENT_ADD_INCLUDEDIRS := asio/asio/include port/include -COMPONENT_PRIV_INCLUDEDIRS := private_include -COMPONENT_SRCDIRS := asio/asio/src port/src - -ifeq ($(CONFIG_ASIO_SSL_SUPPORT), ) -COMPONENT_OBJEXCLUDE := asio/asio/src/asio_ssl.o port/src/esp_asio_openssl_stubs.o -endif - -COMPONENT_SUBMODULES += asio - -endif # CONFIG_LWIP_IPV6 diff --git a/examples/protocols/asio/asio_chat/Makefile b/examples/protocols/asio/asio_chat/Makefile deleted file mode 100644 index 93950cb9a..000000000 --- a/examples/protocols/asio/asio_chat/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# -PROJECT_NAME := asio_chat - -EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/asio_chat/main/component.mk b/examples/protocols/asio/asio_chat/main/component.mk deleted file mode 100644 index 0adf45649..000000000 --- a/examples/protocols/asio/asio_chat/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# diff --git a/examples/protocols/asio/ssl_client_server/Makefile b/examples/protocols/asio/ssl_client_server/Makefile deleted file mode 100644 index af59f284f..000000000 --- a/examples/protocols/asio/ssl_client_server/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# -PROJECT_NAME := asio_ssl_client_server - -EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/ssl_client_server/main/component.mk b/examples/protocols/asio/ssl_client_server/main/component.mk deleted file mode 100644 index 36ed173b9..000000000 --- a/examples/protocols/asio/ssl_client_server/main/component.mk +++ /dev/null @@ -1,12 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# - -COMPONENT_EMBED_TXTFILES := ca.crt -COMPONENT_EMBED_TXTFILES += server.key -COMPONENT_EMBED_TXTFILES += srv.crt diff --git a/examples/protocols/asio/tcp_echo_server/Makefile b/examples/protocols/asio/tcp_echo_server/Makefile deleted file mode 100644 index ed9cfb8d8..000000000 --- a/examples/protocols/asio/tcp_echo_server/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# -PROJECT_NAME := asio_tcp_echo_server - -EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/tcp_echo_server/main/component.mk b/examples/protocols/asio/tcp_echo_server/main/component.mk deleted file mode 100644 index 0adf45649..000000000 --- a/examples/protocols/asio/tcp_echo_server/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# diff --git a/examples/protocols/asio/udp_echo_server/Makefile b/examples/protocols/asio/udp_echo_server/Makefile deleted file mode 100644 index f28a9d96a..000000000 --- a/examples/protocols/asio/udp_echo_server/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# -PROJECT_NAME := asio_udp_echo_server - -EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common - -include $(IDF_PATH)/make/project.mk diff --git a/examples/protocols/asio/udp_echo_server/main/component.mk b/examples/protocols/asio/udp_echo_server/main/component.mk deleted file mode 100644 index 0adf45649..000000000 --- a/examples/protocols/asio/udp_echo_server/main/component.mk +++ /dev/null @@ -1,8 +0,0 @@ -# -# Main component makefile. -# -# This Makefile can be left empty. By default, it will take the sources in the -# src/ directory, compile them and link them into lib(subdirectory_name).a -# in the build directory. This behaviour is entirely configurable, -# please read the ESP-IDF documents if you need to do this. -# From f605fdd63283df25ba28eb22d0eb1aeb3f06bc0b Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 14 Oct 2021 10:17:24 +0200 Subject: [PATCH 48/60] asio: Use internal ssl context and engine impl Implement asio-ssl layer with three classes in asio::ssl::mbedtls: * context -- replaces SSL_CTX, used mainly as a container to options, certs, keys * engine -- replaces SSL, implements the actual mbedtls operations * bio -- implements openssl BIO specifically tailered to mbedtls and its asio usage Further updates: * asio: Used shared_ptr<> for bio pairs * asio: Add error checks to mbedtls-bio * asio: Address potential ssl-context ownership issue * asio: Address potential bio-engine ownership issue * Original commit: espressif/esp-idf@d823106aa6b24b8bdcc30373513c8688c61438c4 --- components/asio/CMakeLists.txt | 11 +- components/asio/Kconfig | 9 + .../asio/port/include/esp_asio_config.h | 8 +- components/asio/port/include/esp_exception.h | 1 - components/asio/port/include/openssl/conf.h | 18 -- components/asio/port/include/openssl/dh.h | 15 - .../include/openssl/esp_asio_openssl_stubs.h | 201 ------------ components/asio/port/include/openssl/rsa.h | 15 - components/asio/port/include/openssl/x509v3.h | 15 - components/asio/port/include/openssl_stub.hpp | 46 +++ .../asio/port/mbedtls/include/mbedtls_bio.hpp | 113 +++++++ .../port/mbedtls/include/mbedtls_context.hpp | 105 +++++++ .../port/mbedtls/include/mbedtls_engine.hpp | 294 ++++++++++++++++++ .../port/mbedtls/include/mbedtls_error.hpp | 55 ++++ .../asio/port/mbedtls/include/openssl/conf.h | 6 + .../asio/port/mbedtls/include/openssl/dh.h | 6 + .../asio/port/mbedtls/include/openssl/err.h | 6 + .../asio/port/mbedtls/include/openssl/rsa.h | 6 + .../asio/port/mbedtls/include/openssl/ssl.h | 8 + .../port/mbedtls/include/openssl/x509v3.h | 6 + .../asio/port/mbedtls/src/mbedtls_context.cpp | 115 +++++++ .../asio/port/mbedtls/src/mbedtls_engine.cpp | 208 +++++++++++++ components/asio/port/src/asio_ssl_impl.cpp | 20 ++ .../asio/port/src/esp_asio_openssl_stubs.c | 47 --- .../asio/ssl_client_server/CMakeLists.txt | 1 + 25 files changed, 1014 insertions(+), 321 deletions(-) delete mode 100644 components/asio/port/include/openssl/conf.h delete mode 100644 components/asio/port/include/openssl/dh.h delete mode 100644 components/asio/port/include/openssl/esp_asio_openssl_stubs.h delete mode 100644 components/asio/port/include/openssl/rsa.h delete mode 100644 components/asio/port/include/openssl/x509v3.h create mode 100644 components/asio/port/include/openssl_stub.hpp create mode 100644 components/asio/port/mbedtls/include/mbedtls_bio.hpp create mode 100644 components/asio/port/mbedtls/include/mbedtls_context.hpp create mode 100644 components/asio/port/mbedtls/include/mbedtls_engine.hpp create mode 100644 components/asio/port/mbedtls/include/mbedtls_error.hpp create mode 100644 components/asio/port/mbedtls/include/openssl/conf.h create mode 100644 components/asio/port/mbedtls/include/openssl/dh.h create mode 100644 components/asio/port/mbedtls/include/openssl/err.h create mode 100644 components/asio/port/mbedtls/include/openssl/rsa.h create mode 100644 components/asio/port/mbedtls/include/openssl/ssl.h create mode 100644 components/asio/port/mbedtls/include/openssl/x509v3.h create mode 100644 components/asio/port/mbedtls/src/mbedtls_context.cpp create mode 100644 components/asio/port/mbedtls/src/mbedtls_engine.cpp create mode 100644 components/asio/port/src/asio_ssl_impl.cpp delete mode 100644 components/asio/port/src/esp_asio_openssl_stubs.c diff --git a/components/asio/CMakeLists.txt b/components/asio/CMakeLists.txt index e2421fead..336654597 100644 --- a/components/asio/CMakeLists.txt +++ b/components/asio/CMakeLists.txt @@ -11,8 +11,10 @@ set(asio_sources "asio/asio/src/asio.cpp") if(CONFIG_ASIO_SSL_SUPPORT) if(CONFIG_ASIO_USE_ESP_OPENSSL) list(APPEND asio_sources - "asio/asio/src/asio_ssl.cpp" - "port/src/esp_asio_openssl_stubs.c") + "port/src/asio_ssl_impl.cpp" + "port/mbedtls/src/mbedtls_context.cpp" + "port/mbedtls/src/mbedtls_engine.cpp") + set(asio_priv_includes "port/mbedtls/include") endif() if(CONFIG_ASIO_USE_ESP_WOLFSSL) @@ -23,6 +25,7 @@ endif() idf_component_register(SRCS ${asio_sources} INCLUDE_DIRS "asio/asio/include" "port/include" + PRIV_INCLUDE_DIRS ${asio_priv_includes} REQUIRES lwip) if(CONFIG_ASIO_SSL_SUPPORT) @@ -35,7 +38,7 @@ if(CONFIG_ASIO_SSL_SUPPORT) endif() if(CONFIG_ASIO_USE_ESP_OPENSSL) - idf_component_get_property(esp_openssl openssl COMPONENT_LIB) - target_link_libraries(${COMPONENT_LIB} PUBLIC ${esp_openssl}) + idf_component_get_property(mbedtls mbedtls COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls}) endif() endif() diff --git a/components/asio/Kconfig b/components/asio/Kconfig index 3b488a0c3..6754e1aa2 100644 --- a/components/asio/Kconfig +++ b/components/asio/Kconfig @@ -24,4 +24,13 @@ menu "ESP-ASIO" bool "wolfSSL (License info in wolfSSL directory README)" endchoice + config ASIO_SSL_BIO_SIZE + int "Size of BIO object" + default 1024 + depends on ASIO_SSL_SUPPORT + help + Size in bytes of SSL-BIO implementation. + Reducing the BIO size saves more RAM, but may slow down input output operations due to + fragmentation. + endmenu diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index 3f3a9b03e..53215ca16 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -18,11 +18,6 @@ # define ASIO_NO_TYPEID # endif // CONFIG_COMPILER_RTTI -// -// Supress OpenSSL deprecation warning, when building ASIO -// -#define ESP_OPENSSL_SUPPRESS_LEGACY_WARNING - // // LWIP compatibility inet and address macros/functions // @@ -40,6 +35,9 @@ # ifdef CONFIG_ASIO_USE_ESP_OPENSSL # define ASIO_USE_ESP_OPENSSL # define OPENSSL_NO_ENGINE +# define ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP +# include "openssl_stub.hpp" + # elif CONFIG_ASIO_USE_ESP_WOLFSSL # define ASIO_USE_WOLFSSL # endif // CONFIG_ASIO_USE_ESP_OPENSSL diff --git a/components/asio/port/include/esp_exception.h b/components/asio/port/include/esp_exception.h index 6f88866a4..15cada7a7 100644 --- a/components/asio/port/include/esp_exception.h +++ b/components/asio/port/include/esp_exception.h @@ -1,4 +1,3 @@ - /* * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD * diff --git a/components/asio/port/include/openssl/conf.h b/components/asio/port/include/openssl/conf.h deleted file mode 100644 index 1ed025d93..000000000 --- a/components/asio/port/include/openssl/conf.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _ESP_ASIO_OPENSSL_CONF_H -#define _ESP_ASIO_OPENSSL_CONF_H -#include "esp_asio_config.h" -#include "openssl/esp_asio_openssl_stubs.h" - -#if defined(ASIO_USE_WOLFSSL) -// SSLv3 Methods not present in current wolfSSL library -#define OPENSSL_NO_SSL3 -#include_next "openssl/conf.h" -#endif // ASIO_USE_WOLFSSL - -#endif // _ESP_ASIO_OPENSSL_CONF_H diff --git a/components/asio/port/include/openssl/dh.h b/components/asio/port/include/openssl/dh.h deleted file mode 100644 index af72e083a..000000000 --- a/components/asio/port/include/openssl/dh.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _ESP_ASIO_OPENSSL_DH_STUB_H -#define _ESP_ASIO_OPENSSL_DH_STUB_H -// Dummy header needed for ASIO compilation with esp-openssl - -#if defined(ASIO_USE_WOLFSSL) -#include_next "openssl/dh.h" -#endif // ASIO_USE_WOLFSSL - -#endif // _ESP_ASIO_OPENSSL_DH_STUB_H diff --git a/components/asio/port/include/openssl/esp_asio_openssl_stubs.h b/components/asio/port/include/openssl/esp_asio_openssl_stubs.h deleted file mode 100644 index 506277410..000000000 --- a/components/asio/port/include/openssl/esp_asio_openssl_stubs.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _ESP_ASIO_OPENSSL_STUBS_H -#define _ESP_ASIO_OPENSSL_STUBS_H - -/** - * @note This header contains openssl API which are NOT implemented, and are only provided - * as stubs or no-operations to get the ASIO library compiled and working with most - * practical use cases as an embedded application on ESP platform - */ - -#if defined(ASIO_USE_WOLFSSL) - -#include "wolfssl/ssl.h" -// esp-wolfssl disables filesystem by default, but the ssl filesystem functions are needed for the ASIO to compile -// - so we could either configure wolfSSL to use filesystem -// - or use the default wolfSSL and declare the filesystem functions -- preferred option, as whenever -// the filesystem functions are used from app code (potential security impact if private keys in a filesystem) -// compilation fails with linking errors. - -#if defined(NO_FILESYSTEM) -// WolfSSL methods that are not included in standard esp-wolfssl config, must be defined here -// as function stubs, so ASIO compiles, but would get link errors, if these functions were used. - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct WOLFSSL_CTX WOLFSSL_CTX; - -void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); -int SSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, const char*); -int SSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int); -int SSL_CTX_use_certificate_chain_file(WOLFSSL_CTX*, const char*); -int SSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int); -int SSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int); - -#if defined(__cplusplus) -} /* extern C */ -#endif - -#endif // NO_FILESYSTEM - -#elif defined(ASIO_USE_ESP_OPENSSL) - -#include "internal/ssl_x509.h" -#include "internal/ssl_pkey.h" -#include "mbedtls/pem.h" -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -// The most applicable OpenSSL version wrtt ASIO usage -#define OPENSSL_VERSION_NUMBER 0x10100001L -// SSLv2 methods not supported -// OpenSSL port supports: TLS_ANY, TLS_1, TLS_1_1, TLS_1_2, SSL_3 -#define OPENSSL_NO_SSL2 -#define SSL2_VERSION 0x0002 - -#define SSL_R_SHORT_READ 219 -#define SSL_OP_ALL 0 -#define SSL_OP_SINGLE_DH_USE 0 -#define SSL_OP_NO_COMPRESSION 0 -// Translates mbedTLS PEM parse error, used by ASIO -#define PEM_R_NO_START_LINE -MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT - -#define SSL_OP_NO_SSLv2 0x01000000L -#define SSL_OP_NO_SSLv3 0x02000000L -#define SSL_OP_NO_TLSv1 0x04000000L - -#define X509_FILETYPE_PEM 1 -#define X509_FILETYPE_ASN1 2 -#define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 -#define SSL_FILETYPE_PEM X509_FILETYPE_PEM - -#define NID_subject_alt_name 85 - - -#define GEN_DNS 2 -#define GEN_IPADD 7 -#define V_ASN1_OCTET_STRING 4 -#define V_ASN1_IA5STRING 22 -#define NID_commonName 13 - -#define SSL_CTX_get_app_data(ctx) ((void*)SSL_CTX_get_ex_data(ctx, 0)) - -/** -* @brief Frees DH object -- not implemented -* -* Current implementation calls SSL_ASSERT -* -* @param r DH object -*/ -void DH_free(DH *r); - -/** - * @brief Frees GENERAL_NAMES -- not implemented - * - * Current implementation calls SSL_ASSERT - * - * @param r GENERAL_NAMES object - */ -void GENERAL_NAMES_free(GENERAL_NAMES * gens); - -/** - * @brief Returns subject name from X509 -- not implemented - * - * Current implementation calls SSL_ASSERT - * - * @param r X509 object - */ -X509_NAME *X509_get_subject_name(X509 *a); - -/** - * @brief API provaded as declaration only - * - */ -int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); - -/** - * @brief API provaded as declaration only - * - */ -int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos); - -/** - * @brief API provaded as declaration only - * - */ -X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc); - -/** - * @brief API provaded as declaration only - * - */ -ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne); - -/** - * @brief API provaded as declaration only - * - */ -void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); - -/** - * @brief API provaded as declaration only - * - */ -X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); - -/** - * @brief Reads DH params from a bio object -- not implemented - * - * Current implementation calls SSL_ASSERT - */ -DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u); - -/** - * @brief API provaded as declaration only - * - */ -void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); - -/** - * @brief Sets DH params to ssl ctx -- not implemented - * - * Current implementation calls SSL_ASSERT - */ -int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh); - -/** - * @brief API provaded as declaration only - * - */ -void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data); - -/** - * @brief API provaded as declaration only - * - */ -void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); - -/** - * @brief Clears any existing chain associated with the current certificate of ctx. - * - */ -int SSL_CTX_clear_chain_certs(SSL_CTX *ctx); - -#if defined(__cplusplus) -} /* extern C */ -#endif - -#endif /* ASIO_USE_ESP_OPENSSL, ASIO_USE_WOLFSSL */ -#endif /* _ESP_ASIO_OPENSSL_STUBS_H */ diff --git a/components/asio/port/include/openssl/rsa.h b/components/asio/port/include/openssl/rsa.h deleted file mode 100644 index 53018a33a..000000000 --- a/components/asio/port/include/openssl/rsa.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _ESP_ASIO_OPENSSL_RSA_STUB_H -#define _ESP_ASIO_OPENSSL_RSA_STUB_H -// Dummy header needed for ASIO compilation with esp-openssl - -#if defined(ASIO_USE_WOLFSSL) -#include_next "openssl/rsa.h" -#endif // ASIO_USE_WOLFSSL - -#endif // _ESP_ASIO_OPENSSL_RSA_STUB_H diff --git a/components/asio/port/include/openssl/x509v3.h b/components/asio/port/include/openssl/x509v3.h deleted file mode 100644 index dad747542..000000000 --- a/components/asio/port/include/openssl/x509v3.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef _ESP_ASIO_OPENSSL_X509V3_STUB_H -#define _ESP_ASIO_OPENSSL_X509V3_STUB_H -// Dummy header needed for ASIO compilation with esp-openssl - -#if defined(ASIO_USE_WOLFSSL) -#include_next "openssl/x509v3.h" -#endif // ASIO_USE_WOLFSSL - -#endif // _ESP_ASIO_OPENSSL_X509V3_STUB_H diff --git a/components/asio/port/include/openssl_stub.hpp b/components/asio/port/include/openssl_stub.hpp new file mode 100644 index 000000000..175879542 --- /dev/null +++ b/components/asio/port/include/openssl_stub.hpp @@ -0,0 +1,46 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// + +#pragma once + +// +// Supply OpenSSL macros and flags for asio-ssl header files +// +#define OPENSSL_VERSION_NUMBER 0x10100001L + +#define SSL_R_SHORT_READ 219 +#define SSL_OP_ALL 0 +#define SSL_OP_SINGLE_DH_USE 0 +#define SSL_OP_NO_COMPRESSION 0 + +#define SSL_OP_NO_SSLv2 0x01000000L +#define SSL_OP_NO_SSLv3 0x02000000L +#define SSL_OP_NO_TLSv1 0x04000000L + +#define SSL_VERIFY_NONE 0x00 +#define SSL_VERIFY_PEER 0x01 +#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +#define SSL_VERIFY_CLIENT_ONCE 0x04 + +// +// Implement asio-ssl layer with these three classes in asio::ssl::mbedtls +// +namespace asio { +namespace ssl { +namespace mbedtls { + +class engine; +class bio; +class shared_ctx; +} } } // namespace asio::ssl::mbedtls + +// +// Supply OpenSSL types as aliases to mbedtls classes +// +using X509_STORE_CTX=void; +using BIO=asio::ssl::mbedtls::bio; +using SSL_CTX=asio::ssl::mbedtls::shared_ctx; +using SSL=asio::ssl::mbedtls::engine; diff --git a/components/asio/port/mbedtls/include/mbedtls_bio.hpp b/components/asio/port/mbedtls/include/mbedtls_bio.hpp new file mode 100644 index 000000000..d5348a052 --- /dev/null +++ b/components/asio/port/mbedtls/include/mbedtls_bio.hpp @@ -0,0 +1,113 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once + +#include "asio/ssl/context_base.hpp" +#include "asio/ssl/context.hpp" +#include "sdkconfig.h" + +namespace asio { +namespace ssl { +namespace mbedtls { + +class bio { + static constexpr int BIO_SIZE = CONFIG_ASIO_SSL_BIO_SIZE; + static constexpr int BIO_FLAGS_READ = 1; + static constexpr int BIO_FLAGS_WRITE = 2; + +public: + int write(const void *buf, int len) + { + if (buf == nullptr || len <= 0) { + // not an error, just empty operation (as in openssl/bio) + return 0; + } + int remaining = size_ - offset_; + if (remaining <= 0) { + flags_ |= BIO_FLAGS_WRITE; + return -1; + } + int len_to_write = len > remaining ? remaining : len; + std::memcpy(&data_[offset_], buf, len_to_write); + offset_ += len_to_write; + dlen_ = offset_; + if (len_to_write == len) { + flags_ &= ~BIO_FLAGS_WRITE; + } + return len_to_write; + } + + int read(void *buf, int len) + { + if (buf == nullptr || len <= 0) { + // not an error, just empty operation (as in openssl/bio) + return 0; + } + int remaining = peer_->dlen_ - peer_->roffset_; + if (remaining <= 0) { + flags_ |= BIO_FLAGS_READ; + return -1; + } + int len_to_read = remaining > len ? len : remaining; + std::memcpy(buf, &peer_->data_[peer_->roffset_], len_to_read); + peer_->roffset_ += len_to_read; + if (len_to_read == len) { + flags_ &= ~BIO_FLAGS_READ; + } + if (peer_->offset_) { + // shift data back to the beginning of the buffer + std::memmove(&peer_->data_[0], &peer_->data_[peer_->roffset_], peer_->offset_ - peer_->roffset_); + peer_->offset_ -= peer_->roffset_; + peer_->roffset_ = 0; + peer_->dlen_ = peer_->offset_; + } + return len_to_read; + } + + size_t wpending() const + { + return dlen_ - roffset_; + } + + size_t ctrl_pending() + { + return peer_->dlen_ - peer_->roffset_; + } + + bool should_write() const + { + return flags_ & BIO_FLAGS_WRITE; + } + + bool should_read() const + { + return flags_ & BIO_FLAGS_READ; + } + + static std::pair, std::shared_ptr> new_pair(const char* error_location) + { + auto b1 = std::shared_ptr(new (std::nothrow) bio); + auto b2 = std::shared_ptr(new (std::nothrow) bio); + if (b1 == nullptr || b2 == nullptr) { + throw_alloc_failure(error_location); + } else { + b1->peer_ = b2; + b2->peer_ = b1; + } + return std::make_pair(b1, b2); + } + +private: + std::array data_ {}; + size_t size_ {BIO_SIZE}; + std::shared_ptr peer_ {nullptr}; + int dlen_ {0}; + size_t offset_ {0}; + size_t roffset_ {0}; + size_t flags_ {0}; +}; + +} } } // namespace asio::ssl::mbedtls diff --git a/components/asio/port/mbedtls/include/mbedtls_context.hpp b/components/asio/port/mbedtls/include/mbedtls_context.hpp new file mode 100644 index 000000000..27d135b5d --- /dev/null +++ b/components/asio/port/mbedtls/include/mbedtls_context.hpp @@ -0,0 +1,105 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once + +#include "asio/ssl/context_base.hpp" +#include "asio/ssl/context.hpp" + +namespace asio { +namespace error { + +const asio::error_category& get_mbedtls_category(); +} // namespace error + +namespace ssl { +namespace mbedtls { + +void throw_alloc_failure(const char* location); + +const char *error_message(int error_code); + +enum class container { + CERT, CA_CERT, PRIVKEY +}; + +template +inline T* create(const char * location, Args &&... args) +{ + T* t = new (std::nothrow) T(std::forward(args)...); + if (t == nullptr) + { + throw_alloc_failure(location); + } + return t; +} + +class context { +public: + explicit context(context_base::method m): method_(m), options_(0) {} + + const unsigned char *data(container c) const + { + switch (c) { + case container::CERT: + return static_cast(cert_chain_.data()); + case container::CA_CERT: + return static_cast(ca_cert_.data()); + case container::PRIVKEY: + return static_cast(private_key_.data()); + } + return nullptr; + } + + std::size_t size(container c) const + { + switch (c) { + case container::CERT: + return cert_chain_.size(); + case container::CA_CERT: + return ca_cert_.size(); + case container::PRIVKEY: + return private_key_.size(); + } + return 0; + } + + context_base::method method_; + asio::ssl::context::options options_; + const_buffer cert_chain_; + const_buffer private_key_; + const_buffer ca_cert_; +}; + +/** + * @brief Wrapper class around SSL_CTX so we can easily create + * a shared pointer to the context without throwing the default exception. + * This is useful, as we can use asio::detail::throw_error for allocation errors. + */ +class shared_ctx { +public: + static SSL_CTX *create(const char* location, context_base::method m) + { + auto wrapped = asio::ssl::mbedtls::create(location, m); + if (wrapped->ctx_ == nullptr) + { + throw_alloc_failure(location); + } + return wrapped; + } + + std::shared_ptr get() const + { + return ctx_; + } + + explicit shared_ctx(context_base::method m) + :ctx_(std::shared_ptr(new (std::nothrow) context(m))) { } + +private: + std::shared_ptr ctx_; +}; + +} } } // namespace asio::ssl::mbedtls diff --git a/components/asio/port/mbedtls/include/mbedtls_engine.hpp b/components/asio/port/mbedtls/include/mbedtls_engine.hpp new file mode 100644 index 000000000..9e77acbc3 --- /dev/null +++ b/components/asio/port/mbedtls/include/mbedtls_engine.hpp @@ -0,0 +1,294 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once + +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" +#include "mbedtls/esp_debug.h" +#include "esp_log.h" + +namespace asio { +namespace ssl { +namespace mbedtls { + +const char *error_message(int error_code) +{ + static char error_buf[100]; + mbedtls_strerror(error_code, error_buf, sizeof(error_buf)); + return error_buf; +} + +void throw_alloc_failure(const char* location) +{ + asio::error_code ec( MBEDTLS_ERR_SSL_ALLOC_FAILED, asio::error::get_mbedtls_category()); + asio::detail::throw_error(ec, location); +} + +namespace error_codes { + +bool is_error(int ret) +{ + return ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE; +} + +static bool want_write(int ret) +{ + return ret == MBEDTLS_ERR_SSL_WANT_WRITE; +} + +static bool want_read(int ret) +{ + return ret == MBEDTLS_ERR_SSL_WANT_READ; +} + +} // namespace error_codes + +enum rw_state { + IDLE, READING, WRITING, CLOSED +}; + +class engine { +public: + explicit engine(std::shared_ptr ctx): ctx_(std::move(ctx)), + bio_(bio::new_pair("mbedtls-engine")), state_(IDLE), verify_mode_(0) {} + + void set_verify_mode(asio::ssl::verify_mode mode) + { + verify_mode_ = mode; + } + + bio* ext_bio() const + { + return bio_.second.get(); + } + + rw_state get_state() const + { + return state_; + } + + int shutdown() + { + int ret = mbedtls_ssl_close_notify(&impl_.ssl_); + if (ret) { + impl::print_error("mbedtls_ssl_close_notify", ret); + } + state_ = CLOSED; + return ret; + } + + int connect() + { + return handshake(true); + } + + int accept() + { + return handshake(false); + } + + int write(const void *buffer, int len) + { + int ret = impl_.write(buffer, len); + state_ = ret == len ? IDLE: WRITING; + return ret; + } + + int read(void *buffer, int len) + { + int ret = impl_.read(buffer, len); + state_ = ret == len ? IDLE: READING; + return ret; + } + +private: + int handshake(bool is_client_not_server) + { + if (impl_.before_handshake()) { + impl_.configure(ctx_.get(), is_client_not_server, impl_verify_mode(is_client_not_server)); + } + return do_handshake(); + } + + static int bio_read(void *ctx, unsigned char *buf, size_t len) + { + auto bio = static_cast(ctx); + int read = bio->read(buf, len); + if (read <= 0 && bio->should_read()) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + return read; + } + + static int bio_write(void *ctx, const unsigned char *buf, size_t len) + { + auto bio = static_cast(ctx); + int written = bio->write(buf, len); + if (written <= 0 && bio->should_write()) { + return MBEDTLS_ERR_SSL_WANT_WRITE; + } + return written; + } + + int do_handshake() + { + int ret = 0; + mbedtls_ssl_set_bio(&impl_.ssl_, bio_.first.get(), bio_write, bio_read, nullptr); + + while (impl_.ssl_.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + ret = mbedtls_ssl_handshake_step(&impl_.ssl_); + + if (ret != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + impl::print_error("mbedtls_ssl_handshake_step", ret); + } + if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + state_ = READING; + } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + state_ = WRITING; + } + break; + } + } + return ret; + } + + // Converts OpenSSL verification mode to mbedtls enum + int impl_verify_mode(bool is_client_not_server) const + { + int mode = MBEDTLS_SSL_VERIFY_UNSET; + if (is_client_not_server) { + if (verify_mode_ & SSL_VERIFY_PEER) + mode = MBEDTLS_SSL_VERIFY_REQUIRED; + else if (verify_mode_ == SSL_VERIFY_NONE) + mode = MBEDTLS_SSL_VERIFY_NONE; + } else { + if (verify_mode_ & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + mode = MBEDTLS_SSL_VERIFY_REQUIRED; + else if (verify_mode_ & SSL_VERIFY_PEER) + mode = MBEDTLS_SSL_VERIFY_OPTIONAL; + else if (verify_mode_ == SSL_VERIFY_NONE) + mode = MBEDTLS_SSL_VERIFY_NONE; + } + return mode; + } + + struct impl { + static void print_error(const char* function, int error_code) + { + constexpr const char *TAG="mbedtls-engine-impl"; + ESP_LOGE(TAG, "%s() returned -0x%04X", function, -error_code); + ESP_LOGI(TAG, "-0x%04X: %s", -error_code, error_message(error_code)); + } + + bool before_handshake() const + { + return ssl_.state == 0; + } + + int write(const void *buffer, int len) + { + int ret = mbedtls_ssl_write(&ssl_, static_cast(buffer), len); + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + print_error("mbedtls_ssl_write", ret); + } + return ret; + } + + int read(void *buffer, int len) + { + int ret = mbedtls_ssl_read(&ssl_, static_cast(buffer), len); + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ) { + print_error("mbedtls_ssl_read", ret); + } + return ret; + } + + impl() + { + const unsigned char pers[] = "asio ssl"; + mbedtls_ssl_init(&ssl_); + mbedtls_ssl_config_init(&conf_); + mbedtls_ctr_drbg_init(&ctr_drbg_); +#ifdef CONFIG_MBEDTLS_DEBUG + mbedtls_esp_enable_debug_log(&conf_, CONFIG_MBEDTLS_DEBUG_LEVEL); +#endif + mbedtls_entropy_init(&entropy_); + mbedtls_ctr_drbg_seed(&ctr_drbg_, mbedtls_entropy_func, &entropy_, pers, sizeof(pers)); + mbedtls_x509_crt_init(&public_cert_); + mbedtls_pk_init(&pk_key_); + mbedtls_x509_crt_init(&ca_cert_); + } + + bool configure(context *ctx, bool is_client_not_server, int mbedtls_verify_mode) + { + mbedtls_x509_crt_init(&public_cert_); + mbedtls_pk_init(&pk_key_); + mbedtls_x509_crt_init(&ca_cert_); + int ret = mbedtls_ssl_config_defaults(&conf_, is_client_not_server ? MBEDTLS_SSL_IS_CLIENT: MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); + if (ret) { + print_error("mbedtls_ssl_config_defaults", ret); + return false; + } + mbedtls_ssl_conf_rng(&conf_, mbedtls_ctr_drbg_random, &ctr_drbg_); + mbedtls_ssl_conf_authmode(&conf_, mbedtls_verify_mode); + if (ctx->cert_chain_.size() > 0 && ctx->private_key_.size() > 0) { + ret = mbedtls_x509_crt_parse(&public_cert_, ctx->data(container::CERT), ctx->size(container::CERT)); + if (ret < 0) { + print_error("mbedtls_x509_crt_parse", ret); + return false; + } + ret = mbedtls_pk_parse_key(&pk_key_, ctx->data(container::PRIVKEY), ctx->size(container::PRIVKEY), + nullptr, 0); + if (ret < 0) { + print_error("mbedtls_pk_parse_keyfile", ret); + return false; + } + ret = mbedtls_ssl_conf_own_cert(&conf_, &public_cert_, &pk_key_); + if (ret) { + print_error("mbedtls_ssl_conf_own_cert", ret); + return false; + } + } + + if (ctx->ca_cert_.size() > 0) { + ret = mbedtls_x509_crt_parse(&ca_cert_, ctx->data(container::CA_CERT), ctx->size(container::CA_CERT)); + if (ret < 0) { + print_error("mbedtls_x509_crt_parse", ret); + return false; + } + mbedtls_ssl_conf_ca_chain(&conf_, &ca_cert_, nullptr); + } else { + mbedtls_ssl_conf_ca_chain(&conf_, nullptr, nullptr); + } + ret = mbedtls_ssl_setup(&ssl_, &conf_); + if (ret) { + print_error("mbedtls_ssl_setup", ret); + return false; + } + return true; + } + mbedtls_ssl_context ssl_{}; + mbedtls_entropy_context entropy_{}; + mbedtls_ctr_drbg_context ctr_drbg_{}; + mbedtls_ssl_config conf_{}; + mbedtls_x509_crt public_cert_{}; + mbedtls_pk_context pk_key_{}; + mbedtls_x509_crt ca_cert_{}; + }; + + impl impl_{}; + std::shared_ptr ctx_; + std::pair, std::shared_ptr> bio_; + enum rw_state state_; + asio::ssl::verify_mode verify_mode_; +}; + +} } } // namespace asio::ssl::mbedtls diff --git a/components/asio/port/mbedtls/include/mbedtls_error.hpp b/components/asio/port/mbedtls/include/mbedtls_error.hpp new file mode 100644 index 000000000..083cf6c88 --- /dev/null +++ b/components/asio/port/mbedtls/include/mbedtls_error.hpp @@ -0,0 +1,55 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once + +#include "asio/detail/config.hpp" +#include "asio/ssl/error.hpp" +#include "asio/ssl/detail/openssl_init.hpp" +#include "mbedtls_context.hpp" + +namespace asio { +namespace error { +namespace detail { + +class mbedtls_category : public asio::error_category +{ +public: + const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + { + return "asio.ssl"; + } + + std::string message(int value) const + { + const char* s = asio::ssl::mbedtls::error_message(value); + return s ? s : "asio.mbedtls error"; + } +}; + +} // namespace detail + +const asio::error_category& get_mbedtls_category() +{ + static detail::mbedtls_category instance; + return instance; +} + +const asio::error_category& get_ssl_category() +{ + return asio::error::get_mbedtls_category(); +} + +} // namespace error + +namespace ssl { +namespace error { + +const asio::error_category& get_stream_category() +{ + return asio::error::get_mbedtls_category(); +} + +} } } // namespace asio::ssl::error diff --git a/components/asio/port/mbedtls/include/openssl/conf.h b/components/asio/port/mbedtls/include/openssl/conf.h new file mode 100644 index 000000000..dc024544e --- /dev/null +++ b/components/asio/port/mbedtls/include/openssl/conf.h @@ -0,0 +1,6 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once diff --git a/components/asio/port/mbedtls/include/openssl/dh.h b/components/asio/port/mbedtls/include/openssl/dh.h new file mode 100644 index 000000000..dc024544e --- /dev/null +++ b/components/asio/port/mbedtls/include/openssl/dh.h @@ -0,0 +1,6 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once diff --git a/components/asio/port/mbedtls/include/openssl/err.h b/components/asio/port/mbedtls/include/openssl/err.h new file mode 100644 index 000000000..dc024544e --- /dev/null +++ b/components/asio/port/mbedtls/include/openssl/err.h @@ -0,0 +1,6 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once diff --git a/components/asio/port/mbedtls/include/openssl/rsa.h b/components/asio/port/mbedtls/include/openssl/rsa.h new file mode 100644 index 000000000..dc024544e --- /dev/null +++ b/components/asio/port/mbedtls/include/openssl/rsa.h @@ -0,0 +1,6 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once diff --git a/components/asio/port/mbedtls/include/openssl/ssl.h b/components/asio/port/mbedtls/include/openssl/ssl.h new file mode 100644 index 000000000..be147bc00 --- /dev/null +++ b/components/asio/port/mbedtls/include/openssl/ssl.h @@ -0,0 +1,8 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once + +#include "openssl_stub.hpp" diff --git a/components/asio/port/mbedtls/include/openssl/x509v3.h b/components/asio/port/mbedtls/include/openssl/x509v3.h new file mode 100644 index 000000000..dc024544e --- /dev/null +++ b/components/asio/port/mbedtls/include/openssl/x509v3.h @@ -0,0 +1,6 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: BSL-1.0 +// +#pragma once diff --git a/components/asio/port/mbedtls/src/mbedtls_context.cpp b/components/asio/port/mbedtls/src/mbedtls_context.cpp new file mode 100644 index 000000000..36ba700dd --- /dev/null +++ b/components/asio/port/mbedtls/src/mbedtls_context.cpp @@ -0,0 +1,115 @@ +// +// SPDX-FileCopyrightText: 2005 Voipster / Indrek dot Juhani at voipster dot com +// SPDX-FileCopyrightText: 2005-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// SPDX-License-Identifier: BSL-1.0 +// +// SPDX-FileContributor: 2021 Espressif Systems (Shanghai) CO LTD +// + +#include "asio/detail/config.hpp" +#include "openssl_stub.hpp" +#include +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" +#include "asio/ssl/context.hpp" +#include "asio/ssl/error.hpp" +#include "mbedtls_context.hpp" + + +namespace asio { +namespace ssl { + + +context::context(context::method m) + : handle_(0) +{ + handle_ = mbedtls::shared_ctx::create("mbedtls-context", m); + set_options(no_compression); +} + +context::context(context&& other) +{ + handle_ = other.handle_; + other.handle_ = 0; +} + +context& context::operator=(context&& other) +{ + context tmp(ASIO_MOVE_CAST(context)(*this)); + handle_ = other.handle_; + other.handle_ = 0; + return *this; +} + +context::~context() +{ + delete handle_; +} + +context::native_handle_type context::native_handle() +{ + return handle_; +} + +void context::set_options(context::options o) +{ + asio::error_code ec; + set_options(o, ec); + asio::detail::throw_error(ec, "set_options"); +} + +ASIO_SYNC_OP_VOID context::set_options( + context::options o, asio::error_code& ec) +{ + handle_->get()->options_ = o; + ec = asio::error_code(); + ASIO_SYNC_OP_VOID_RETURN(ec); +} + +void context::add_certificate_authority(const const_buffer& ca) +{ + asio::error_code ec; + add_certificate_authority(ca, ec); + asio::detail::throw_error(ec, "add_certificate_authority"); +} + +ASIO_SYNC_OP_VOID context::add_certificate_authority( + const const_buffer& ca, asio::error_code& ec) +{ + handle_->get()->ca_cert_ = ca; + ASIO_SYNC_OP_VOID_RETURN(asio::error_code()); +} + +void context::use_certificate_chain(const const_buffer& chain) +{ + asio::error_code ec; + use_certificate_chain(chain, ec); + asio::detail::throw_error(ec, "use_certificate_chain"); +} + +ASIO_SYNC_OP_VOID context::use_certificate_chain( + const const_buffer& chain, asio::error_code& ec) +{ + handle_->get()->cert_chain_ = chain; + ASIO_SYNC_OP_VOID_RETURN(asio::error_code()); +} + +void context::use_private_key( + const const_buffer& private_key, context::file_format format) +{ + asio::error_code ec; + use_private_key(private_key, format, ec); + asio::detail::throw_error(ec, "use_private_key"); +} + +ASIO_SYNC_OP_VOID context::use_private_key( + const const_buffer& private_key, context::file_format format, + asio::error_code& ec) +{ + handle_->get()->private_key_ = private_key; + ASIO_SYNC_OP_VOID_RETURN(asio::error_code()); +} + +} // namespace ssl +} // namespace asio diff --git a/components/asio/port/mbedtls/src/mbedtls_engine.cpp b/components/asio/port/mbedtls/src/mbedtls_engine.cpp new file mode 100644 index 000000000..c3ff91842 --- /dev/null +++ b/components/asio/port/mbedtls/src/mbedtls_engine.cpp @@ -0,0 +1,208 @@ +// +// SPDX-FileCopyrightText: 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// SPDX-License-Identifier: BSL-1.0 +// +// SPDX-FileContributor: 2021 Espressif Systems (Shanghai) CO LTD +// + +#include "asio/detail/config.hpp" +#include "openssl_stub.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" +#include "asio/ssl/detail/engine.hpp" +#include "asio/ssl/error.hpp" +#include "asio/ssl/verify_context.hpp" +#include "mbedtls_context.hpp" +#include "mbedtls_bio.hpp" +#include "mbedtls_error.hpp" +#include "mbedtls_engine.hpp" + + +namespace asio { +namespace ssl { +namespace detail { + + +engine::engine(SSL_CTX* context) + : ssl_(nullptr) +{ + ssl_ = mbedtls::create("mbedtls-engine", context->get()); +} + +engine::~engine() +{ + delete ssl_; +} + +SSL* engine::native_handle() +{ + return ssl_; +} + +asio::error_code engine::set_verify_mode( + verify_mode v, asio::error_code& ec) +{ + ssl_->set_verify_mode(v); + return {}; +} + +engine::want engine::handshake( + stream_base::handshake_type type, asio::error_code& ec) +{ + return perform((type == asio::ssl::stream_base::client) + ? &engine::do_connect : &engine::do_accept, 0, 0, ec, 0); +} + +engine::want engine::shutdown(asio::error_code& ec) +{ + return perform(&engine::do_shutdown, 0, 0, ec, 0); +} + +engine::want engine::write(const asio::const_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + if (data.size() == 0) + { + ec = asio::error_code(); + return engine::want_nothing; + } + + return perform(&engine::do_write, + const_cast(data.data()), + data.size(), ec, &bytes_transferred); +} + +engine::want engine::read(const asio::mutable_buffer& data, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + if (data.size() == 0) + { + ec = asio::error_code(); + return engine::want_nothing; + } + + return perform(&engine::do_read, data.data(), + data.size(), ec, &bytes_transferred); +} + +asio::mutable_buffer engine::get_output( + const asio::mutable_buffer& data) +{ + int length = ssl_->ext_bio()->read(data.data(), static_cast(data.size())); + + return asio::buffer(data, + length > 0 ? static_cast(length) : 0); +} + +asio::const_buffer engine::put_input( + const asio::const_buffer& data) +{ + int length = ssl_->ext_bio()->write(data.data(), static_cast(data.size())); + + return asio::buffer(data + + (length > 0 ? static_cast(length) : 0)); +} + +const asio::error_code& engine::map_error_code( + asio::error_code& ec) const +{ + // We only want to map the error::eof code. + if (ec != asio::error::eof) + return ec; + + // If there's data yet to be read, it's an error. + if (ssl_->ext_bio()->wpending()) + { + ec = asio::ssl::error::stream_truncated; + return ec; + } + + // Otherwise, the peer should have negotiated a proper shutdown. + if (ssl_->shutdown() != 0) + { + ec = asio::ssl::error::stream_truncated; + } + + return ec; +} + +// This is a simplified implementation of a generic ssl io operation +// original implementation using openssl's SSL object is in asio/include/asio/ssl/detail/impl/engine.ipp +engine::want engine::perform(int (engine::* op)(void*, std::size_t), + void* data, std::size_t length, asio::error_code& ec, + std::size_t* bytes_transferred) +{ + std::size_t pending_output_before = ssl_->ext_bio()->ctrl_pending(); + int result = (this->*op)(data, length); + + std::size_t pending_output_after = ssl_->ext_bio()->ctrl_pending(); + + if (mbedtls::error_codes::is_error(result)) + { + ec = asio::error_code(result, asio::error::get_mbedtls_category()); + return pending_output_after > pending_output_before ? want_output : want_nothing; + } + + if (result == 0) + { + return pending_output_after > pending_output_before + ? want_output : want_nothing; + } + + if (result > 0 && bytes_transferred) + *bytes_transferred = static_cast(result); + + if (mbedtls::error_codes::want_write(result)) + { + ec = asio::error_code(); + return want_output_and_retry; + } + else if (pending_output_after > pending_output_before) + { + ec = asio::error_code(); + return result > 0 ? want_output : want_output_and_retry; + } + else if (mbedtls::error_codes::want_read(result)) + { + ec = asio::error_code(); + return want_input_and_retry; + } + else if (ssl_->get_state() == mbedtls::CLOSED) + { + ec = asio::error::eof; + return want_nothing; + } + + ec = asio::error_code(); + return want_nothing; +} + +int engine::do_accept(void*, std::size_t) +{ + return ssl_->accept(); +} + +int engine::do_connect(void*, std::size_t) +{ + return ssl_->connect(); +} + +int engine::do_shutdown(void*, std::size_t) +{ + return ssl_->shutdown(); +} + +int engine::do_read(void* data, std::size_t length) +{ + return ssl_->read(data, length < INT_MAX ? static_cast(length) : INT_MAX); +} + +int engine::do_write(void* data, std::size_t length) +{ + return ssl_->write(data, length < INT_MAX ? static_cast(length) : INT_MAX); +} + +} // namespace detail +} // namespace ssl +} // namespace asio diff --git a/components/asio/port/src/asio_ssl_impl.cpp b/components/asio/port/src/asio_ssl_impl.cpp new file mode 100644 index 000000000..8f387dd7b --- /dev/null +++ b/components/asio/port/src/asio_ssl_impl.cpp @@ -0,0 +1,20 @@ +// +// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include "asio/detail/config.hpp" +#include "asio/ssl/detail/openssl_init.hpp" + +namespace asio { +namespace ssl { +namespace detail { + +// No OpenSSL in this implementation, instance is nullptr +asio::detail::shared_ptr openssl_init_base::instance() +{ + return nullptr; +} + +} } } // namespace asio::ssl::detail diff --git a/components/asio/port/src/esp_asio_openssl_stubs.c b/components/asio/port/src/esp_asio_openssl_stubs.c deleted file mode 100644 index c766fb0d7..000000000 --- a/components/asio/port/src/esp_asio_openssl_stubs.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -// - -#include "esp_asio_config.h" -#include "internal/ssl_dbg.h" -#include "openssl/esp_asio_openssl_stubs.h" - -// Unsupported features as macros to make the assertions more readable -#define ESP_OPENSSL_DH_IS_SUPPORTED 0 -#define ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED 0 - -void DH_free (DH *r) -{ - SSL_ASSERT3(ESP_OPENSSL_DH_IS_SUPPORTED); -} - -DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u) -{ - SSL_ASSERT2(ESP_OPENSSL_DH_IS_SUPPORTED); - return NULL; -} - -int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) -{ - SSL_ASSERT1(ESP_OPENSSL_DH_IS_SUPPORTED); - return -1; -} - -void GENERAL_NAMES_free(GENERAL_NAMES * gens) -{ - SSL_ASSERT3(ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED); -} - -X509_NAME *X509_get_subject_name(X509 *a) -{ - SSL_ASSERT2(ESP_OPENSSL_GENERAL_NAMES_IS_SUPPORTED); - return NULL; -} - -int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) -{ - return 1; -} diff --git a/examples/protocols/asio/ssl_client_server/CMakeLists.txt b/examples/protocols/asio/ssl_client_server/CMakeLists.txt index fcdac1488..804b8428b 100644 --- a/examples/protocols/asio/ssl_client_server/CMakeLists.txt +++ b/examples/protocols/asio/ssl_client_server/CMakeLists.txt @@ -5,6 +5,7 @@ cmake_minimum_required(VERSION 3.5) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXCLUDE_COMPONENTS openssl) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_ssl_client_server) From b76d3fbff9edf2841fc71f3ccc08b5783f2b2ba5 Mon Sep 17 00:00:00 2001 From: Euripedes Rocha Date: Mon, 20 Sep 2021 15:25:02 -0300 Subject: [PATCH 49/60] EXAMPLE/ASIO Async HTTP request Introduces a new example on ASIO to ilustrates on how to compose async operation to build network related protocols. * Original commit: espressif/esp-idf@2433816b14374dffd5c4a2b5a4234841fdcec3b9 --- .../asio/async_request/CMakeLists.txt | 10 + .../protocols/asio/async_request/README.md | 52 +++ .../asio/async_request/main/CMakeLists.txt | 2 + .../async_request/main/async_http_request.cpp | 369 ++++++++++++++++++ 4 files changed, 433 insertions(+) create mode 100644 examples/protocols/asio/async_request/CMakeLists.txt create mode 100644 examples/protocols/asio/async_request/README.md create mode 100644 examples/protocols/asio/async_request/main/CMakeLists.txt create mode 100644 examples/protocols/asio/async_request/main/async_http_request.cpp diff --git a/examples/protocols/asio/async_request/CMakeLists.txt b/examples/protocols/asio/async_request/CMakeLists.txt new file mode 100644 index 000000000..fc7e3c944 --- /dev/null +++ b/examples/protocols/asio/async_request/CMakeLists.txt @@ -0,0 +1,10 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(async_http_request) diff --git a/examples/protocols/asio/async_request/README.md b/examples/protocols/asio/async_request/README.md new file mode 100644 index 000000000..c2b114511 --- /dev/null +++ b/examples/protocols/asio/async_request/README.md @@ -0,0 +1,52 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | + +# Async request using ASIO + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +The application aims to show how to compose async operations using ASIO to build network protocols and operations. + +# Configure and Building example + +This example doesn't require any configuration, just build it with + +``` +idf.py build +``` + +# Async operations composition and automatic lifetime control + +On this example we compose the operation by starting the next step in the chain inside the completion handler of the +previous operation. Also we pass the `Connection` class itself as the parameter of its final handler to be owned by +the following operation. This is possible due to the control of lifetime by the usage of `std::shared_ptr`. + +The control of lifetime of the class, done by `std::shared_ptr` usage, guarantee that the data will be available for +async operations until it's not needed any more. This makes necessary that all of the async operation class must start +its lifetime as a `std::shared_ptr` due to the usage of `std::enable_shared_from_this`. + + + User creates a shared_ptr──┐ + of AddressResolution and │ + ask for resolve. │ + The handler for the ┌▼─────────────────────┐ + complete operation is sent│ AddressResolution │ In the completion of resolve a connection is created. + └─────────────────┬────┘ AddressResolution is automaticly destroyed since it's + │ no longer needed + ┌─▼────────────────────────────────────┐ + │ Connection │ + └──────┬───────────────────────────────┘ + Http::Session is created once we have a Connection. │ + Connection is passed to Http::Session that holds it │ + avoiding it's destruction. │ + ┌─▼───────────────────────────────┐ + │ Http::Session │ + └────────┬────────────────────────┘ + After the HTTP request is │ + sent the completion handler │ + is called. │ + └────►Completion Handler() + + +The previous diagram shows the process and the life span of each of the tasks in this examples. At each stage the +object responsible for the last action inject itself to the completion handler of the next stage for reuse. diff --git a/examples/protocols/asio/async_request/main/CMakeLists.txt b/examples/protocols/asio/async_request/main/CMakeLists.txt new file mode 100644 index 000000000..018c22a0a --- /dev/null +++ b/examples/protocols/asio/async_request/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "async_http_request.cpp" + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/async_request/main/async_http_request.cpp b/examples/protocols/asio/async_request/main/async_http_request.cpp new file mode 100644 index 000000000..579a61fe2 --- /dev/null +++ b/examples/protocols/asio/async_request/main/async_http_request.cpp @@ -0,0 +1,369 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * ASIO HTTP request example +*/ + +#include +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "protocol_examples_common.h" + +constexpr auto TAG = "async_request"; +using asio::ip::tcp; + +namespace { + +void esp_init() +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_log_level_set("async_request", ESP_LOG_DEBUG); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); +} + +/** + * @brief Simple class to add the resolver to a chain of actions + * + */ +class AddressResolution : public std::enable_shared_from_this { +public: + explicit AddressResolution(asio::io_context &context) : ctx(context), resolver(ctx) {} + + /** + * @brief Initiator function for the address resolution + * + * @tparam CompletionToken callable responsible to use the results. + * + * @param host Host address + * @param port Port for the target, must be number due to a limitation on lwip. + */ + template + void resolve(const std::string &host, const std::string &port, CompletionToken &&completion_handler) + { + auto self(shared_from_this()); + resolver.async_resolve(host, port, [self, completion_handler](const asio::error_code & error, tcp::resolver::results_type results) { + if (error) { + ESP_LOGE(TAG, "Failed to resolve: %s", error.message().c_str()); + return; + } + completion_handler(self, results); + }); + } + +private: + asio::io_context &ctx; + tcp::resolver resolver; + +}; + +/** + * @brief Connection class + * + * The lowest level dependency on our asynchronous task, Connection provide an interface to TCP sockets. + * A similar class could be provided for a TLS connection. + * + * @note: All read and write operations are written on an explicit strand, even though an implicit strand + * occurs in this example since we run the io context in a single task. + * + */ +class Connection : public std::enable_shared_from_this { +public: + explicit Connection(asio::io_context &context) : ctx(context), strand(context), socket(ctx) {} + + /** + * @brief Start the connection + * + * Async operation to start a connection. As the final act of the process the Connection class pass a + * std::shared_ptr of itself to the completion_handler. + * Since it uses std::shared_ptr as an automatic control of its lifetime this class must be created + * through a std::make_shared call. + * + * @tparam completion_handler A callable to act as the final handler for the process. + * @param host host address + * @param port port number - due to a limitation on lwip implementation this should be the number not the + * service name tipically seen in ASIO examples. + * + * @note The class could be modified to store the completion handler, as a member variable, instead of + * pass it along asynchronous calls to allow the process to run again completely. + * + */ + template + void start(tcp::resolver::results_type results, CompletionToken &&completion_handler) + { + connect(results, completion_handler); + } + + /** + * @brief Start an async write on the socket + * + * @tparam data + * @tparam completion_handler A callable to act as the final handler for the process. + * + */ + template + void write_async(const DataType &data, CompletionToken &&completion_handler) + { + asio::async_write(socket, data, asio::bind_executor(strand, completion_handler)); + } + + /** + * @brief Start an async read on the socket + * + * @tparam data + * @tparam completion_handler A callable to act as the final handler for the process. + * + */ + template + void read_async(DataBuffer &&in_data, CompletionToken &&completion_handler) + { + asio::async_read(socket, in_data, asio::bind_executor(strand, completion_handler)); + } + +private: + + template + void connect(tcp::resolver::results_type results, CompletionToken &&completion_handler) + { + auto self(shared_from_this()); + asio::async_connect(socket, results, [self, completion_handler](const asio::error_code & error, [[maybe_unused]] const tcp::endpoint & endpoint) { + if (error) { + ESP_LOGE(TAG, "Failed to connect: %s", error.message().c_str()); + return; + } + completion_handler(self); + }); + } + asio::io_context &ctx; + asio::io_context::strand strand; + tcp::socket socket; +}; + +} // namespace +namespace Http { +enum class Method { GET }; + +/** + * @brief Simple HTTP request class + * + * The user needs to write the request information direct to header and body fields. + * + * Only GET verb is provided. + * + */ +class Request { +public: + Request(Method method, std::string host, std::string port, const std::string &target) : host_data(std::move(host)), port_data(std::move(port)) + { + header_data.append("GET "); + header_data.append(target); + header_data.append(" HTTP/1.1"); + header_data.append("\r\n"); + header_data.append("Host: "); + header_data.append(host_data); + header_data.append("\r\n"); + header_data.append("\r\n"); + }; + + void set_header_field(std::string const &field) + { + header_data.append(field); + } + + void append_to_body(std::string const &data) + { + body_data.append(data); + }; + + const std::string &host() const + { + return host_data; + } + + const std::string &service_port() const + { + return port_data; + } + + const std::string &header() const + { + return header_data; + } + + const std::string &body() const + { + return body_data; + } + +private: + std::string host_data; + std::string port_data; + std::string header_data; + std::string body_data; +}; + +/** + * @brief Simple HTTP response class + * + * The response is built from received data and only parsed to split header and body. + * + * A copy of the received data is kept. + * + */ +struct Response { + /** + * @brief Construct a response from a contiguous buffer. + * + * Simple http parsing. + * + */ + template + explicit Response(DataIt data, size_t size) + { + raw_response = std::string(data, size); + + auto header_last = raw_response.find("\r\n\r\n"); + if (header_last != std::string::npos) { + header = raw_response.substr(0, header_last); + } + body = raw_response.substr(header_last + 3); + } + /** + * @brief Print response content. + */ + void print() + { + ESP_LOGI(TAG, "Header :\n %s", header.c_str()); + ESP_LOGI(TAG, "Body : \n %s", body.c_str()); + } + + std::string raw_response; + std::string header; + std::string body; +}; + +/** @brief HTTP Session + * + * Session class to handle HTTP protocol implementation. + * + */ +class Session : public std::enable_shared_from_this { +public: + explicit Session(std::shared_ptr connection_in) : connection(std::move(connection_in)) + { + } + + template + void send_request(const Request &request, CompletionToken &&completion_handler) + { + auto self = shared_from_this(); + send_data = { asio::buffer(request.header()), asio::buffer(request.body()) }; + connection->write_async(send_data, [self, &completion_handler](std::error_code error, std::size_t bytes_transfered) { + if (error) { + ESP_LOGE(TAG, "Request write error: %s", error.message().c_str()); + return; + } + ESP_LOGD(TAG, "Bytes Transfered: %d", bytes_transfered); + self->get_response(completion_handler); + }); + } + +private: + template + void get_response(CompletionToken &&completion_handler) + { + auto self = shared_from_this(); + connection->read_async(asio::buffer(receive_buffer), [self, &completion_handler](std::error_code error, std::size_t bytes_received) { + if (error and error.value() != asio::error::eof) { + return; + } + ESP_LOGD(TAG, "Bytes Received: %d", bytes_received); + if (bytes_received == 0) { + return; + } + Response response(std::begin(self->receive_buffer), bytes_received); + + completion_handler(self, response); + }); + } + /* + * For this example we assumed 2048 to be enough for the receive_buffer + */ + std::array receive_buffer; + /* + * The hardcoded 2 below is related to the type we receive the data to send. We gather the parts from Request, header + * and body, to send avoiding the copy. + */ + std::array send_data; + std::shared_ptr connection; +}; + +/** @brief Execute a fully async HTTP request + * + * @tparam completion_handler + * @param ctx io context + * @param request + * + * @note : We build this function as a simpler interface to compose the operations of connecting to + * the address and running the HTTP session. The Http::Session class is injected to the completion handler + * for further use. + */ +template +void request_async(asio::io_context &context, const Request &request, CompletionToken &&completion_handler) +{ + /* + * The first step is to resolve the address we want to connect to. + * The AddressResolution itself is injected to the completion handler. + * + * This shared_ptr is destroyed by the end of the scope. Pay attention that this is a non blocking function + * the lifetime of the object is extended by the resolve call + */ + std::make_shared(context)->resolve(request.host(), request.service_port(), + [&context, &request, completion_handler](std::shared_ptr resolver, tcp::resolver::results_type results) { + /* After resolution we create a Connection. + * The completion handler gets a shared_ptr to receive the connection, once the + * connection process is complete. + */ + std::make_shared(context)->start(results, + [&request, completion_handler](std::shared_ptr connection) { + // Now we create a HTTP::Session and inject the necessary connection. + std::make_shared(connection)->send_request(request, completion_handler); + }); + }); +} +}// namespace Http + +extern "C" void app_main(void) +{ + // Basic initialization of ESP system + esp_init(); + + asio::io_context io_context; + Http::Request request(Http::Method::GET, "www.httpbin.org", "80", "/get"); + Http::request_async(io_context, request, [](std::shared_ptr session, Http::Response response) { + /* + * We only print the response here but could reuse session for other requests. + */ + response.print(); + }); + + // io_context.run will block until all the tasks on the context are done. + io_context.run(); + ESP_LOGI(TAG, "Context run done"); + + ESP_ERROR_CHECK(example_disconnect()); +} From 30dae8f7ed59bf74efe84ed9cc89016d6bd05ed8 Mon Sep 17 00:00:00 2001 From: Euripedes Rocha Date: Wed, 1 Dec 2021 10:48:49 -0300 Subject: [PATCH 50/60] EXAMPLES/ASIO: Adds a SOCKS4 example Creates an example on how to connect using Socks4 based proxy. * Original commit: espressif/esp-idf@f7b842bbc7e66d5c6492808b9e59c69c68973605 --- .../async_request/main/async_http_request.cpp | 4 +- examples/protocols/asio/socks4/CMakeLists.txt | 10 + examples/protocols/asio/socks4/README.md | 73 ++++ .../protocols/asio/socks4/main/CMakeLists.txt | 2 + .../asio/socks4/main/Kconfig.projbuild | 16 + .../protocols/asio/socks4/main/socks4.cpp | 393 ++++++++++++++++++ .../protocols/asio/socks4/main/socks4.hpp | 143 +++++++ .../protocols/asio/socks4/sdkconfig.defaults | 3 + 8 files changed, 642 insertions(+), 2 deletions(-) create mode 100644 examples/protocols/asio/socks4/CMakeLists.txt create mode 100644 examples/protocols/asio/socks4/README.md create mode 100644 examples/protocols/asio/socks4/main/CMakeLists.txt create mode 100644 examples/protocols/asio/socks4/main/Kconfig.projbuild create mode 100644 examples/protocols/asio/socks4/main/socks4.cpp create mode 100644 examples/protocols/asio/socks4/main/socks4.hpp create mode 100644 examples/protocols/asio/socks4/sdkconfig.defaults diff --git a/examples/protocols/asio/async_request/main/async_http_request.cpp b/examples/protocols/asio/async_request/main/async_http_request.cpp index 579a61fe2..3f2df210b 100644 --- a/examples/protocols/asio/async_request/main/async_http_request.cpp +++ b/examples/protocols/asio/async_request/main/async_http_request.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 * @@ -96,7 +96,7 @@ public: * @tparam completion_handler A callable to act as the final handler for the process. * @param host host address * @param port port number - due to a limitation on lwip implementation this should be the number not the - * service name tipically seen in ASIO examples. + * service name typically seen in ASIO examples. * * @note The class could be modified to store the completion handler, as a member variable, instead of * pass it along asynchronous calls to allow the process to run again completely. diff --git a/examples/protocols/asio/socks4/CMakeLists.txt b/examples/protocols/asio/socks4/CMakeLists.txt new file mode 100644 index 000000000..0482e2022 --- /dev/null +++ b/examples/protocols/asio/socks4/CMakeLists.txt @@ -0,0 +1,10 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +# (Not part of the boilerplate) +# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(asio_sock4) diff --git a/examples/protocols/asio/socks4/README.md b/examples/protocols/asio/socks4/README.md new file mode 100644 index 000000000..f9cc88b46 --- /dev/null +++ b/examples/protocols/asio/socks4/README.md @@ -0,0 +1,73 @@ +| Supported Targets | ESP32 | ESP32-S2 | +| ----------------- | ----- | ----- | + +# Async request using ASIO + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +The application aims to show how to connect to a Socks4 proxy using async operations with ASIO. The SOCKS protocol is +briefly described by the diagram below. + + ┌──────┐ ┌─────┐ ┌──────┐ + │Client│ │Proxy│ │Target│ + └──┬───┘ └──┬──┘ └──┬───┘ + │ │ │ + │ ╔═╧══════════════╗ │ +══════════════════════╪════════════════════════╣ Initialization ╠═══╪════════════════════════════════════════════ + │ ╚═╤══════════════╝ │ + │ │ │ + ╔══════════════════╗│ │ │ + ║We establish a ░║│ Socket Connection │ │ + ║TCP connection ║│ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ > │ + ║and get a socket ║│ │ │ + ╚══════════════════╝│ │ │ + │ │ │ + │ ╔═╧══════════════╗ │ +══════════════════════╪════════════════════════╣ Socks Protocol ╠═══╪════════════════════════════════════════════ + │ ╚═╤══════════════╝ │ + │ │ │ + │ Client Connection Request│ │ + │ ─────────────────────────> │ + │ │ │ + │ │ │ + │ ╔════════════╪═══════╤══════════╪════════════════════════════════╗ + │ ║ TARGET CONNECTION │ │ ║ + │ ╟────────────────────┘ │ ╔═══════════════════╗ ║ + │ ║ │ Socket Connection│ ║Proxy establishes ░║ ║ + │ ║ │ <─ ─ ─ ─ ─ ─ ─ ─ > ║ TCPconnection ║ ║ + │ ║ │ │ ║ with target host ║ ║ + │ ╚════════════╪══════════════════╪══╚═══════════════════╝═════════╝ + │ │ │ + │ Response packet │ │ + │ <───────────────────────── │ + │ │ │ + │ │ │ + │ │ ╔═══════╗ │ +══════════════════════╪══════════════════════════╪══╣ Usage ╠═══════╪════════════════════════════════════════════ + │ │ ╚═══════╝ │ + │ │ │ + ╔═════════════════╗│ │ │ + ║Client uses the ░║│ │ │ + ║ socket opened ║│ │ │ + ║ with proxy ║│ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─> + ║to communicate ║│ │ │ + ║ ║│ │ │ + ╚═════════════════╝┴───┐ ┌──┴──┐ ┌──┴───┐ + │Client│ │Proxy│ │Target│ + └──────┘ └─────┘ └──────┘ + + +# Configure and Building example + +This example requires the proxy address to be configured. You can do this using the menuconfig option. +Proxy address and port must be configured in order for this example to work. + +If using Linux ssh can be used as a proxy for testing. + +``` +ssh -N -v -D 0.0.0.0:1080 localhost +``` +# Async operations composition and automatic lifetime control + +For documentation about the structure of this example look into [async\_request README](../async_request/README.md). + diff --git a/examples/protocols/asio/socks4/main/CMakeLists.txt b/examples/protocols/asio/socks4/main/CMakeLists.txt new file mode 100644 index 000000000..517ab52d9 --- /dev/null +++ b/examples/protocols/asio/socks4/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "socks4.cpp" + INCLUDE_DIRS ".") diff --git a/examples/protocols/asio/socks4/main/Kconfig.projbuild b/examples/protocols/asio/socks4/main/Kconfig.projbuild new file mode 100644 index 000000000..984b2f20f --- /dev/null +++ b/examples/protocols/asio/socks4/main/Kconfig.projbuild @@ -0,0 +1,16 @@ +menu "Example Configuration" + + config EXAMPLE_PROXY_ADDRESS + string "Proxy address" + default "myproxy" + help + Address of the proxy to be used. + + config EXAMPLE_PROXY_PORT + string "Proxy port" + default "myport" + help + Port for the proxy. Due to a limitation of lwip, must + be a number e.g. "1080". + +endmenu diff --git a/examples/protocols/asio/socks4/main/socks4.cpp b/examples/protocols/asio/socks4/main/socks4.cpp new file mode 100644 index 000000000..b03d78808 --- /dev/null +++ b/examples/protocols/asio/socks4/main/socks4.cpp @@ -0,0 +1,393 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + * + * + * ASIO Socks4 example +*/ + +#include +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "socks4.hpp" +#include "nvs_flash.h" +#include "esp_event.h" +#include "protocol_examples_common.h" + +constexpr auto TAG = "asio_socks4"; +using asio::ip::tcp; + +namespace { + +void esp_init() +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_log_level_set("async_request", ESP_LOG_DEBUG); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); +} + +/** + * @brief Simple class to add the resolver to a chain of actions + * + */ +class AddressResolution : public std::enable_shared_from_this { +public: + explicit AddressResolution(asio::io_context &context) : ctx(context), resolver(ctx) {} + + /** + * @brief Initiator function for the address resolution + * + * @tparam CompletionToken callable responsible to use the results. + * + * @param host Host address + * @param port Port for the target, must be number due to a limitation on lwip. + */ + template + void resolve(const std::string &host, const std::string &port, CompletionToken &&completion_handler) + { + auto self(shared_from_this()); + resolver.async_resolve(host, port, [self, completion_handler](const asio::error_code & error, tcp::resolver::results_type results) { + if (error) { + ESP_LOGE(TAG, "Failed to resolve: %s", error.message().c_str()); + return; + } + completion_handler(self, results); + }); + } + +private: + asio::io_context &ctx; + tcp::resolver resolver; + +}; + +/** + * @brief Connection class + * + * The lowest level dependency on our asynchronous task, Connection provide an interface to TCP sockets. + * A similar class could be provided for a TLS connection. + * + * @note: All read and write operations are written on an explicit strand, even though an implicit strand + * occurs in this example since we run the io context in a single task. + * + */ +class Connection : public std::enable_shared_from_this { +public: + explicit Connection(asio::io_context &context) : ctx(context), strand(context), socket(ctx) {} + + /** + * @brief Start the connection + * + * Async operation to start a connection. As the final act of the process the Connection class pass a + * std::shared_ptr of itself to the completion_handler. + * Since it uses std::shared_ptr as an automatic control of its lifetime this class must be created + * through a std::make_shared call. + * + * @tparam completion_handler A callable to act as the final handler for the process. + * @param host host address + * @param port port number - due to a limitation on lwip implementation this should be the number not the + * service name typically seen in ASIO examples. + * + * @note The class could be modified to store the completion handler, as a member variable, instead of + * pass it along asynchronous calls to allow the process to run again completely. + * + */ + template + void start(tcp::resolver::results_type results, CompletionToken &&completion_handler) + { + connect(results, completion_handler); + } + + /** + * @brief Start an async write on the socket + * + * @tparam data + * @tparam completion_handler A callable to act as the final handler for the process. + * + */ + template + void write_async(const DataType &data, CompletionToken &&completion_handler) + { + asio::async_write(socket, data, asio::bind_executor(strand, completion_handler)); + } + + /** + * @brief Start an async read on the socket + * + * @tparam data + * @tparam completion_handler A callable to act as the final handler for the process. + * + */ + template + void read_async(DataBuffer &&in_data, CompletionToken &&completion_handler) + { + asio::async_read(socket, in_data, asio::bind_executor(strand, completion_handler)); + } + +private: + + template + void connect(tcp::resolver::results_type results, CompletionToken &&completion_handler) + { + auto self(shared_from_this()); + asio::async_connect(socket, results, [self, completion_handler](const asio::error_code & error, [[maybe_unused]] const tcp::endpoint & endpoint) { + if (error) { + ESP_LOGE(TAG, "Failed to connect: %s", error.message().c_str()); + return; + } + completion_handler(self); + }); + } + asio::io_context &ctx; + asio::io_context::strand strand; + tcp::socket socket; +}; + +} + +namespace Socks { + +struct ConnectionData { + ConnectionData(socks4::request::command_type cmd, const asio::ip::tcp::endpoint &endpoint, + const std::string &user_id) : request(cmd, endpoint, user_id) {}; + socks4::request request; + socks4::reply reply; +}; + +template +void async_connect(asio::io_context &context, std::string proxy, std::string proxy_port, std::string host, std::string port, CompletionToken &&completion_handler) +{ + /* + * The first step is to resolve the address of the proxy we want to connect to. + * The AddressResolution itself is injected to the completion handler. + */ + // Resolve proxy + std::make_shared(context)->resolve(proxy, proxy_port, + [&context, host, port, completion_handler](std::shared_ptr resolver, tcp::resolver::results_type proxy_resolution) { + // We also need to resolve the target host address + resolver->resolve(host, port, [&context, proxy_resolution, completion_handler](std::shared_ptr resolver, tcp::resolver::results_type host_resolution) { + // Make connection with the proxy + ESP_LOGI(TAG, "Startig Proxy Connection"); + std::make_shared(context)->start(proxy_resolution, + [resolver, host_resolution, completion_handler](std::shared_ptr connection) { + auto connect_data = std::make_shared(socks4::request::connect, *host_resolution, ""); + ESP_LOGI(TAG, "Sending Request to proxy for host connection."); + connection->write_async(connect_data->request.buffers(), [connection, connect_data, completion_handler](std::error_code error, std::size_t bytes_received) { + if (error) { + ESP_LOGE(TAG, "Proxy request write error: %s", error.message().c_str()); + return; + } + connection->read_async(connect_data->reply.buffers(), [connection, connect_data, completion_handler](std::error_code error, std::size_t bytes_received) { + if (error) { + + ESP_LOGE(TAG, "Proxy response read error: %s", error.message().c_str()); + return; + } + if (!connect_data->reply.success()) { + ESP_LOGE(TAG, "Proxy error: %#x", connect_data->reply.status()); + } + completion_handler(connection); + + }); + + }); + + }); + + }); + }); + +} +} // namespace Socks + +namespace Http { +enum class Method { GET }; + +/** + * @brief Simple HTTP request class + * + * The user needs to write the request information direct to header and body fields. + * + * Only GET verb is provided. + * + */ +class Request { +public: + Request(Method method, std::string host, std::string port, const std::string &target) : host_data(std::move(host)), port_data(std::move(port)) + { + header_data.append("GET "); + header_data.append(target); + header_data.append(" HTTP/1.1"); + header_data.append("\r\n"); + header_data.append("Host: "); + header_data.append(host_data); + header_data.append("\r\n"); + header_data.append("\r\n"); + }; + + void set_header_field(std::string const &field) + { + header_data.append(field); + } + + void append_to_body(std::string const &data) + { + body_data.append(data); + }; + + const std::string &host() const + { + return host_data; + } + + const std::string &service_port() const + { + return port_data; + } + + const std::string &header() const + { + return header_data; + } + + const std::string &body() const + { + return body_data; + } + +private: + std::string host_data; + std::string port_data; + std::string header_data; + std::string body_data; +}; + +/** + * @brief Simple HTTP response class + * + * The response is built from received data and only parsed to split header and body. + * + * A copy of the received data is kept. + * + */ +struct Response { + /** + * @brief Construct a response from a contiguous buffer. + * + * Simple http parsing. + * + */ + template + explicit Response(DataIt data, size_t size) + { + raw_response = std::string(data, size); + + auto header_last = raw_response.find("\r\n\r\n"); + if (header_last != std::string::npos) { + header = raw_response.substr(0, header_last); + } + body = raw_response.substr(header_last + 3); + } + /** + * @brief Print response content. + */ + void print() + { + ESP_LOGI(TAG, "Header :\n %s", header.c_str()); + ESP_LOGI(TAG, "Body : \n %s", body.c_str()); + } + + std::string raw_response; + std::string header; + std::string body; +}; + +/** @brief HTTP Session + * + * Session class to handle HTTP protocol implementation. + * + */ +class Session : public std::enable_shared_from_this { +public: + explicit Session(std::shared_ptr connection_in) : connection(std::move(connection_in)) + { + } + + template + void send_request(const Request &request, CompletionToken &&completion_handler) + { + auto self = shared_from_this(); + send_data = { asio::buffer(request.header()), asio::buffer(request.body()) }; + connection->write_async(send_data, [self, &completion_handler](std::error_code error, std::size_t bytes_transfered) { + if (error) { + ESP_LOGE(TAG, "Request write error: %s", error.message().c_str()); + return; + } + ESP_LOGD(TAG, "Bytes Transfered: %d", bytes_transfered); + self->get_response(completion_handler); + }); + } + +private: + template + void get_response(CompletionToken &&completion_handler) + { + auto self = shared_from_this(); + connection->read_async(asio::buffer(receive_buffer), [self, &completion_handler](std::error_code error, std::size_t bytes_received) { + if (error and error.value() != asio::error::eof) { + return; + } + ESP_LOGD(TAG, "Bytes Received: %d", bytes_received); + if (bytes_received == 0) { + return; + } + Response response(std::begin(self->receive_buffer), bytes_received); + + completion_handler(self, response); + }); + } + /* + * For this example we assumed 2048 to be enough for the receive_buffer + */ + std::array receive_buffer; + /* + * The hardcoded 2 below is related to the type we receive the data to send. We gather the parts from Request, header + * and body, to send avoiding the copy. + */ + std::array send_data; + std::shared_ptr connection; +}; +}// namespace Http + +extern "C" void app_main(void) +{ + // Basic initialization of ESP system + esp_init(); + + asio::io_context io_context; + Http::Request request(Http::Method::GET, "www.httpbin.org", "80", "/get"); + Socks::async_connect(io_context, CONFIG_EXAMPLE_PROXY_ADDRESS, CONFIG_EXAMPLE_PROXY_PORT, request.host(), request.service_port(), + [&request](std::shared_ptr connection) { + // Now we create a HTTP::Session and inject the necessary connection. + std::make_shared(connection)->send_request(request, [](std::shared_ptr session, Http::Response response) { + response.print(); + }); + }); + // io_context.run will block until all the tasks on the context are done. + io_context.run(); + ESP_LOGI(TAG, "Context run done"); + + ESP_ERROR_CHECK(example_disconnect()); +} diff --git a/examples/protocols/asio/socks4/main/socks4.hpp b/examples/protocols/asio/socks4/main/socks4.hpp new file mode 100644 index 000000000..a039c07ca --- /dev/null +++ b/examples/protocols/asio/socks4/main/socks4.hpp @@ -0,0 +1,143 @@ +// +// socks4.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef SOCKS4_HPP +#define SOCKS4_HPP + +#include +#include +#include +#include + +namespace socks4 { + +const unsigned char version = 0x04; + +class request +{ +public: + enum command_type + { + connect = 0x01, + bind = 0x02 + }; + + request(command_type cmd, const asio::ip::tcp::endpoint& endpoint, + const std::string& user_id) + : version_(version), + command_(cmd), + user_id_(user_id), + null_byte_(0) + { + // Only IPv4 is supported by the SOCKS 4 protocol. + if (endpoint.protocol() != asio::ip::tcp::v4()) + { + throw asio::system_error( + asio::error::address_family_not_supported); + } + + // Convert port number to network byte order. + unsigned short port = endpoint.port(); + port_high_byte_ = (port >> 8) & 0xff; + port_low_byte_ = port & 0xff; + + // Save IP address in network byte order. + address_ = endpoint.address().to_v4().to_bytes(); + } + + std::array buffers() const + { + return + { + { + asio::buffer(&version_, 1), + asio::buffer(&command_, 1), + asio::buffer(&port_high_byte_, 1), + asio::buffer(&port_low_byte_, 1), + asio::buffer(address_), + asio::buffer(user_id_), + asio::buffer(&null_byte_, 1) + } + }; + } + +private: + unsigned char version_; + unsigned char command_; + unsigned char port_high_byte_; + unsigned char port_low_byte_; + asio::ip::address_v4::bytes_type address_; + std::string user_id_; + unsigned char null_byte_; +}; + +class reply +{ +public: + enum status_type + { + request_granted = 0x5a, + request_failed = 0x5b, + request_failed_no_identd = 0x5c, + request_failed_bad_user_id = 0x5d + }; + + reply() + : null_byte_(0), + status_() + { + } + + std::array buffers() + { + return + { + { + asio::buffer(&null_byte_, 1), + asio::buffer(&status_, 1), + asio::buffer(&port_high_byte_, 1), + asio::buffer(&port_low_byte_, 1), + asio::buffer(address_) + } + }; + } + + bool success() const + { + return null_byte_ == 0 && status_ == request_granted; + } + + unsigned char status() const + { + return status_; + } + + asio::ip::tcp::endpoint endpoint() const + { + unsigned short port = port_high_byte_; + port = (port << 8) & 0xff00; + port = port | port_low_byte_; + + asio::ip::address_v4 address(address_); + + return asio::ip::tcp::endpoint(address, port); + } + +private: + unsigned char null_byte_; + unsigned char status_; + unsigned char port_high_byte_; + unsigned char port_low_byte_; + asio::ip::address_v4::bytes_type address_; +}; + +} // namespace socks4 + +#endif // SOCKS4_HPP diff --git a/examples/protocols/asio/socks4/sdkconfig.defaults b/examples/protocols/asio/socks4/sdkconfig.defaults new file mode 100644 index 000000000..a6320e2c3 --- /dev/null +++ b/examples/protocols/asio/socks4/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_COMPILER_CXX_EXCEPTIONS=y +CONFIG_COMPILER_CXX_RTTI=y +CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 From 98138189c9d4bc886cb8ce289599d9270c11ede6 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Fri, 28 May 2021 18:43:32 +0530 Subject: [PATCH 51/60] mbedtls-3 update: 1) Fix build issue in mbedtls 2) skip the public headers check in IDF 3)Update Kconfig Macros 4)Remove deprecated config options 5) Update the sha API according to new nomenclature 6) Update mbedtls_rsa_init usage 7) Include mbedtls/build_info.h instead of mbedtls/config.h 8) Dont include check_config.h 9) Add additional error message in esp_blufi_api.h * Original commit: espressif/esp-idf@45122533e0bca5d538585e22308f14b74c33e474 --- components/asio/port/mbedtls/include/mbedtls_engine.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/asio/port/mbedtls/include/mbedtls_engine.hpp b/components/asio/port/mbedtls/include/mbedtls_engine.hpp index 9e77acbc3..d9ac614d4 100644 --- a/components/asio/port/mbedtls/include/mbedtls_engine.hpp +++ b/components/asio/port/mbedtls/include/mbedtls_engine.hpp @@ -1,5 +1,5 @@ // -// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +// SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD // // SPDX-License-Identifier: BSL-1.0 // @@ -141,7 +141,7 @@ private: int ret = 0; mbedtls_ssl_set_bio(&impl_.ssl_, bio_.first.get(), bio_write, bio_read, nullptr); - while (impl_.ssl_.state != MBEDTLS_SSL_HANDSHAKE_OVER) { + while (impl_.ssl_.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake_step(&impl_.ssl_); if (ret != 0) { @@ -189,7 +189,7 @@ private: bool before_handshake() const { - return ssl_.state == 0; + return ssl_.MBEDTLS_PRIVATE(state) == 0; } int write(const void *buffer, int len) @@ -246,7 +246,7 @@ private: return false; } ret = mbedtls_pk_parse_key(&pk_key_, ctx->data(container::PRIVKEY), ctx->size(container::PRIVKEY), - nullptr, 0); + nullptr, 0, mbedtls_ctr_drbg_random, &ctr_drbg_); if (ret < 0) { print_error("mbedtls_pk_parse_keyfile", ret); return false; From e3c439124654d31c308a130f58fef427d1f6f4ec Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Mon, 14 Mar 2022 14:16:14 +0530 Subject: [PATCH 52/60] mbedtls: Remove certs.c and certs.h from port directory * Original commit: espressif/esp-idf@f31d8dd2955be0fe949340dcf3b043ec6daf4378 --- components/asio/port/mbedtls/include/mbedtls_engine.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/components/asio/port/mbedtls/include/mbedtls_engine.hpp b/components/asio/port/mbedtls/include/mbedtls_engine.hpp index d9ac614d4..a52ba459d 100644 --- a/components/asio/port/mbedtls/include/mbedtls_engine.hpp +++ b/components/asio/port/mbedtls/include/mbedtls_engine.hpp @@ -9,7 +9,6 @@ #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" -#include "mbedtls/certs.h" #include "mbedtls/esp_debug.h" #include "esp_log.h" From 952e5df4773194c7e29458b78633720d44e940c0 Mon Sep 17 00:00:00 2001 From: Euripedes Rocha Date: Wed, 13 Apr 2022 11:22:34 -0300 Subject: [PATCH 53/60] [EXAMPLES/ASIO] Renames Kconfig parameter and clarify On ip::tcp::resolver ASIO uses service to identify the type of connection and get the port number. LWIP can't resolve this way. * Original commit: espressif/esp-idf@232b0eda5fc97ece0ed32028c013635846fed435 --- examples/protocols/asio/socks4/main/Kconfig.projbuild | 8 ++++---- examples/protocols/asio/socks4/main/socks4.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/protocols/asio/socks4/main/Kconfig.projbuild b/examples/protocols/asio/socks4/main/Kconfig.projbuild index 984b2f20f..69dd024cd 100644 --- a/examples/protocols/asio/socks4/main/Kconfig.projbuild +++ b/examples/protocols/asio/socks4/main/Kconfig.projbuild @@ -6,11 +6,11 @@ menu "Example Configuration" help Address of the proxy to be used. - config EXAMPLE_PROXY_PORT - string "Proxy port" + config EXAMPLE_PROXY_SERVICE + string "Proxy Service Type" default "myport" help - Port for the proxy. Due to a limitation of lwip, must - be a number e.g. "1080". + Service type. Due to a limitation of lwip, must + be the port number e.g. "1080". endmenu diff --git a/examples/protocols/asio/socks4/main/socks4.cpp b/examples/protocols/asio/socks4/main/socks4.cpp index b03d78808..5bd0011ed 100644 --- a/examples/protocols/asio/socks4/main/socks4.cpp +++ b/examples/protocols/asio/socks4/main/socks4.cpp @@ -378,7 +378,7 @@ extern "C" void app_main(void) asio::io_context io_context; Http::Request request(Http::Method::GET, "www.httpbin.org", "80", "/get"); - Socks::async_connect(io_context, CONFIG_EXAMPLE_PROXY_ADDRESS, CONFIG_EXAMPLE_PROXY_PORT, request.host(), request.service_port(), + Socks::async_connect(io_context, CONFIG_EXAMPLE_PROXY_ADDRESS, CONFIG_EXAMPLE_PROXY_SERVICE, request.host(), request.service_port(), [&request](std::shared_ptr connection) { // Now we create a HTTP::Session and inject the necessary connection. std::make_shared(connection)->send_request(request, [](std::shared_ptr session, Http::Response response) { From 0c84c9750ce800ab965c1bf3191cd7ba8cf6cdaf Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Thu, 28 Apr 2022 14:34:20 +0800 Subject: [PATCH 54/60] docs: update redirected links * Original commit: espressif/esp-idf@030cb77597eccf2a0d5f5bf6c9d5c58bf4110bd7 --- docs/en/api-reference/protocols/asio.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-reference/protocols/asio.rst b/docs/en/api-reference/protocols/asio.rst index 0306a5ae1..ec6b0b159 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/docs/en/api-reference/protocols/asio.rst @@ -3,7 +3,7 @@ ASIO port Overview -------- -Asio is a cross-platform C++ library, see https://think-async.com. It provides a consistent asynchronous model using a modern C++ approach. +Asio is a cross-platform C++ library, see https://think-async.com/Asio/. It provides a consistent asynchronous model using a modern C++ approach. ASIO documentation From 938ddf16b9911b6126a56fa4c0e8571918cdcb85 Mon Sep 17 00:00:00 2001 From: Djordje Nedic Date: Fri, 27 May 2022 10:10:51 +0200 Subject: [PATCH 55/60] tools: Increase the minimal supported CMake version to 3.16 This updates the minimal supported version of CMake to 3.16, which in turn enables us to use more CMake features and have a cleaner build system. This is the version that provides most new features and also the one we use in our latest docker image for CI. * Original commit: espressif/esp-idf@facab8c5a78323dceb0a418ecaaaa4319b102793 --- examples/protocols/asio/asio_chat/CMakeLists.txt | 2 +- examples/protocols/asio/async_request/CMakeLists.txt | 2 +- examples/protocols/asio/socks4/CMakeLists.txt | 2 +- examples/protocols/asio/ssl_client_server/CMakeLists.txt | 2 +- examples/protocols/asio/tcp_echo_server/CMakeLists.txt | 2 +- examples/protocols/asio/udp_echo_server/CMakeLists.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/protocols/asio/asio_chat/CMakeLists.txt b/examples/protocols/asio/asio_chat/CMakeLists.txt index 483b43d70..31a345c19 100644 --- a/examples/protocols/asio/asio_chat/CMakeLists.txt +++ b/examples/protocols/asio/asio_chat/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. diff --git a/examples/protocols/asio/async_request/CMakeLists.txt b/examples/protocols/asio/async_request/CMakeLists.txt index fc7e3c944..b360f7df5 100644 --- a/examples/protocols/asio/async_request/CMakeLists.txt +++ b/examples/protocols/asio/async_request/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. diff --git a/examples/protocols/asio/socks4/CMakeLists.txt b/examples/protocols/asio/socks4/CMakeLists.txt index 0482e2022..1a2667508 100644 --- a/examples/protocols/asio/socks4/CMakeLists.txt +++ b/examples/protocols/asio/socks4/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. diff --git a/examples/protocols/asio/ssl_client_server/CMakeLists.txt b/examples/protocols/asio/ssl_client_server/CMakeLists.txt index 804b8428b..927c74690 100644 --- a/examples/protocols/asio/ssl_client_server/CMakeLists.txt +++ b/examples/protocols/asio/ssl_client_server/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. diff --git a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt index 6bf8f4682..9ed3aab2d 100644 --- a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/tcp_echo_server/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. diff --git a/examples/protocols/asio/udp_echo_server/CMakeLists.txt b/examples/protocols/asio/udp_echo_server/CMakeLists.txt index 59493277c..1282ffd88 100644 --- a/examples/protocols/asio/udp_echo_server/CMakeLists.txt +++ b/examples/protocols/asio/udp_echo_server/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. From 63bff632df07035152a963b5bb73e9bbbf7a4748 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 14 Feb 2022 13:46:21 +0100 Subject: [PATCH 56/60] esp_netif/lwip: Implement basic support for vanilla-lwip (2.1.3-REL) * Reference lwip-2.1.3-REL vanilla lwip version * Use inherent NETIF callbacks instead of dhcp/ipv6/autoip * Original commit: espressif/esp-idf@5b471a18489b056f65fe8dcbb2c992d27909ebc9 --- components/asio/port/include/esp_asio_config.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index 53215ca16..d80717ed9 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,8 +21,7 @@ // // LWIP compatibility inet and address macros/functions // -# define LWIP_COMPAT_SOCKET_INET 1 -# define LWIP_COMPAT_SOCKET_ADDR 1 +# include "esp_cpp_sockets.h" // // Specific ASIO feature flags From 057a5d2db8adab8f0880c3f9a17d611bfe0e82e6 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 17 Mar 2022 13:07:05 +0100 Subject: [PATCH 57/60] lwip: Update socket API to include port-version of sockets/netdb Added socket extention to the lwip hooks for implementing non-vanilla {get/set}sockopts() * Original commit: espressif/esp-idf@53c009e62631bae569fa849c6b6c9e70a10b3afe --- components/asio/port/include/esp_asio_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index d80717ed9..f8e34d617 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -19,9 +19,9 @@ # endif // CONFIG_COMPILER_RTTI // -// LWIP compatibility inet and address macros/functions +// Use system sockets // -# include "esp_cpp_sockets.h" +# include "sys/socket.h" // // Specific ASIO feature flags From 2cf751811484f52cb7a3f5035cb6eb3eb1ba74b1 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Fri, 20 May 2022 17:50:08 +0800 Subject: [PATCH 58/60] ci: partially enable example build for esp32c2 * Original commit: espressif/esp-idf@f7be540222e204f682dfe27bb23f0f622f5a93e7 --- examples/protocols/asio/asio_chat/README.md | 5 ++++- examples/protocols/asio/ssl_client_server/README.md | 9 ++++++--- examples/protocols/asio/tcp_echo_server/README.md | 3 +++ examples/protocols/asio/udp_echo_server/README.md | 3 +++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/examples/protocols/asio/asio_chat/README.md b/examples/protocols/asio/asio_chat/README.md index 4848b457b..2896e9ab7 100644 --- a/examples/protocols/asio/asio_chat/README.md +++ b/examples/protocols/asio/asio_chat/README.md @@ -1,3 +1,6 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | -------- | + # Asio chat client and server examples @@ -48,7 +51,7 @@ Set following parameters under Example Configuration Options: - Connect to the server using multiple clients, for example using any option below. - build and run asio chat client on your host machine - run chat_client asio example on ESP platform - - since chat messages consists of ASCII size and message, it is possible to + - since chat messages consists of ASCII size and message, it is possible to netcat `nc IP PORT` and type for example ` 4ABC` to transmit 'ABC\n' ## Running the example in client mode diff --git a/examples/protocols/asio/ssl_client_server/README.md b/examples/protocols/asio/ssl_client_server/README.md index e99ccfe11..fbf2cc15e 100644 --- a/examples/protocols/asio/ssl_client_server/README.md +++ b/examples/protocols/asio/ssl_client_server/README.md @@ -1,3 +1,6 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | -------- | + # Asio SSL client/server example Simple Asio client and server with SSL/TLS transport @@ -13,8 +16,8 @@ to connect to internet or a local network via WiFi or Ethernet to easily exercis * Open the project configuration menu (`idf.py menuconfig`) * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. -* Enable the ASIO client and set server's host name to examine client's functionality. -The ASIO client connects to the configured server and sends default payload string "GET / HTTP/1.1" +* Enable the ASIO client and set server's host name to examine client's functionality. +The ASIO client connects to the configured server and sends default payload string "GET / HTTP/1.1" * Enable the ASIO server to examine server's functionality. The ASIO server listens to connection and echos back what was received. ### Build and Flash @@ -58,7 +61,7 @@ D ### Both server and client enabled The below output demonstrates the client connecting to the ASIO server via loopback interface, so no WiFi, nor Ethernet connection -was established. +was established. ``` I (0) cpu_start: App cpu up. I (495) heap_init: Initializing. RAM available for dynamic allocation: diff --git a/examples/protocols/asio/tcp_echo_server/README.md b/examples/protocols/asio/tcp_echo_server/README.md index b2443a245..2c3893550 100644 --- a/examples/protocols/asio/tcp_echo_server/README.md +++ b/examples/protocols/asio/tcp_echo_server/README.md @@ -1,3 +1,6 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | -------- | + # Asio TCP echo server example Simple Asio TCP echo server using WiFi STA or Ethernet. diff --git a/examples/protocols/asio/udp_echo_server/README.md b/examples/protocols/asio/udp_echo_server/README.md index cc8a67e66..cd384fc39 100644 --- a/examples/protocols/asio/udp_echo_server/README.md +++ b/examples/protocols/asio/udp_echo_server/README.md @@ -1,3 +1,6 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | -------- | + # Asio UDP echo server example Simple Asio UDP echo server using WiFi STA or Ethernet. From ac7bf465d290eb1196dde3e1d94d6b5ee313a02a Mon Sep 17 00:00:00 2001 From: gabsuren Date: Wed, 22 Jun 2022 17:55:10 +0400 Subject: [PATCH 59/60] asio: Disable concepts support Fix example for compatibility with C++20 * Original commit: espressif/esp-idf@9dba0476a01cd80d76e21706ad350009606b877e * Original commit: espressif/esp-idf@157247f98fcfe73dbb126b740206e8603eb6e002 --- components/asio/port/include/esp_asio_config.h | 1 + examples/protocols/asio/asio_chat/main/chat_message.hpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/asio/port/include/esp_asio_config.h b/components/asio/port/include/esp_asio_config.h index f8e34d617..cf42183a3 100644 --- a/components/asio/port/include/esp_asio_config.h +++ b/components/asio/port/include/esp_asio_config.h @@ -30,6 +30,7 @@ # define ASIO_SEPARATE_COMPILATION # define ASIO_STANDALONE # define ASIO_HAS_PTHREADS +# define ASIO_DISABLE_CONCEPTS # ifdef CONFIG_ASIO_USE_ESP_OPENSSL # define ASIO_USE_ESP_OPENSSL diff --git a/examples/protocols/asio/asio_chat/main/chat_message.hpp b/examples/protocols/asio/asio_chat/main/chat_message.hpp index 629105b05..a6ffc83b8 100644 --- a/examples/protocols/asio/asio_chat/main/chat_message.hpp +++ b/examples/protocols/asio/asio_chat/main/chat_message.hpp @@ -18,8 +18,8 @@ class chat_message { public: - enum { header_length = 4 }; - enum { max_body_length = 512 }; + static constexpr std::size_t header_length = 4; + static constexpr std::size_t max_body_length = 512; chat_message() : body_length_(0) From 055f051f537a2f0395e7359437a57f3d0369bfd4 Mon Sep 17 00:00:00 2001 From: gabsuren Date: Wed, 22 Jun 2022 14:49:37 +0400 Subject: [PATCH 60/60] ASIO: Initial version based on IDF 5.0 with history --- .../build_and_run_example_test_mdns.yml | 5 +- ... build_and_run_example_test_websocket.yml} | 4 +- .github/workflows/build_asio.yml | 28 +++++++ .github/workflows/publish-docs-component.yml | 8 +- .gitmodules | 3 + README.md | 5 ++ components/asio/README.md | 11 +++ components/asio/asio | 2 +- components/asio/docs/Doxyfile | 73 +++++++++++++++++++ components/asio/docs/conf_common.py | 21 ++++++ components/asio/docs/en/conf.py | 24 ++++++ .../asio/docs/en/index.rst | 10 +-- components/asio/docs/generate_docs | 27 +++++++ components/asio/docs/zh_CN/conf.py | 27 +++++++ .../asio/docs/zh_CN/index.rst | 0 .../asio/examples}/asio_chat/CMakeLists.txt | 2 +- .../asio/examples}/asio_chat/README.md | 0 .../asio/examples}/asio_chat/example_test.py | 0 .../examples}/asio_chat/main/CMakeLists.txt | 0 .../asio_chat/main/Kconfig.projbuild | 0 .../examples}/asio_chat/main/asio_chat.cpp | 0 .../examples}/asio_chat/main/chat_message.hpp | 0 .../asio/examples}/asio_chat/main/client.hpp | 0 .../asio/examples}/asio_chat/main/server.hpp | 0 .../asio/examples}/asio_chat/sdkconfig.ci | 0 .../examples}/asio_chat/sdkconfig.defaults | 0 .../examples}/async_request/CMakeLists.txt | 2 +- .../asio/examples}/async_request/README.md | 0 .../async_request/main/CMakeLists.txt | 0 .../async_request/main/async_http_request.cpp | 0 .../asio/examples}/socks4/CMakeLists.txt | 2 +- .../asio/examples}/socks4/README.md | 0 .../asio/examples}/socks4/main/CMakeLists.txt | 0 .../examples}/socks4/main/Kconfig.projbuild | 0 .../asio/examples}/socks4/main/socks4.cpp | 0 .../asio/examples}/socks4/main/socks4.hpp | 0 .../asio/examples}/socks4/sdkconfig.defaults | 0 .../ssl_client_server/CMakeLists.txt | 2 +- .../examples}/ssl_client_server/README.md | 0 .../ssl_client_server/example_test.py | 0 .../ssl_client_server/main/CMakeLists.txt | 0 .../ssl_client_server/main/Kconfig.projbuild | 0 .../ssl_client_server/main/asio_ssl_main.cpp | 0 .../examples}/ssl_client_server/main/ca.crt | 0 .../ssl_client_server/main/server.key | 0 .../examples}/ssl_client_server/main/srv.crt | 0 .../ssl_client_server/partitions.csv | 0 .../examples}/ssl_client_server/sdkconfig.ci | 0 .../ssl_client_server/sdkconfig.defaults | 0 .../examples}/tcp_echo_server/CMakeLists.txt | 2 +- .../asio/examples}/tcp_echo_server/README.md | 0 .../tcp_echo_server/asio_tcp_server_test.py | 0 .../tcp_echo_server/main/CMakeLists.txt | 0 .../tcp_echo_server/main/Kconfig.projbuild | 0 .../tcp_echo_server/main/echo_server.cpp | 0 .../tcp_echo_server/sdkconfig.defaults | 0 .../examples}/udp_echo_server/CMakeLists.txt | 2 +- .../asio/examples}/udp_echo_server/README.md | 0 .../udp_echo_server/asio_udp_server_test.py | 0 .../udp_echo_server/main/CMakeLists.txt | 0 .../udp_echo_server/main/Kconfig.projbuild | 0 .../udp_echo_server/main/udp_echo_server.cpp | 0 .../udp_echo_server/sdkconfig.defaults | 0 components/asio/idf_component.yml | 5 ++ 64 files changed, 250 insertions(+), 15 deletions(-) rename .github/workflows/{build_and_run_example_test.yml => build_and_run_example_test_websocket.yml} (97%) create mode 100644 .github/workflows/build_asio.yml create mode 100644 .gitmodules create mode 100644 components/asio/README.md create mode 100755 components/asio/docs/Doxyfile create mode 100644 components/asio/docs/conf_common.py create mode 100644 components/asio/docs/en/conf.py rename docs/en/api-reference/protocols/asio.rst => components/asio/docs/en/index.rst (79%) create mode 100755 components/asio/docs/generate_docs create mode 100644 components/asio/docs/zh_CN/conf.py rename docs/zh_CN/api-reference/protocols/asio.rst => components/asio/docs/zh_CN/index.rst (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/CMakeLists.txt (79%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/README.md (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/example_test.py (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/main/CMakeLists.txt (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/main/Kconfig.projbuild (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/main/asio_chat.cpp (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/main/chat_message.hpp (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/main/client.hpp (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/main/server.hpp (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/sdkconfig.ci (100%) rename {examples/protocols/asio => components/asio/examples}/asio_chat/sdkconfig.defaults (100%) rename {examples/protocols/asio => components/asio/examples}/async_request/CMakeLists.txt (80%) rename {examples/protocols/asio => components/asio/examples}/async_request/README.md (100%) rename {examples/protocols/asio => components/asio/examples}/async_request/main/CMakeLists.txt (100%) rename {examples/protocols/asio => components/asio/examples}/async_request/main/async_http_request.cpp (100%) rename {examples/protocols/asio => components/asio/examples}/socks4/CMakeLists.txt (79%) rename {examples/protocols/asio => components/asio/examples}/socks4/README.md (100%) rename {examples/protocols/asio => components/asio/examples}/socks4/main/CMakeLists.txt (100%) rename {examples/protocols/asio => components/asio/examples}/socks4/main/Kconfig.projbuild (100%) rename {examples/protocols/asio => components/asio/examples}/socks4/main/socks4.cpp (100%) rename {examples/protocols/asio => components/asio/examples}/socks4/main/socks4.hpp (100%) rename {examples/protocols/asio => components/asio/examples}/socks4/sdkconfig.defaults (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/CMakeLists.txt (81%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/README.md (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/example_test.py (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/main/CMakeLists.txt (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/main/Kconfig.projbuild (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/main/asio_ssl_main.cpp (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/main/ca.crt (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/main/server.key (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/main/srv.crt (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/partitions.csv (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/sdkconfig.ci (100%) rename {examples/protocols/asio => components/asio/examples}/ssl_client_server/sdkconfig.defaults (100%) rename {examples/protocols/asio => components/asio/examples}/tcp_echo_server/CMakeLists.txt (80%) rename {examples/protocols/asio => components/asio/examples}/tcp_echo_server/README.md (100%) rename {examples/protocols/asio => components/asio/examples}/tcp_echo_server/asio_tcp_server_test.py (100%) rename {examples/protocols/asio => components/asio/examples}/tcp_echo_server/main/CMakeLists.txt (100%) rename {examples/protocols/asio => components/asio/examples}/tcp_echo_server/main/Kconfig.projbuild (100%) rename {examples/protocols/asio => components/asio/examples}/tcp_echo_server/main/echo_server.cpp (100%) rename {examples/protocols/asio => components/asio/examples}/tcp_echo_server/sdkconfig.defaults (100%) rename {examples/protocols/asio => components/asio/examples}/udp_echo_server/CMakeLists.txt (80%) rename {examples/protocols/asio => components/asio/examples}/udp_echo_server/README.md (100%) rename {examples/protocols/asio => components/asio/examples}/udp_echo_server/asio_udp_server_test.py (100%) rename {examples/protocols/asio => components/asio/examples}/udp_echo_server/main/CMakeLists.txt (100%) rename {examples/protocols/asio => components/asio/examples}/udp_echo_server/main/Kconfig.projbuild (100%) rename {examples/protocols/asio => components/asio/examples}/udp_echo_server/main/udp_echo_server.cpp (100%) rename {examples/protocols/asio => components/asio/examples}/udp_echo_server/sdkconfig.defaults (100%) create mode 100644 components/asio/idf_component.yml diff --git a/.github/workflows/build_and_run_example_test_mdns.yml b/.github/workflows/build_and_run_example_test_mdns.yml index de4aac90e..3d309a6f5 100644 --- a/.github/workflows/build_and_run_example_test_mdns.yml +++ b/.github/workflows/build_and_run_example_test_mdns.yml @@ -13,8 +13,9 @@ jobs: container: espressif/idf:${{ matrix.idf_ver }} steps: - name: Checkout esp-protocols - uses: actions/checkout@master + uses: actions/checkout@v3 with: + submodules: recursive path: esp-protocols - name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} env: @@ -23,6 +24,7 @@ jobs: run: | . ${IDF_PATH}/export.sh cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/examples/ + idf.py set-target ${{ matrix.idf_target }} cat sdkconfig.ci.eth_def >> sdkconfig.defaults idf.py build rm sdkconfig.defaults @@ -32,4 +34,5 @@ jobs: cat sdkconfig.ci.eth_socket >> sdkconfig.defaults idf.py build cd $GITHUB_WORKSPACE/esp-protocols/components/mdns/tests/test_apps/ + idf.py set-target ${{ matrix.idf_target }} idf.py build diff --git a/.github/workflows/build_and_run_example_test.yml b/.github/workflows/build_and_run_example_test_websocket.yml similarity index 97% rename from .github/workflows/build_and_run_example_test.yml rename to .github/workflows/build_and_run_example_test_websocket.yml index 4f26acd48..678b6d1e6 100644 --- a/.github/workflows/build_and_run_example_test.yml +++ b/.github/workflows/build_and_run_example_test_websocket.yml @@ -13,7 +13,9 @@ jobs: container: espressif/idf:${{ matrix.idf_ver }} steps: - name: Checkout esp-protocols - uses: actions/checkout@v1 + uses: actions/checkout@v3 + with: + submodules: recursive - name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} env: IDF_TARGET: ${{ matrix.idf_target }} diff --git a/.github/workflows/build_asio.yml b/.github/workflows/build_asio.yml new file mode 100644 index 000000000..83ccf2d94 --- /dev/null +++ b/.github/workflows/build_asio.yml @@ -0,0 +1,28 @@ +name: Build ASIO + +on: [push, pull_request] + +jobs: + build: + strategy: + matrix: + idf_ver: ["latest"] + idf_target: ["esp32", "esp32s2"] + example: ["asio_chat", "async_request", "socks4", "ssl_client_server", "tcp_echo_server", "udp_echo_server"] + + runs-on: ubuntu-20.04 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - name: Checkout esp-protocols + uses: actions/checkout@v3 + with: + path: esp-protocols + - name: Build ${{ matrix.example }} with IDF-${{ matrix.idf_ver }} for ${{ matrix.idf_target }} + env: + IDF_TARGET: ${{ matrix.idf_target }} + shell: bash + run: | + . ${IDF_PATH}/export.sh + cd $GITHUB_WORKSPACE/esp-protocols/components/asio/examples/${{ matrix.example }} + idf.py set-target ${{ matrix.idf_target }} + idf.py build diff --git a/.github/workflows/publish-docs-component.yml b/.github/workflows/publish-docs-component.yml index fbc674a2d..0eeda079c 100644 --- a/.github/workflows/publish-docs-component.yml +++ b/.github/workflows/publish-docs-component.yml @@ -39,10 +39,16 @@ jobs: cp -r html_en/. $GITHUB_WORKSPACE/docs/mdns/en cp -r html_zh_CN/. $GITHUB_WORKSPACE/docs/mdns/zh_CN + cd $GITHUB_WORKSPACE/components/asio/docs + ./generate_docs + mkdir -p $GITHUB_WORKSPACE/docs/asio + cp -r html/. $GITHUB_WORKSPACE/docs/asio + cd $GITHUB_WORKSPACE/docs touch .nojekyll echo 'esp-modem
' > index.html echo 'esp-websocket-client
' >> index.html + echo 'ASIO
' >> index.html echo 'mDNS_en
' >> index.html echo 'mDNS_zh_CN
' >> index.html @@ -50,7 +56,7 @@ jobs: - name: Upload components to component service uses: espressif/github-actions/upload_components@master with: - directories: "components/esp_modem;components/esp_websocket_client;components/mdns" + directories: "components/esp_modem;components/esp_websocket_client;components/mdns;components/asio" namespace: "espressif" api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..6ecce627b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "components/asio/asio"] + path = components/asio/asio + url = https://github.com/espressif/asio diff --git a/README.md b/README.md index c886af4b8..c422581ad 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,8 @@ * Brief introduction [README](components/esp_websocket_client/README.md) * Full html [documentation](https://espressif.github.io/esp-protocols/esp_websocket_client/index.html) + +### ASIO port + +* Brief introduction [README](components/asio/README.md) +* Full html [documentation](https://espressif.github.io/esp-protocols/asio/index.html) diff --git a/components/asio/README.md b/components/asio/README.md new file mode 100644 index 000000000..acfbd5f91 --- /dev/null +++ b/components/asio/README.md @@ -0,0 +1,11 @@ +# ASIO port + +Asio is a cross-platform C++ library, see https://think-async.com/Asio/. It provides a consistent asynchronous model using a modern C++ approach. + +## Examples + +Get started with example test :example:`examples `: + +## Documentation + +* View the full [html documentation](https://espressif.github.io/esp-protocols/asio/index.html) diff --git a/components/asio/asio b/components/asio/asio index f31694c9f..58384fb6a 160000 --- a/components/asio/asio +++ b/components/asio/asio @@ -1 +1 @@ -Subproject commit f31694c9f1746ba189a4bcae2e34db15135ddb22 +Subproject commit 58384fb6af92e7952b1534acb3004924f7ea0565 diff --git a/components/asio/docs/Doxyfile b/components/asio/docs/Doxyfile new file mode 100755 index 000000000..1e95d8217 --- /dev/null +++ b/components/asio/docs/Doxyfile @@ -0,0 +1,73 @@ +# This is Doxygen configuration file +# +# Doxygen provides over 260 configuration statements +# To make this file easier to follow, +# it contains only statements that are non-default +# +# NOTE: +# It is recommended not to change defaults unless specifically required +# Test any changes how they affect generated documentation +# Make sure that correct warnings are generated to flag issues with documented code +# +# For the complete list of configuration statements see: +# http://doxygen.nl/manual/config.html + + +PROJECT_NAME = "ESP Protocols Programming Guide" + +## The 'INPUT' statement below is used as input by script 'gen-df-input.py' +## to automatically generate API reference list files heder_file.inc +## These files are placed in '_inc' directory +## and used to include in API reference documentation + + +## Get warnings for functions that have no documentation for their parameters or return value +## +WARN_NO_PARAMDOC = YES + +## Enable preprocessing and remove __attribute__(...) expressions from the INPUT files +## +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +PREDEFINED = \ + $(ENV_DOXYGEN_DEFINES) \ + __DOXYGEN__=1 \ + __attribute__(x)= \ + _Static_assert()= \ + IDF_DEPRECATED(X)= \ + IRAM_ATTR= \ + configSUPPORT_DYNAMIC_ALLOCATION=1 \ + configSUPPORT_STATIC_ALLOCATION=1 \ + configQUEUE_REGISTRY_SIZE=1 \ + configUSE_RECURSIVE_MUTEXES=1 \ + configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS=1 \ + configNUM_THREAD_LOCAL_STORAGE_POINTERS=1 \ + configUSE_APPLICATION_TASK_TAG=1 \ + configTASKLIST_INCLUDE_COREID=1 \ + "ESP_EVENT_DECLARE_BASE(x)=extern esp_event_base_t x" + +## Do not complain about not having dot +## +HAVE_DOT = NO + +## Generate XML that is required for Breathe +## +GENERATE_XML = YES +XML_OUTPUT = xml + +GENERATE_HTML = NO +HAVE_DOT = NO +GENERATE_LATEX = NO +GENERATE_MAN = YES +GENERATE_RTF = NO + +## Skip distracting progress messages +## +QUIET = YES + +## Enable Section Tags for conditional documentation +## +ENABLED_SECTIONS += \ + DOC_EXCLUDE_HEADER_SECTION \ ## To conditionally remove doc sections from IDF source files without affecting documentation in upstream files. + DOC_SINGLE_GROUP ## To conditionally remove groups from the documentation and create a 'flat' document without affecting documentation in upstream files. diff --git a/components/asio/docs/conf_common.py b/components/asio/docs/conf_common.py new file mode 100644 index 000000000..10d1e997e --- /dev/null +++ b/components/asio/docs/conf_common.py @@ -0,0 +1,21 @@ +from esp_docs.conf_docs import * # noqa: F403,F401 + +extensions += ['sphinx_copybutton', + # Needed as a trigger for running doxygen + 'esp_docs.esp_extensions.dummy_build_system', + 'esp_docs.esp_extensions.run_doxygen', + ] + +# link roles config +github_repo = 'espressif/esp-protocols' + +# context used by sphinx_idf_theme +html_context['github_user'] = 'espressif' +html_context['github_repo'] = 'esp-protocols' + +# Extra options required by sphinx_idf_theme +project_slug = 'esp-idf' # >=5.0 +versions_url = 'https://github.com/espressif/esp-protocols/docs/docs_versions.js' + +idf_targets = ['esp32'] +languages = ['en', 'zh_CN'] diff --git a/components/asio/docs/en/conf.py b/components/asio/docs/en/conf.py new file mode 100644 index 000000000..bba642268 --- /dev/null +++ b/components/asio/docs/en/conf.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# +# English Language RTD & Sphinx config file +# +# Uses ../conf_common.py for most non-language-specific settings. + +# Importing conf_common adds all the non-language-specific +# parts to this conf module + +try: + from conf_common import * # noqa: F403,F401 +except ImportError: + import os + import sys + sys.path.insert(0, os.path.abspath('../')) + from conf_common import * # noqa: F403,F401 + +# General information about the project. +project = u'ESP-Protocols' +copyright = u'2016 - 2022, Espressif Systems (Shanghai) Co., Ltd' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +language = 'en' diff --git a/docs/en/api-reference/protocols/asio.rst b/components/asio/docs/en/index.rst similarity index 79% rename from docs/en/api-reference/protocols/asio.rst rename to components/asio/docs/en/index.rst index ec6b0b159..56ff694f2 100644 --- a/docs/en/api-reference/protocols/asio.rst +++ b/components/asio/docs/en/index.rst @@ -32,11 +32,11 @@ Internal asio settings for ESP include Application Example ------------------- -ESP examples are based on standard asio :example:`protocols/asio`: +ESP examples are based on standard asio :example:`examples <../examples>`: -- :example:`protocols/asio/udp_echo_server` -- :example:`protocols/asio/tcp_echo_server` -- :example:`protocols/asio/asio_chat` -- :example:`protocols/asio/ssl_client_server` +- :example:`udp_echo_server <../examples/udp_echo_server>` +- :example:`tcp_echo_server <../examples/tcp_echo_server>` +- :example:`asio_chat <../examples/asio_chat>` +- :example:`ssl_client_server <../examples/ssl_client_server>` Please refer to the specific example README.md for details diff --git a/components/asio/docs/generate_docs b/components/asio/docs/generate_docs new file mode 100755 index 000000000..e60c1a8f9 --- /dev/null +++ b/components/asio/docs/generate_docs @@ -0,0 +1,27 @@ +build-docs --target esp32 --language en + +cp -rf _build/en/esp32/html . +rm -rf _build __pycache__ + +# Modifes some version and target fields of index.html +echo "" >> html/index.html + diff --git a/components/asio/docs/zh_CN/conf.py b/components/asio/docs/zh_CN/conf.py new file mode 100644 index 000000000..cc6fbc271 --- /dev/null +++ b/components/asio/docs/zh_CN/conf.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# +# English Language RTD & Sphinx config file +# +# Uses ../conf_common.py for most non-language-specific settings. + +# Importing conf_common adds all the non-language-specific +# parts to this conf module +try: + from conf_common import * # noqa: F403,F401 +except ImportError: + import os + import sys + sys.path.insert(0, os.path.abspath('..')) + from conf_common import * # noqa: F403,F401 + +import datetime + +current_year = datetime.datetime.now().year + +# General information about the project. +project = u'ESP-IDF 编程指南' +copyright = u'2016 - {} 乐鑫信息科技(上海)股份有限公司'.format(current_year) + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +language = 'zh_CN' diff --git a/docs/zh_CN/api-reference/protocols/asio.rst b/components/asio/docs/zh_CN/index.rst similarity index 100% rename from docs/zh_CN/api-reference/protocols/asio.rst rename to components/asio/docs/zh_CN/index.rst diff --git a/examples/protocols/asio/asio_chat/CMakeLists.txt b/components/asio/examples/asio_chat/CMakeLists.txt similarity index 79% rename from examples/protocols/asio/asio_chat/CMakeLists.txt rename to components/asio/examples/asio_chat/CMakeLists.txt index 31a345c19..2d3c9ecbe 100644 --- a/examples/protocols/asio/asio_chat/CMakeLists.txt +++ b/components/asio/examples/asio_chat/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_chat) diff --git a/examples/protocols/asio/asio_chat/README.md b/components/asio/examples/asio_chat/README.md similarity index 100% rename from examples/protocols/asio/asio_chat/README.md rename to components/asio/examples/asio_chat/README.md diff --git a/examples/protocols/asio/asio_chat/example_test.py b/components/asio/examples/asio_chat/example_test.py similarity index 100% rename from examples/protocols/asio/asio_chat/example_test.py rename to components/asio/examples/asio_chat/example_test.py diff --git a/examples/protocols/asio/asio_chat/main/CMakeLists.txt b/components/asio/examples/asio_chat/main/CMakeLists.txt similarity index 100% rename from examples/protocols/asio/asio_chat/main/CMakeLists.txt rename to components/asio/examples/asio_chat/main/CMakeLists.txt diff --git a/examples/protocols/asio/asio_chat/main/Kconfig.projbuild b/components/asio/examples/asio_chat/main/Kconfig.projbuild similarity index 100% rename from examples/protocols/asio/asio_chat/main/Kconfig.projbuild rename to components/asio/examples/asio_chat/main/Kconfig.projbuild diff --git a/examples/protocols/asio/asio_chat/main/asio_chat.cpp b/components/asio/examples/asio_chat/main/asio_chat.cpp similarity index 100% rename from examples/protocols/asio/asio_chat/main/asio_chat.cpp rename to components/asio/examples/asio_chat/main/asio_chat.cpp diff --git a/examples/protocols/asio/asio_chat/main/chat_message.hpp b/components/asio/examples/asio_chat/main/chat_message.hpp similarity index 100% rename from examples/protocols/asio/asio_chat/main/chat_message.hpp rename to components/asio/examples/asio_chat/main/chat_message.hpp diff --git a/examples/protocols/asio/asio_chat/main/client.hpp b/components/asio/examples/asio_chat/main/client.hpp similarity index 100% rename from examples/protocols/asio/asio_chat/main/client.hpp rename to components/asio/examples/asio_chat/main/client.hpp diff --git a/examples/protocols/asio/asio_chat/main/server.hpp b/components/asio/examples/asio_chat/main/server.hpp similarity index 100% rename from examples/protocols/asio/asio_chat/main/server.hpp rename to components/asio/examples/asio_chat/main/server.hpp diff --git a/examples/protocols/asio/asio_chat/sdkconfig.ci b/components/asio/examples/asio_chat/sdkconfig.ci similarity index 100% rename from examples/protocols/asio/asio_chat/sdkconfig.ci rename to components/asio/examples/asio_chat/sdkconfig.ci diff --git a/examples/protocols/asio/asio_chat/sdkconfig.defaults b/components/asio/examples/asio_chat/sdkconfig.defaults similarity index 100% rename from examples/protocols/asio/asio_chat/sdkconfig.defaults rename to components/asio/examples/asio_chat/sdkconfig.defaults diff --git a/examples/protocols/asio/async_request/CMakeLists.txt b/components/asio/examples/async_request/CMakeLists.txt similarity index 80% rename from examples/protocols/asio/async_request/CMakeLists.txt rename to components/asio/examples/async_request/CMakeLists.txt index b360f7df5..ff659707e 100644 --- a/examples/protocols/asio/async_request/CMakeLists.txt +++ b/components/asio/examples/async_request/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(async_http_request) diff --git a/examples/protocols/asio/async_request/README.md b/components/asio/examples/async_request/README.md similarity index 100% rename from examples/protocols/asio/async_request/README.md rename to components/asio/examples/async_request/README.md diff --git a/examples/protocols/asio/async_request/main/CMakeLists.txt b/components/asio/examples/async_request/main/CMakeLists.txt similarity index 100% rename from examples/protocols/asio/async_request/main/CMakeLists.txt rename to components/asio/examples/async_request/main/CMakeLists.txt diff --git a/examples/protocols/asio/async_request/main/async_http_request.cpp b/components/asio/examples/async_request/main/async_http_request.cpp similarity index 100% rename from examples/protocols/asio/async_request/main/async_http_request.cpp rename to components/asio/examples/async_request/main/async_http_request.cpp diff --git a/examples/protocols/asio/socks4/CMakeLists.txt b/components/asio/examples/socks4/CMakeLists.txt similarity index 79% rename from examples/protocols/asio/socks4/CMakeLists.txt rename to components/asio/examples/socks4/CMakeLists.txt index 1a2667508..f1ffe9d12 100644 --- a/examples/protocols/asio/socks4/CMakeLists.txt +++ b/components/asio/examples/socks4/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_sock4) diff --git a/examples/protocols/asio/socks4/README.md b/components/asio/examples/socks4/README.md similarity index 100% rename from examples/protocols/asio/socks4/README.md rename to components/asio/examples/socks4/README.md diff --git a/examples/protocols/asio/socks4/main/CMakeLists.txt b/components/asio/examples/socks4/main/CMakeLists.txt similarity index 100% rename from examples/protocols/asio/socks4/main/CMakeLists.txt rename to components/asio/examples/socks4/main/CMakeLists.txt diff --git a/examples/protocols/asio/socks4/main/Kconfig.projbuild b/components/asio/examples/socks4/main/Kconfig.projbuild similarity index 100% rename from examples/protocols/asio/socks4/main/Kconfig.projbuild rename to components/asio/examples/socks4/main/Kconfig.projbuild diff --git a/examples/protocols/asio/socks4/main/socks4.cpp b/components/asio/examples/socks4/main/socks4.cpp similarity index 100% rename from examples/protocols/asio/socks4/main/socks4.cpp rename to components/asio/examples/socks4/main/socks4.cpp diff --git a/examples/protocols/asio/socks4/main/socks4.hpp b/components/asio/examples/socks4/main/socks4.hpp similarity index 100% rename from examples/protocols/asio/socks4/main/socks4.hpp rename to components/asio/examples/socks4/main/socks4.hpp diff --git a/examples/protocols/asio/socks4/sdkconfig.defaults b/components/asio/examples/socks4/sdkconfig.defaults similarity index 100% rename from examples/protocols/asio/socks4/sdkconfig.defaults rename to components/asio/examples/socks4/sdkconfig.defaults diff --git a/examples/protocols/asio/ssl_client_server/CMakeLists.txt b/components/asio/examples/ssl_client_server/CMakeLists.txt similarity index 81% rename from examples/protocols/asio/ssl_client_server/CMakeLists.txt rename to components/asio/examples/ssl_client_server/CMakeLists.txt index 927c74690..73ee939a7 100644 --- a/examples/protocols/asio/ssl_client_server/CMakeLists.txt +++ b/components/asio/examples/ssl_client_server/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common) set(EXCLUDE_COMPONENTS openssl) include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/examples/protocols/asio/ssl_client_server/README.md b/components/asio/examples/ssl_client_server/README.md similarity index 100% rename from examples/protocols/asio/ssl_client_server/README.md rename to components/asio/examples/ssl_client_server/README.md diff --git a/examples/protocols/asio/ssl_client_server/example_test.py b/components/asio/examples/ssl_client_server/example_test.py similarity index 100% rename from examples/protocols/asio/ssl_client_server/example_test.py rename to components/asio/examples/ssl_client_server/example_test.py diff --git a/examples/protocols/asio/ssl_client_server/main/CMakeLists.txt b/components/asio/examples/ssl_client_server/main/CMakeLists.txt similarity index 100% rename from examples/protocols/asio/ssl_client_server/main/CMakeLists.txt rename to components/asio/examples/ssl_client_server/main/CMakeLists.txt diff --git a/examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild b/components/asio/examples/ssl_client_server/main/Kconfig.projbuild similarity index 100% rename from examples/protocols/asio/ssl_client_server/main/Kconfig.projbuild rename to components/asio/examples/ssl_client_server/main/Kconfig.projbuild diff --git a/examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp b/components/asio/examples/ssl_client_server/main/asio_ssl_main.cpp similarity index 100% rename from examples/protocols/asio/ssl_client_server/main/asio_ssl_main.cpp rename to components/asio/examples/ssl_client_server/main/asio_ssl_main.cpp diff --git a/examples/protocols/asio/ssl_client_server/main/ca.crt b/components/asio/examples/ssl_client_server/main/ca.crt similarity index 100% rename from examples/protocols/asio/ssl_client_server/main/ca.crt rename to components/asio/examples/ssl_client_server/main/ca.crt diff --git a/examples/protocols/asio/ssl_client_server/main/server.key b/components/asio/examples/ssl_client_server/main/server.key similarity index 100% rename from examples/protocols/asio/ssl_client_server/main/server.key rename to components/asio/examples/ssl_client_server/main/server.key diff --git a/examples/protocols/asio/ssl_client_server/main/srv.crt b/components/asio/examples/ssl_client_server/main/srv.crt similarity index 100% rename from examples/protocols/asio/ssl_client_server/main/srv.crt rename to components/asio/examples/ssl_client_server/main/srv.crt diff --git a/examples/protocols/asio/ssl_client_server/partitions.csv b/components/asio/examples/ssl_client_server/partitions.csv similarity index 100% rename from examples/protocols/asio/ssl_client_server/partitions.csv rename to components/asio/examples/ssl_client_server/partitions.csv diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.ci b/components/asio/examples/ssl_client_server/sdkconfig.ci similarity index 100% rename from examples/protocols/asio/ssl_client_server/sdkconfig.ci rename to components/asio/examples/ssl_client_server/sdkconfig.ci diff --git a/examples/protocols/asio/ssl_client_server/sdkconfig.defaults b/components/asio/examples/ssl_client_server/sdkconfig.defaults similarity index 100% rename from examples/protocols/asio/ssl_client_server/sdkconfig.defaults rename to components/asio/examples/ssl_client_server/sdkconfig.defaults diff --git a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt b/components/asio/examples/tcp_echo_server/CMakeLists.txt similarity index 80% rename from examples/protocols/asio/tcp_echo_server/CMakeLists.txt rename to components/asio/examples/tcp_echo_server/CMakeLists.txt index 9ed3aab2d..29e290677 100644 --- a/examples/protocols/asio/tcp_echo_server/CMakeLists.txt +++ b/components/asio/examples/tcp_echo_server/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_tcp_echo_server) diff --git a/examples/protocols/asio/tcp_echo_server/README.md b/components/asio/examples/tcp_echo_server/README.md similarity index 100% rename from examples/protocols/asio/tcp_echo_server/README.md rename to components/asio/examples/tcp_echo_server/README.md diff --git a/examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py b/components/asio/examples/tcp_echo_server/asio_tcp_server_test.py similarity index 100% rename from examples/protocols/asio/tcp_echo_server/asio_tcp_server_test.py rename to components/asio/examples/tcp_echo_server/asio_tcp_server_test.py diff --git a/examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt b/components/asio/examples/tcp_echo_server/main/CMakeLists.txt similarity index 100% rename from examples/protocols/asio/tcp_echo_server/main/CMakeLists.txt rename to components/asio/examples/tcp_echo_server/main/CMakeLists.txt diff --git a/examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild b/components/asio/examples/tcp_echo_server/main/Kconfig.projbuild similarity index 100% rename from examples/protocols/asio/tcp_echo_server/main/Kconfig.projbuild rename to components/asio/examples/tcp_echo_server/main/Kconfig.projbuild diff --git a/examples/protocols/asio/tcp_echo_server/main/echo_server.cpp b/components/asio/examples/tcp_echo_server/main/echo_server.cpp similarity index 100% rename from examples/protocols/asio/tcp_echo_server/main/echo_server.cpp rename to components/asio/examples/tcp_echo_server/main/echo_server.cpp diff --git a/examples/protocols/asio/tcp_echo_server/sdkconfig.defaults b/components/asio/examples/tcp_echo_server/sdkconfig.defaults similarity index 100% rename from examples/protocols/asio/tcp_echo_server/sdkconfig.defaults rename to components/asio/examples/tcp_echo_server/sdkconfig.defaults diff --git a/examples/protocols/asio/udp_echo_server/CMakeLists.txt b/components/asio/examples/udp_echo_server/CMakeLists.txt similarity index 80% rename from examples/protocols/asio/udp_echo_server/CMakeLists.txt rename to components/asio/examples/udp_echo_server/CMakeLists.txt index 1282ffd88..2e0c28024 100644 --- a/examples/protocols/asio/udp_echo_server/CMakeLists.txt +++ b/components/asio/examples/udp_echo_server/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.16) # (Not part of the boilerplate) # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection. -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) +set(EXTRA_COMPONENT_DIRS ../../../../common_components/protocol_examples_common) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(asio_udp_echo_server) diff --git a/examples/protocols/asio/udp_echo_server/README.md b/components/asio/examples/udp_echo_server/README.md similarity index 100% rename from examples/protocols/asio/udp_echo_server/README.md rename to components/asio/examples/udp_echo_server/README.md diff --git a/examples/protocols/asio/udp_echo_server/asio_udp_server_test.py b/components/asio/examples/udp_echo_server/asio_udp_server_test.py similarity index 100% rename from examples/protocols/asio/udp_echo_server/asio_udp_server_test.py rename to components/asio/examples/udp_echo_server/asio_udp_server_test.py diff --git a/examples/protocols/asio/udp_echo_server/main/CMakeLists.txt b/components/asio/examples/udp_echo_server/main/CMakeLists.txt similarity index 100% rename from examples/protocols/asio/udp_echo_server/main/CMakeLists.txt rename to components/asio/examples/udp_echo_server/main/CMakeLists.txt diff --git a/examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild b/components/asio/examples/udp_echo_server/main/Kconfig.projbuild similarity index 100% rename from examples/protocols/asio/udp_echo_server/main/Kconfig.projbuild rename to components/asio/examples/udp_echo_server/main/Kconfig.projbuild diff --git a/examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp b/components/asio/examples/udp_echo_server/main/udp_echo_server.cpp similarity index 100% rename from examples/protocols/asio/udp_echo_server/main/udp_echo_server.cpp rename to components/asio/examples/udp_echo_server/main/udp_echo_server.cpp diff --git a/examples/protocols/asio/udp_echo_server/sdkconfig.defaults b/components/asio/examples/udp_echo_server/sdkconfig.defaults similarity index 100% rename from examples/protocols/asio/udp_echo_server/sdkconfig.defaults rename to components/asio/examples/udp_echo_server/sdkconfig.defaults diff --git a/components/asio/idf_component.yml b/components/asio/idf_component.yml new file mode 100644 index 000000000..b2e11a570 --- /dev/null +++ b/components/asio/idf_component.yml @@ -0,0 +1,5 @@ +version: "1.0.1" +description: ASIO +dependencies: + idf: + version: ">=5.0"