mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-06-25 17:31:33 +02:00
fix(modem): Fixed OAT test to verify server cert and CN
This commit is contained in:
@ -29,6 +29,7 @@ public:
|
||||
int read(unsigned char *buf, size_t len);
|
||||
[[nodiscard]] bool set_own_cert(const_buf crt, const_buf key);
|
||||
[[nodiscard]] bool set_ca_cert(const_buf crt);
|
||||
bool set_hostname(const char *name);
|
||||
virtual int send(const unsigned char *buf, size_t len) = 0;
|
||||
virtual int recv(unsigned char *buf, size_t len) = 0;
|
||||
size_t get_available_bytes();
|
||||
|
@ -116,6 +116,16 @@ bool Tls::set_ca_cert(const_buf crt)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tls::set_hostname(const char *name)
|
||||
{
|
||||
int ret = mbedtls_ssl_set_hostname(&ssl_, name);
|
||||
if (ret < 0) {
|
||||
print_error("mbedtls_ssl_set_hostname", ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Tls::Tls()
|
||||
{
|
||||
mbedtls_x509_crt_init(&public_cert_);
|
||||
|
@ -19,3 +19,9 @@ sudo pppd /dev/ttyUSB1 115200 192.168.11.1:192.168.11.2 ms-dns 8.8.8.8 modem loc
|
||||
```
|
||||
* MQTT broker: Running mosquitto in the default config is enough, configuring the broker's URL to the local PPP address: `config.broker.address.uri = "mqtt://192.168.11.1";`
|
||||
* HTTP server: Need to support HTTP/1.1 (to support ranges). You can use the script `http_server.py` and configure the OTA endpoint as `"https://192.168.11.1:1234/esp32.bin"`
|
||||
|
||||
## Potential issues
|
||||
|
||||
When running this test it is expected to experience some buffer overflows or connection interruption.
|
||||
The modem library should recover from these failure modes and continue and complete OTA update.
|
||||
These issues are expected, since UART ISR is deliberately not placed into IRAM in the test configuration to exhibit some minor communication glitches.
|
||||
|
BIN
components/esp_modem/test/target_ota/bin/blink.bin
Normal file
BIN
components/esp_modem/test/target_ota/bin/blink.bin
Normal file
Binary file not shown.
@ -17,17 +17,9 @@ static const char *TAG = "manual_ota";
|
||||
bool manual_ota::begin()
|
||||
{
|
||||
if (status != state::UNDEF) {
|
||||
ESP_LOGE(TAG, "Invalid state");
|
||||
ESP_LOGE(TAG, "Invalid state for manual_ota::perform");
|
||||
return false;
|
||||
}
|
||||
status = state::INIT;
|
||||
esp_transport_handle_t tcp = esp_transport_tcp_init();
|
||||
ssl_ = esp_transport_batch_tls_init(tcp, max_buffer_size_);
|
||||
|
||||
esp_http_client_config_t config = { };
|
||||
config.skip_cert_common_name_check = true;
|
||||
config.url = uri_;
|
||||
config.transport = ssl_;
|
||||
const esp_partition_t *configured = esp_ota_get_boot_partition();
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
|
||||
@ -36,38 +28,40 @@ bool manual_ota::begin()
|
||||
return false;
|
||||
}
|
||||
|
||||
http_ = esp_http_client_init(&config);
|
||||
if (http_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to initialise HTTP connection");
|
||||
return false;
|
||||
}
|
||||
esp_http_client_set_method(http_, HTTP_METHOD_HEAD);
|
||||
esp_err_t err = esp_http_client_perform(http_);
|
||||
if (err == ESP_OK) {
|
||||
int http_status = esp_http_client_get_status_code(http_);
|
||||
if (http_status != HttpStatus_Ok) {
|
||||
ESP_LOGE(TAG, "Received incorrect http status %d", http_status);
|
||||
return false;
|
||||
status = state::INIT;
|
||||
max_buffer_size_ = size_ * 1024;
|
||||
if (mode_ == mode::BATCH) {
|
||||
#ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT
|
||||
esp_transport_handle_t tcp = esp_transport_tcp_init();
|
||||
ssl_ = esp_transport_batch_tls_init(tcp, max_buffer_size_);
|
||||
http_.config_.transport = ssl_;
|
||||
if (!esp_transport_batch_set_ca_cert(ssl_, http_.config_.cert_pem, 0)) {
|
||||
return fail();
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "ESP HTTP client perform failed: %d", err);
|
||||
if (!esp_transport_batch_set_cn(ssl_, common_name_)) {
|
||||
return fail();
|
||||
}
|
||||
#else
|
||||
ESP_LOGE(TAG, "mode::BATCH Cannot be used without CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!http_.init()) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
image_length_ = http_.get_image_len();
|
||||
if (image_length_ <= 0) {
|
||||
return fail();
|
||||
}
|
||||
image_length_ = esp_http_client_get_content_length(http_);
|
||||
ESP_LOGI(TAG, "image_length = %lld", image_length_);
|
||||
esp_http_client_close(http_);
|
||||
|
||||
if (image_length_ > size_) {
|
||||
char *header_val = nullptr;
|
||||
asprintf(&header_val, "bytes=0-%d", max_buffer_size_ - 1);
|
||||
if (header_val == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for HTTP header");
|
||||
return false;
|
||||
if (!http_.set_range(0, max_buffer_size_ - 1)) {
|
||||
return fail();
|
||||
}
|
||||
esp_http_client_set_header(http_, "Range", header_val);
|
||||
free(header_val);
|
||||
}
|
||||
esp_http_client_set_method(http_, HTTP_METHOD_GET);
|
||||
esp_http_client_set_method(http_.handle_, HTTP_METHOD_GET);
|
||||
|
||||
partition_ = esp_ota_get_next_update_partition(nullptr);
|
||||
if (partition_ == nullptr) {
|
||||
@ -86,40 +80,42 @@ bool manual_ota::begin()
|
||||
bool manual_ota::perform()
|
||||
{
|
||||
if (status != state::IMAGE_CHECK && status != state::START) {
|
||||
ESP_LOGE(TAG, "Invalid state");
|
||||
ESP_LOGE(TAG, "Invalid state for manual_ota::perform");
|
||||
return false;
|
||||
}
|
||||
esp_err_t err = esp_http_client_open(http_, 0);
|
||||
esp_err_t err = esp_http_client_open(http_.handle_, 0);
|
||||
if (err != ESP_OK) {
|
||||
if (image_length_ == file_length_) {
|
||||
status = state::END;
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_http_client_close(http_);
|
||||
esp_http_client_close(http_.handle_);
|
||||
ESP_LOGI(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
||||
if (reconnect_attempts_++ < max_reconnect_attempts_) {
|
||||
if (prepare_reconnect()) {
|
||||
return true; // will retry in the next iteration
|
||||
}
|
||||
return true; // will retry in the next iteration
|
||||
}
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
esp_http_client_fetch_headers(http_);
|
||||
esp_http_client_fetch_headers(http_.handle_);
|
||||
|
||||
int batch_len = esp_transport_batch_tls_pre_read(ssl_, max_buffer_size_, timeout_ * 1000);
|
||||
if (batch_len < 0) {
|
||||
ESP_LOGE(TAG, "Error: Failed to pre-read plain text data!");
|
||||
return fail_cleanup();
|
||||
int batch_len = max_buffer_size_;
|
||||
if (mode_ == mode::BATCH) {
|
||||
batch_len = esp_transport_batch_tls_pre_read(ssl_, max_buffer_size_, timeout_ * 1000);
|
||||
if (batch_len < 0) {
|
||||
ESP_LOGE(TAG, "Error: Failed to pre-read plain text data!");
|
||||
fail();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int data_read = esp_http_client_read(http_, buffer_.data(), batch_len);
|
||||
int data_read = esp_http_client_read(http_.handle_, buffer_.data(), batch_len);
|
||||
|
||||
if (data_read < 0) {
|
||||
ESP_LOGE(TAG, "Error: SSL data read error");
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
} else if (data_read > 0) {
|
||||
esp_http_client_close(http_);
|
||||
esp_http_client_close(http_.handle_);
|
||||
|
||||
if (status == state::IMAGE_CHECK) {
|
||||
esp_app_desc_t new_app_info;
|
||||
@ -146,7 +142,7 @@ bool manual_ota::perform()
|
||||
ESP_LOGW(TAG, "New version is the same as invalid version.");
|
||||
ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version);
|
||||
ESP_LOGW(TAG, "The firmware has been rolled back to the previous version.");
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,20 +150,18 @@ bool manual_ota::perform()
|
||||
err = esp_ota_begin(partition_, OTA_WITH_SEQUENTIAL_WRITES, &update_handle_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||
esp_ota_abort(update_handle_);
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
ota_begin = true;
|
||||
ESP_LOGI(TAG, "esp_ota_begin succeeded");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Received chunk doesn't contain app descriptor");
|
||||
esp_ota_abort(update_handle_);
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
}
|
||||
err = esp_ota_write(update_handle_, (const void *)buffer_.data(), data_read);
|
||||
if (err != ESP_OK) {
|
||||
esp_ota_abort(update_handle_);
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
file_length_ += data_read;
|
||||
ESP_LOGI(TAG, "Written image length %d", file_length_);
|
||||
@ -178,28 +172,22 @@ bool manual_ota::perform()
|
||||
}
|
||||
|
||||
if (!prepare_reconnect()) {
|
||||
esp_ota_abort(update_handle_);
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
|
||||
} else if (data_read == 0) {
|
||||
if (file_length_ == 0) {
|
||||
// Try to handle possible HTTP redirections
|
||||
int status_code = esp_http_client_get_status_code(http_);
|
||||
ESP_LOGW(TAG, "Status code: %d", status_code);
|
||||
err = esp_http_client_set_redirection(http_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "URL redirection Failed");
|
||||
esp_ota_abort(update_handle_);
|
||||
return fail_cleanup();
|
||||
if (!http_.handle_redirects()) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
err = esp_http_client_open(http_, 0);
|
||||
err = esp_http_client_open(http_.handle_, 0);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
esp_http_client_fetch_headers(http_);
|
||||
esp_http_client_fetch_headers(http_.handle_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,26 +196,13 @@ bool manual_ota::perform()
|
||||
|
||||
bool manual_ota::prepare_reconnect()
|
||||
{
|
||||
esp_http_client_set_method(http_, HTTP_METHOD_GET);
|
||||
char *header_val = nullptr;
|
||||
if ((image_length_ - file_length_) > max_buffer_size_) {
|
||||
asprintf(&header_val, "bytes=%d-%d", file_length_, (file_length_ + max_buffer_size_ - 1));
|
||||
} else {
|
||||
asprintf(&header_val, "bytes=%d-", file_length_);
|
||||
}
|
||||
if (header_val == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for HTTP header");
|
||||
return false;
|
||||
}
|
||||
esp_http_client_set_header(http_, "Range", header_val);
|
||||
free(header_val);
|
||||
return true;
|
||||
esp_http_client_set_method(http_.handle_, HTTP_METHOD_GET);
|
||||
return http_.set_range(file_length_,
|
||||
(image_length_ - file_length_) > max_buffer_size_ ? (file_length_ + max_buffer_size_ - 1) : 0);
|
||||
}
|
||||
|
||||
bool manual_ota::fail_cleanup()
|
||||
bool manual_ota::fail()
|
||||
{
|
||||
esp_http_client_close(http_);
|
||||
esp_http_client_cleanup(http_);
|
||||
status = state::FAIL;
|
||||
return false;
|
||||
}
|
||||
@ -235,9 +210,9 @@ bool manual_ota::fail_cleanup()
|
||||
bool manual_ota::end()
|
||||
{
|
||||
if (status == state::END) {
|
||||
if (!esp_http_client_is_complete_data_received(http_)) {
|
||||
if (!http_.is_data_complete()) {
|
||||
ESP_LOGE(TAG, "Error in receiving complete file");
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
esp_err_t err = esp_ota_end(update_handle_);
|
||||
if (err != ESP_OK) {
|
||||
@ -246,14 +221,97 @@ bool manual_ota::end()
|
||||
} else {
|
||||
ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err));
|
||||
}
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
ota_begin = false;
|
||||
err = esp_ota_set_boot_partition(partition_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
|
||||
return fail_cleanup();
|
||||
return fail();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
manual_ota::~manual_ota()
|
||||
{
|
||||
if (ota_begin) {
|
||||
esp_ota_abort(update_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
bool manual_ota::http_client::handle_redirects()
|
||||
{
|
||||
int status_code = esp_http_client_get_status_code(handle_);
|
||||
ESP_LOGW(TAG, "Status code: %d", status_code);
|
||||
esp_err_t err = esp_http_client_set_redirection(handle_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "URL redirection Failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
err = esp_http_client_open(handle_, 0);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
esp_http_client_fetch_headers(handle_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool manual_ota::http_client::set_range(size_t from, size_t to)
|
||||
{
|
||||
char *header_val = nullptr;
|
||||
if (to != 0) {
|
||||
asprintf(&header_val, "bytes=%d-%d", from, to);
|
||||
} else {
|
||||
asprintf(&header_val, "bytes=%d-", from);
|
||||
}
|
||||
if (header_val == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for HTTP header");
|
||||
return false;
|
||||
}
|
||||
esp_http_client_set_header(handle_, "Range", header_val);
|
||||
free(header_val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool manual_ota::http_client::is_data_complete()
|
||||
{
|
||||
return esp_http_client_is_complete_data_received(handle_);
|
||||
}
|
||||
|
||||
manual_ota::http_client::~http_client()
|
||||
{
|
||||
if (handle_) {
|
||||
esp_http_client_close(handle_);
|
||||
esp_http_client_cleanup(handle_);
|
||||
}
|
||||
}
|
||||
|
||||
bool manual_ota::http_client::init()
|
||||
{
|
||||
handle_ = esp_http_client_init(&config_);
|
||||
return handle_ != nullptr;
|
||||
}
|
||||
|
||||
int64_t manual_ota::http_client::get_image_len()
|
||||
{
|
||||
esp_http_client_set_method(handle_, HTTP_METHOD_HEAD);
|
||||
esp_err_t err = esp_http_client_perform(handle_);
|
||||
if (err == ESP_OK) {
|
||||
int http_status = esp_http_client_get_status_code(handle_);
|
||||
if (http_status != HttpStatus_Ok) {
|
||||
ESP_LOGE(TAG, "Received incorrect http status %d", http_status);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "ESP HTTP client perform failed: %d", err);
|
||||
return -1;
|
||||
}
|
||||
int64_t image_length = esp_http_client_get_content_length(handle_);
|
||||
ESP_LOGI(TAG, "image_length = %lld", image_length);
|
||||
esp_http_client_close(handle_);
|
||||
return image_length;
|
||||
}
|
||||
|
@ -12,23 +12,57 @@
|
||||
|
||||
class manual_ota {
|
||||
public:
|
||||
enum class state {
|
||||
UNDEF,
|
||||
INIT,
|
||||
IMAGE_CHECK,
|
||||
START,
|
||||
END,
|
||||
FAIL,
|
||||
};
|
||||
/**
|
||||
* @brief Set the preferred mode
|
||||
*/
|
||||
enum class mode {
|
||||
BATCH, /**< Read data chunk from TCP and pass it to SSL, restore session on reconnection */
|
||||
NORMAL /**< Use standard partial download, continuously passing data from TCP to mbedTLS */
|
||||
} mode_ {mode::BATCH};
|
||||
|
||||
/**
|
||||
* @brief Set the OTA batch size in kB
|
||||
*
|
||||
* This would allocate two big buffers:
|
||||
* - one for reading from TCP socket and
|
||||
* - one for passing to mbedTLS for description
|
||||
*/
|
||||
size_t size_{32};
|
||||
|
||||
/**
|
||||
* @brief Set timeout in seconds
|
||||
*
|
||||
* This is the network timeout, so if less data than the batch size received
|
||||
* the timeout (and no EOF) we should proceed with passing the data to mbedtls
|
||||
*/
|
||||
int timeout_{2};
|
||||
|
||||
/**
|
||||
* @brief Construct a new manual ota object
|
||||
*
|
||||
* @param uri URI of the binary image
|
||||
* @brief Set common name of the server to verify
|
||||
*/
|
||||
explicit manual_ota(const char *uri): uri_(uri) {}
|
||||
const char *common_name_;
|
||||
/**
|
||||
* @brief Wrapper around the http client -- Please set the http config
|
||||
*/
|
||||
class http_client {
|
||||
friend class manual_ota;
|
||||
~http_client();
|
||||
bool init();
|
||||
esp_http_client_handle_t handle_{nullptr};
|
||||
bool handle_redirects();
|
||||
bool set_range(size_t from, size_t to);
|
||||
bool is_data_complete();
|
||||
int64_t get_image_len();
|
||||
public:
|
||||
esp_http_client_config_t config_{}; /**< Configure the http connection parameters */
|
||||
} http_;
|
||||
|
||||
/**
|
||||
* @brief Construct a new manual ota object
|
||||
*/
|
||||
explicit manual_ota() {}
|
||||
|
||||
~manual_ota();
|
||||
|
||||
/**
|
||||
* @brief Start the manual OTA process
|
||||
@ -53,11 +87,17 @@ public:
|
||||
bool end();
|
||||
|
||||
private:
|
||||
const char *uri_{};
|
||||
esp_http_client_handle_t http_;
|
||||
enum class state {
|
||||
UNDEF,
|
||||
INIT,
|
||||
IMAGE_CHECK,
|
||||
START,
|
||||
END,
|
||||
FAIL,
|
||||
};
|
||||
int64_t image_length_;
|
||||
size_t file_length_;
|
||||
const size_t max_buffer_size_{size_ * 1024};
|
||||
size_t max_buffer_size_{size_ * 1024};
|
||||
const esp_partition_t *partition_{nullptr};
|
||||
state status{state::UNDEF};
|
||||
std::vector<char> buffer_{};
|
||||
@ -65,7 +105,8 @@ private:
|
||||
const int max_reconnect_attempts_{3};
|
||||
esp_transport_handle_t ssl_;
|
||||
esp_ota_handle_t update_handle_{0};
|
||||
bool ota_begin;
|
||||
|
||||
bool prepare_reconnect();
|
||||
bool fail_cleanup();
|
||||
bool fail();
|
||||
};
|
||||
|
@ -12,7 +12,8 @@
|
||||
|
||||
class TlsTransport: public Tls {
|
||||
public:
|
||||
explicit TlsTransport(esp_transport_handle_t parent) : Tls(), transport_(parent), read_len(0), offset(0) {}
|
||||
explicit TlsTransport(esp_transport_handle_t parent):
|
||||
Tls(), transport_(parent), last_timeout(0), read_len(0), offset(0) {}
|
||||
int send(const unsigned char *buf, size_t len) override;
|
||||
int recv(unsigned char *buf, size_t len) override;
|
||||
static bool set_func(esp_transport_handle_t tls_transport);
|
||||
@ -40,11 +41,11 @@ private:
|
||||
|
||||
esp_transport_handle_t esp_transport_tls_init(esp_transport_handle_t parent)
|
||||
{
|
||||
esp_transport_handle_t ssl = esp_transport_init();
|
||||
auto *tls = new TlsTransport(parent);
|
||||
esp_transport_set_context_data(ssl, tls);
|
||||
TlsTransport::set_func(ssl);
|
||||
return ssl;
|
||||
esp_transport_handle_t transport_handle = esp_transport_init();
|
||||
auto *tls_context = new TlsTransport(parent);
|
||||
esp_transport_set_context_data(transport_handle, tls_context);
|
||||
TlsTransport::set_func(transport_handle);
|
||||
return transport_handle;
|
||||
}
|
||||
|
||||
int TlsTransport::send(const unsigned char *buf, size_t len)
|
||||
@ -105,7 +106,7 @@ void TlsTransport::delay()
|
||||
int TlsTransport::transport::connect(esp_transport_handle_t t, const char *host, int port, int timeout_ms)
|
||||
{
|
||||
auto tls = static_cast<TlsTransport *>(esp_transport_get_context_data(t));
|
||||
tls->init(is_server{false}, do_verify{false});
|
||||
tls->init(is_server{false}, do_verify{true});
|
||||
|
||||
ESP_LOGD(TAG, "TLS-connect");
|
||||
auto ret = tls->connect(host, port, timeout_ms);
|
||||
@ -122,7 +123,10 @@ int TlsTransport::transport::connect(esp_transport_handle_t t, const char *host,
|
||||
ESP_LOGI(TAG, "Failed to handshake");
|
||||
return ret;
|
||||
}
|
||||
tls->get_session();
|
||||
if (!tls->get_session()) {
|
||||
// we're not able to save session, report an error and continue (next connection will be slower)
|
||||
ESP_LOGW(TAG, "Failed to save session");
|
||||
}
|
||||
ESP_LOGI(TAG, "After handshake");
|
||||
return 0;
|
||||
}
|
||||
@ -202,6 +206,19 @@ esp_transport_handle_t esp_transport_batch_tls_init(esp_transport_handle_t paren
|
||||
return ssl;
|
||||
}
|
||||
|
||||
bool esp_transport_batch_set_ca_cert(esp_transport_handle_t t, const char *ca_cert, size_t cert_len = 0)
|
||||
{
|
||||
auto tls = static_cast<TlsTransport *>(esp_transport_get_context_data(t));
|
||||
const_buf cert((const unsigned char *)ca_cert, cert_len ? cert_len : strlen(ca_cert) + 1);
|
||||
return tls->set_ca_cert(cert);
|
||||
}
|
||||
|
||||
bool esp_transport_batch_set_cn(esp_transport_handle_t t, const char *name)
|
||||
{
|
||||
auto tls = static_cast<TlsTransport *>(esp_transport_get_context_data(t));
|
||||
return tls->set_hostname(name);
|
||||
}
|
||||
|
||||
int TlsTransport::preread(size_t len, int timeout_ms)
|
||||
{
|
||||
while (len != read_len) {
|
||||
@ -225,7 +242,7 @@ bool TlsTransport::prepare_buffer(size_t max_size)
|
||||
return true;
|
||||
}
|
||||
|
||||
int esp_transport_batch_tls_pre_read(esp_transport_handle_t t, int len, int timeout_ms)
|
||||
int esp_transport_batch_tls_pre_read(esp_transport_handle_t t, size_t len, int timeout_ms)
|
||||
{
|
||||
auto tls = static_cast<TlsTransport *>(esp_transport_get_context_data(t));
|
||||
return tls->preread(len, timeout_ms);
|
||||
|
@ -22,4 +22,22 @@ esp_transport_handle_t esp_transport_batch_tls_init(esp_transport_handle_t paren
|
||||
* @param timeout_ms Timeout in ms
|
||||
* @return true If read from the parent transport completed successfully
|
||||
*/
|
||||
bool esp_transport_batch_tls_pre_read(esp_transport_handle_t t, int len, int timeout_ms);
|
||||
bool esp_transport_batch_tls_pre_read(esp_transport_handle_t t, size_t len, int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Set the CA Certificate to verify the server
|
||||
*
|
||||
* @param ca_cert Pointer to the CA Cert data
|
||||
* @param cert_len CA Cert data len (set to 0 if null terminated string, i.e. PEM format)
|
||||
* @return true on success
|
||||
*/
|
||||
bool esp_transport_batch_set_ca_cert(esp_transport_handle_t t, const char *ca_cert, size_t cert_len);
|
||||
|
||||
/**
|
||||
* @brief Set comman name
|
||||
* @param t
|
||||
* @param ca_cert
|
||||
* @param cert_len
|
||||
* @return
|
||||
*/
|
||||
bool esp_transport_batch_set_cn(esp_transport_handle_t t, const char *name);
|
||||
|
@ -38,6 +38,19 @@ menu "Test Configuration"
|
||||
help
|
||||
HTTPS address of the update binary.
|
||||
|
||||
config TEST_OTA_CA_CERT
|
||||
string "Server certificate"
|
||||
default "---paste the server side certificate here---"
|
||||
help
|
||||
Insert the CA cert of the server side here. copy the base64 text between -----BEGIN CERTIFICATE-----
|
||||
and -----END CERTIFICATE-----.
|
||||
|
||||
config TEST_OTA_CN
|
||||
string "Server common name"
|
||||
default "192.168.11.1"
|
||||
help
|
||||
Insert the server's common name to be checked within verification of the Server side certificat
|
||||
|
||||
config BROKER_URI
|
||||
string "Broker URL"
|
||||
default "mqtt://test.mosquitto.org"
|
||||
|
@ -50,7 +50,9 @@ public:
|
||||
|
||||
void remove_mqtt()
|
||||
{
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
|
||||
esp_mqtt_client_unregister_event(mqtt, MQTT_EVENT_ANY, on_event);
|
||||
#endif
|
||||
mqtt = nullptr;
|
||||
}
|
||||
|
||||
@ -145,9 +147,17 @@ static constexpr auto OTA_FAILED = SignalGroup::bit1;
|
||||
|
||||
void ota_task(void *ctx)
|
||||
{
|
||||
static const char *ca_cert_pem = "-----BEGIN CERTIFICATE-----\n" CONFIG_TEST_OTA_CA_CERT "\n-----END CERTIFICATE-----";
|
||||
auto ota_done = static_cast<esp_modem::SignalGroup *>(ctx);
|
||||
manual_ota ota(CONFIG_TEST_OTA_URI);
|
||||
ota.size_ = 64;
|
||||
manual_ota ota;
|
||||
ota.http_.config_.url = CONFIG_TEST_OTA_URI;
|
||||
ota.http_.config_.cert_pem = ca_cert_pem;
|
||||
ota.size_ = 32;
|
||||
ota.common_name_ = CONFIG_TEST_OTA_CN;
|
||||
#ifndef CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT
|
||||
// will have to use NORMAL mode, before custom transport is supported in IDF
|
||||
ota.mode_ = manual_ota::mode::NORMAL;
|
||||
#endif
|
||||
|
||||
ota.begin();
|
||||
while (true) {
|
||||
@ -253,11 +263,13 @@ extern "C" void app_main(void)
|
||||
|
||||
|
||||
esp_modem::SignalGroup ota_done{};
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||
// now stop the LCP keepalive before performing OTA
|
||||
esp_netif_ppp_config_t cfg;
|
||||
ESP_ERROR_CHECK(esp_netif_ppp_get_params(esp_netif, &cfg));
|
||||
cfg.ppp_lcp_echo_disabled = true;
|
||||
ESP_ERROR_CHECK(esp_netif_ppp_set_params(esp_netif, &cfg));
|
||||
#endif
|
||||
|
||||
// Run the OTA in a separate task to keep sending commands to the modem at the same time
|
||||
xTaskCreate(ota_task, "ota_task", 8192, &ota_done, 5, nullptr);
|
||||
|
2
components/esp_modem/test/target_ota/sdkconfig.ci.1
Normal file
2
components/esp_modem/test/target_ota/sdkconfig.ci.1
Normal file
@ -0,0 +1,2 @@
|
||||
CONFIG_TEST_DEVICE_PPPD_SERVER=y
|
||||
CONFIG_ESP_MODEM_CMUX_DEFRAGMENT_PAYLOAD=n
|
4
components/esp_modem/test/target_ota/sdkconfig.ci.2
Normal file
4
components/esp_modem/test/target_ota/sdkconfig.ci.2
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG_TEST_DEVICE_MODEM_GENERIC=y
|
||||
CONFIG_TEST_OTA_URI="https://raw.githubusercontent.com/espressif/esp-protocols/master/components/esp_modem/test/target_ota/bin/blink.bin"
|
||||
CONFIG_TEST_OTA_CA_CERT="MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaME8xCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBSU0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6aqXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddng9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuWraKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGBAfr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21reacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBgjCCAX4wEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUt2ui6qiqhIx56rTaD5iyxZV2ufQwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDBCBgNVHR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRHbG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwCwYJYIZIAYb9bAIBMAcGBWeBDAEBMAgGBmeBDAECATAIBgZngQwBAgIwCAYGZ4EMAQIDMA0GCSqGSIb3DQEBCwUAA4IBAQCAMs5eC91uWg0Kr+HWhMvAjvqFcO3aXbMM9yt1QP6FCvrzMXi3cEsaiVi6gL3zax3pfs8LulicWdSQ0/1s/dCYbbdxglvPbQtaCdB73sRD2Cqk3p5BJl+7j5nL3a7hqG+fh/50tx8bIKuxT8b1Z11dmzzp/2n3YWzW2fP9NsarA4h20ksudYbj/NhVfSbCEXffPgK2fPOre3qGNm+499iTcc+G33Mw+nur7SpZyEKEOxEXGlLzyQ4UfaJbcme6ce1XR2bFuAJKZTRei9AqPCCcUZlM51Ke92sRKw2Sfh3oius2FkOH6ipjv3U/697EA7sKPPcw7+uvTPyLNhBzPvOk"
|
||||
CONFIG_TEST_OTA_CN="github.com"
|
4
components/esp_modem/test/target_ota/sdkconfig.ci.3
Normal file
4
components/esp_modem/test/target_ota/sdkconfig.ci.3
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG_TEST_DEVICE_PPPD_SERVER=y
|
||||
CONFIG_ESP_MODEM_CMUX_DEFRAGMENT_PAYLOAD=y
|
||||
CONFIG_ESP_MODEM_USE_INFLATABLE_BUFFER_IF_NEEDED=y
|
||||
CONFIG_TEST_USE_VFS_TERM=y
|
12
components/esp_modem/test/target_ota/sdkconfig.defaults
Normal file
12
components/esp_modem/test/target_ota/sdkconfig.defaults
Normal file
@ -0,0 +1,12 @@
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_PARTITION_TABLE_TWO_OTA=y
|
||||
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
||||
# This is not supported in IDF yet
|
||||
# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT=y
|
||||
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||
CONFIG_LWIP_PPP_SUPPORT=y
|
||||
CONFIG_LWIP_PPP_ENABLE_IPV6=n
|
||||
CONFIG_LWIP_ENABLE_LCP_ECHO=y
|
||||
CONFIG_LWIP_LCP_ECHOINTERVAL=1
|
||||
CONFIG_LWIP_LCP_MAXECHOFAILS=2
|
Reference in New Issue
Block a user