From 7d398557512548d74a415c0eae8d7e36ef1d2b56 Mon Sep 17 00:00:00 2001 From: decentclock Date: Wed, 28 Sep 2022 13:47:54 -0400 Subject: [PATCH] ota: dispatch update download to its own thread --- sphinx-key/sdkconfig.defaults | 3 +- sphinx-key/src/core/events.rs | 22 +++++++++------ sphinx-key/src/ota.rs | 53 ++++++++++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/sphinx-key/sdkconfig.defaults b/sphinx-key/sdkconfig.defaults index f73fb9e..b97b1c6 100644 --- a/sphinx-key/sdkconfig.defaults +++ b/sphinx-key/sdkconfig.defaults @@ -1,6 +1,7 @@ # Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) CONFIG_ESP_MAIN_TASK_STACK_SIZE=64000 -#CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=10000 +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y # Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). # This allows to use 1 ms granuality for thread sleeps (10 ms by default). diff --git a/sphinx-key/src/core/events.rs b/sphinx-key/src/core/events.rs index b0bab0a..d5e1e8c 100644 --- a/sphinx-key/src/core/events.rs +++ b/sphinx-key/src/core/events.rs @@ -1,11 +1,12 @@ use crate::conn::mqtt::QOS; -use crate::ota::update_sphinx_key; +use crate::ota::{update_sphinx_key, validate_ota_message}; use sphinx_key_signer::control::{Config, ControlMessage, ControlResponse, Controller, Policy}; use sphinx_key_signer::lightning_signer::bitcoin::Network; use sphinx_key_signer::vls_protocol::model::PubKey; use sphinx_key_signer::{self, make_init_msg, topics, InitResponse, ParserError, RootHandler}; use std::sync::mpsc; +use std::thread; use embedded_svc::httpd::Result; use embedded_svc::mqtt::client::utils::ConnState; @@ -120,9 +121,6 @@ pub fn make_event_loop( rmp_serde::to_vec(&res).expect("could not publish control response"); mqtt.publish(topics::CONTROL_RETURN, QOS, false, &res_data) .expect("could not publish control response"); - if let ControlResponse::OtaConfirm(_) = res { - unsafe { esp_idf_sys::esp_restart() }; - } } } } @@ -167,12 +165,20 @@ fn handle_control_response( } } ControlMessage::Ota(params) => { - if let Err(e) = update_sphinx_key(params.version, params.url.clone()) { - log::error!("OTA update failed {:?}", e.to_string()); + if let Err(e) = validate_ota_message(params.clone()) { + log::error!("OTA update cannot launch {:?}", e.to_string()); control_res = - ControlResponse::Error(format!("OTA update failed {:?}", e)) + ControlResponse::Error(format!("OTA update cannot launch {:?}", e)) } else { - log::info!("OTA update completed, about to restart the glyph..."); + thread::spawn(move || { + if let Err(e) = update_sphinx_key(params) { + log::error!("OTA update failed {:?}", e.to_string()); + } else { + log::info!("OTA flow complete, restarting esp..."); + unsafe { esp_idf_sys::esp_restart() }; + } + }); + log::info!("OTA update launched..."); } } _ => (), diff --git a/sphinx-key/src/ota.rs b/sphinx-key/src/ota.rs index 9069e32..afab4a5 100644 --- a/sphinx-key/src/ota.rs +++ b/sphinx-key/src/ota.rs @@ -2,6 +2,7 @@ use anyhow::{anyhow, Result}; use embedded_svc::http::client::Client; use embedded_svc::http::client::Request; use embedded_svc::http::client::Response; +use embedded_svc::http::Status; use embedded_svc::io::Read; use embedded_svc::ota::Ota; use esp_idf_svc::http::client::EspHttpClient; @@ -9,6 +10,7 @@ use esp_idf_svc::http::client::EspHttpClientConfiguration; use esp_idf_svc::http::client::FollowRedirectsPolicy::FollowNone; use esp_idf_svc::ota::EspOta; use log::{error, info}; +use sphinx_key_signer::control::OtaParams; use std::fs::{remove_file, File}; use std::io::BufWriter; use std::io::Write; @@ -29,7 +31,7 @@ fn factory_reset() -> Result<()> { } } -fn get_update(version: u64, mut url: String) -> Result<()> { +fn get_update(params: OtaParams) -> Result<()> { let configuration = EspHttpClientConfiguration { buffer_size: Some(BUFFER_LEN), buffer_size_tx: Some(BUFFER_LEN / 3), @@ -38,8 +40,8 @@ fn get_update(version: u64, mut url: String) -> Result<()> { crt_bundle_attach: None, }; let mut client = EspHttpClient::new(&configuration)?; - url.push_str(&version.to_string()); - let mut response = client.get(&url)?.submit()?; + let full_url = params_to_url(params); + let mut response = client.get(&full_url)?.submit()?; let mut reader = response.reader(); let _ = remove_file(UPDATE_BIN_PATH); @@ -69,13 +71,50 @@ fn get_update(version: u64, mut url: String) -> Result<()> { Ok(()) } -pub fn update_sphinx_key(version: u64, url: String) -> Result<()> { +pub fn update_sphinx_key(params: OtaParams) -> Result<()> { info!("Getting the update..."); - info!("Version: {}", version.to_string()); - info!("URL: {}", url); - get_update(version, url)?; + get_update(params)?; info!("Update written to sd card, performing factory reset"); factory_reset()?; info!("Factory reset completed!"); Ok(()) } + +pub fn validate_ota_message(params: OtaParams) -> Result<()> { + let configuration = EspHttpClientConfiguration { + buffer_size: Some(BUFFER_LEN / 3), + buffer_size_tx: Some(BUFFER_LEN / 3), + follow_redirects_policy: FollowNone, + use_global_ca_store: true, + crt_bundle_attach: None, + }; + let mut client = EspHttpClient::new(&configuration)?; + let full_url = params_to_url(params); + info!("Pinging this url for an update: {}", full_url); + let response = client.get(&full_url)?.submit()?; + let status = response.status(); + if status == 200 { + info!("Got valid OTA url! Proceeding with OTA update..."); + Ok(()) + } else if status == 404 { + error!("got 404, update not found on server, make sure the url and version are correct"); + Err(anyhow!( + "got 404, update not found on server, make sure the url and version are correct" + )) + } else { + error!( + "got {} code when fetching update, something is wrong", + &status.to_string() + ); + Err(anyhow!( + "got {} code when fetching update, something is wrong", + &status.to_string() + )) + } +} + +fn params_to_url(params: OtaParams) -> String { + let mut url = params.url.clone(); + url.push_str(¶ms.version.to_string()); + url +}