mirror of
https://github.com/hinto-janai/gupax.git
synced 2024-12-23 03:19:21 +00:00
update: dynamically return [Tor+TLS|TLS-only] HTTP client at runtime
This commit is contained in:
parent
bf81b2c57c
commit
42373a37fe
2 changed files with 88 additions and 77 deletions
16
src/main.rs
16
src/main.rs
|
@ -70,7 +70,7 @@ pub struct App {
|
|||
// State
|
||||
og: State, // og = Old state to compare against
|
||||
state: State, // state = Working state (current settings)
|
||||
update: Update, // State for update data [update.rs]
|
||||
// update: Update, // State for update data [update.rs]
|
||||
diff: bool, // Instead of comparing [og == state] every frame, this bool indicates changes
|
||||
// Process/update state:
|
||||
// Doesn't make sense to save this on disk
|
||||
|
@ -114,7 +114,7 @@ impl App {
|
|||
node: Arc::new(Mutex::new(NodeStruct::default())),
|
||||
og: State::default(),
|
||||
state: State::default(),
|
||||
update: Update::new(&throwaway.gupax.absolute_p2pool_path, &throwaway.gupax.absolute_xmrig_path, true),
|
||||
// update: Update::new(&throwaway.gupax.absolute_p2pool_path, &throwaway.gupax.absolute_xmrig_path, true),
|
||||
diff: false,
|
||||
p2pool: false,
|
||||
xmrig: false,
|
||||
|
@ -147,7 +147,7 @@ impl App {
|
|||
app.og.xmrig.max_threads = num_cpus::get();
|
||||
if app.og.xmrig.current_threads > app.og.xmrig.max_threads { app.og.xmrig.current_threads = app.og.xmrig.max_threads; }
|
||||
app.state = app.og.clone();
|
||||
app.update = Update::new(&app.og.gupax.absolute_p2pool_path, &app.og.gupax.absolute_xmrig_path, app.og.gupax.update_via_tor);
|
||||
// app.update = Update::new(&app.og.gupax.absolute_p2pool_path, &app.og.gupax.absolute_xmrig_path, app.og.gupax.update_via_tor);
|
||||
app
|
||||
}
|
||||
}
|
||||
|
@ -372,8 +372,14 @@ impl eframe::App for App {
|
|||
// *-------*
|
||||
// | DEBUG |
|
||||
// *-------*
|
||||
self.update.start();
|
||||
thread::sleep;
|
||||
let p2pool = self.og.gupax.absolute_p2pool_path.clone();
|
||||
let xmrig = self.og.gupax.absolute_xmrig_path.clone();
|
||||
let tor = self.og.gupax.update_via_tor.clone();
|
||||
thread::spawn(move|| {
|
||||
info!("Spawning update thread...");
|
||||
let update = Update::start(&mut Update::new(p2pool, xmrig, tor));
|
||||
});
|
||||
thread::park();
|
||||
// This sets the top level Ui dimensions.
|
||||
// Used as a reference for other uis.
|
||||
egui::CentralPanel::default().show(ctx, |ui| { self.width = ui.available_width(); self.height = ui.available_height(); });
|
||||
|
|
149
src/update.rs
149
src/update.rs
|
@ -14,6 +14,15 @@
|
|||
//// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
// This file contains all (most) of the code for updating.
|
||||
// The main [Update] struct contains meta update information.
|
||||
// It is held by the top [App] struct. Each package also gets
|
||||
// a [Pkg] struct that only lasts as long as the download.
|
||||
//
|
||||
// An update is triggered by either:
|
||||
// a. user clicks update on [Gupax] tab
|
||||
// b. auto-update at startup
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Imports
|
||||
use serde_derive::{Serialize,Deserialize};
|
||||
use tokio::task::JoinHandle;
|
||||
|
@ -146,7 +155,7 @@ const FAKE_USER_AGENT: [&'static str; 50] = [
|
|||
"curl/7.85.0",
|
||||
];
|
||||
|
||||
const MSG_START: &'static str = "Starting update...";
|
||||
const MSG_START: &'static str = "Starting update";
|
||||
const MSG_TMP: &'static str = "Creating temporary directory";
|
||||
const MSG_PKG: &'static str = "Creating package list";
|
||||
const MSG_TOR: &'static str = "Creating Tor+HTTPS client";
|
||||
|
@ -164,8 +173,8 @@ const MSG_ARCHIVE: &'static str = "Downloading packages";
|
|||
// Progress bar structure:
|
||||
// 5% | Create tmp directory
|
||||
// 5% | Create package list
|
||||
// 10% | Create Tor/HTTPS client
|
||||
// 20% | Download Metadata (x3)
|
||||
// 15% | Create Tor/HTTPS client
|
||||
// 15% | Download Metadata (x3)
|
||||
// 30% | Download Archive (x3)
|
||||
// 15% | Extract (x3)
|
||||
// 15% | Upgrade (x3)
|
||||
|
@ -183,7 +192,7 @@ pub struct Update {
|
|||
|
||||
impl Update {
|
||||
// Takes in current paths from [State]
|
||||
pub fn new(path_p2pool: &PathBuf, path_xmrig: &PathBuf, tor: bool) -> Self {
|
||||
pub fn new(path_p2pool: PathBuf, path_xmrig: PathBuf, tor: bool) -> Self {
|
||||
Self {
|
||||
path_gupax: crate::get_exe().unwrap(),
|
||||
path_p2pool: path_p2pool.display().to_string(),
|
||||
|
@ -207,32 +216,35 @@ impl Update {
|
|||
.collect();
|
||||
let tmp = std::env::temp_dir();
|
||||
let tmp = format!("{}{}{}{}", tmp.display(), "/gupax_", rand_string, "/");
|
||||
info!("Update | TMP directory ... {}", tmp);
|
||||
tmp
|
||||
}
|
||||
|
||||
// The HTTPS client created when Tor is enabled:
|
||||
// TLS implementation | tls-api -> native-tls
|
||||
// Tor implementatoin | arti
|
||||
pub async fn get_tor_client() -> Result<ClientEnum, anyhow::Error> {
|
||||
info!("Update | Creating Tor+HTTPS client...");
|
||||
let tor = TorClient::create_bootstrapped(TorClientConfig::default()).await?;
|
||||
let tls = tls_api_native_tls::TlsConnector::builder()?.build()?;
|
||||
let http = ArtiHttpConnector::new(tor, tls);
|
||||
let client = ClientEnum::Tor(Client::builder().build(http));
|
||||
info!("Update | Tor client ... OK");
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
// The HTTPS client created when Tor is disabled:
|
||||
// TLS implementation | hyper-tls
|
||||
pub async fn get_client() -> Result<ClientEnum, anyhow::Error> {
|
||||
info!("Update | Creating HTTPS client...");
|
||||
let mut https = hyper_tls::HttpsConnector::new();
|
||||
https.https_only(true);
|
||||
let client = ClientEnum::Https(Client::builder().build(https));
|
||||
info!("Update | HTTPS client ... OK");
|
||||
Ok(client)
|
||||
// Get a HTTPS client. Uses [Arti] if Tor is enabled.
|
||||
// The base type looks something like [hyper::Client<...>].
|
||||
// This is then wrapped with the custom [ClientEnum] type to implement
|
||||
// returning either a [Tor+TLS|TLS-only] client AT RUNTIME BASED ON USER SETTINGS
|
||||
// tor == true? => return Tor client
|
||||
// tor == false? => return normal TLS client
|
||||
//
|
||||
// Since functions that take generic INPUT are much easier to implement,
|
||||
// [get_response()] just takes a [hyper::Client<C>], which is passed to
|
||||
// it via deconstructing this [ClientEnum] with a match, like so:
|
||||
// ClientEnum::Tor(T) => get_reponse(... T ...)
|
||||
// ClientEnum::Https(H) => get_reponse(... H ...)
|
||||
//
|
||||
pub async fn get_client(tor: bool) -> Result<ClientEnum, anyhow::Error> {
|
||||
if tor {
|
||||
let tor = TorClient::create_bootstrapped(TorClientConfig::default()).await?;
|
||||
let tls = tls_api_native_tls::TlsConnector::builder()?.build()?;
|
||||
let connector = ArtiHttpConnector::new(tor, tls);
|
||||
let client = ClientEnum::Tor(Client::builder().build(connector));
|
||||
return Ok(client)
|
||||
} else {
|
||||
let mut connector = hyper_tls::HttpsConnector::new();
|
||||
connector.https_only(true);
|
||||
let client = ClientEnum::Https(Client::builder().build(connector));
|
||||
return Ok(client)
|
||||
}
|
||||
}
|
||||
|
||||
// Download process:
|
||||
|
@ -248,57 +260,58 @@ impl Update {
|
|||
// Set progress bar
|
||||
*self.msg.lock().unwrap() = MSG_START.to_string();
|
||||
*self.prog.lock().unwrap() = 0;
|
||||
info!("Update | Init | {}...", *self.msg.lock().unwrap());
|
||||
|
||||
// Get temporary directory
|
||||
*self.msg.lock().unwrap() = MSG_TMP.to_string();
|
||||
info!("Update | Init | {} ... {}%", *self.msg.lock().unwrap(), *self.prog.lock().unwrap());
|
||||
let tmp_dir = Self::get_tmp_dir();
|
||||
*self.prog.lock().unwrap() = 5;
|
||||
*self.prog.lock().unwrap() += 5;
|
||||
|
||||
// Make Pkg vector
|
||||
*self.msg.lock().unwrap() = MSG_PKG.to_string();
|
||||
info!("Update | Init | {} ... {}%", *self.msg.lock().unwrap(), *self.prog.lock().unwrap());
|
||||
let vec = vec![
|
||||
Pkg::new(Gupax, &tmp_dir, self.prog.clone(), self.msg.clone()),
|
||||
Pkg::new(P2pool, &tmp_dir, self.prog.clone(), self.msg.clone()),
|
||||
Pkg::new(Xmrig, &tmp_dir, self.prog.clone(), self.msg.clone()),
|
||||
];
|
||||
let mut handles: Vec<JoinHandle<()>> = vec![];
|
||||
*self.prog.lock().unwrap() = 5;
|
||||
*self.prog.lock().unwrap() += 5;
|
||||
|
||||
// Create Tor/HTTPS client
|
||||
let mut client: ClientEnum;
|
||||
if self.tor {
|
||||
*self.msg.lock().unwrap() = MSG_TOR.to_string();
|
||||
client = Self::get_tor_client().await?;
|
||||
} else {
|
||||
*self.msg.lock().unwrap() = MSG_HTTPS.to_string();
|
||||
client = Self::get_client().await?;
|
||||
}
|
||||
*self.prog.lock().unwrap() = 10;
|
||||
if self.tor { *self.msg.lock().unwrap() = MSG_TOR.to_string() } else { *self.msg.lock().unwrap() = MSG_HTTPS.to_string() }
|
||||
info!("Update | Init | {} ... {}%", *self.msg.lock().unwrap(), *self.prog.lock().unwrap());
|
||||
let client = Self::get_client(self.tor).await?;
|
||||
*self.prog.lock().unwrap() += 10;
|
||||
|
||||
// loop for metadata
|
||||
// Loop for metadata
|
||||
info!("Update | Metadata | Starting metadata fetch...");
|
||||
for pkg in vec.iter() {
|
||||
info!("Update | Metadata | Starting ... {}", pkg.name);
|
||||
// Clone data before sending to async
|
||||
let name = pkg.name.clone();
|
||||
let version = Arc::clone(&pkg.version);
|
||||
let request = hyper::Request::builder()
|
||||
.method("GET")
|
||||
.uri(pkg.link_metadata)
|
||||
.header(hyper::header::USER_AGENT, hyper::header::HeaderValue::from_static("Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"))
|
||||
.body(Body::empty())?;
|
||||
let prog = Arc::clone(&pkg.prog);
|
||||
let client = client.clone();
|
||||
let request = Pkg::get_request(pkg.link_metadata.to_string())?;
|
||||
// Send to async
|
||||
let handle: JoinHandle<()> = tokio::spawn(async move {
|
||||
Pkg::get_tor_response(name, version, client, request).await;
|
||||
match client {
|
||||
ClientEnum::Tor(t) => Pkg::get_response(name, version, prog, t, request).await,
|
||||
ClientEnum::Https(h) => Pkg::get_response(name, version, prog, h, request).await,
|
||||
};
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
// Unwrap async
|
||||
for handle in handles {
|
||||
handle.await?;
|
||||
}
|
||||
info!("Update | Metadata ... OK\n");
|
||||
info!("Update | Metadata ... OK");
|
||||
Ok(())
|
||||
|
||||
//----------------------------------------------
|
||||
//
|
||||
//
|
||||
// // loop for download
|
||||
// let mut handles: Vec<JoinHandle<()>> = vec![];
|
||||
// for pkg in vec.iter() {
|
||||
|
@ -358,10 +371,10 @@ impl Update {
|
|||
}
|
||||
}
|
||||
|
||||
// Wrapper type around Tor/HTTPS client
|
||||
#[derive(Debug,Clone)]
|
||||
enum ClientEnum {
|
||||
Tor(Client<ArtiHttpConnector<tor_rtcompat::PreferredRuntime, tls_api_native_tls::TlsConnector>>),
|
||||
Https(Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>),
|
||||
Tor(Client<ArtiHttpConnector<tor_rtcompat::PreferredRuntime, tls_api_native_tls::TlsConnector>>),
|
||||
Https(Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>),
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Pkg struct/impl
|
||||
|
@ -373,14 +386,14 @@ pub struct Pkg {
|
|||
link_suffix: &'static str,
|
||||
link_extension: &'static str,
|
||||
tmp_dir: String,
|
||||
update_prog: Arc<Mutex<u8>>,
|
||||
update_msg: Arc<Mutex<String>>,
|
||||
prog: Arc<Mutex<u8>>,
|
||||
msg: Arc<Mutex<String>>,
|
||||
bytes: Arc<Mutex<bytes::Bytes>>,
|
||||
version: Arc<Mutex<String>>,
|
||||
}
|
||||
|
||||
impl Pkg {
|
||||
pub fn new(name: Name, tmp_dir: &String, update_prog: Arc<Mutex<u8>>, update_msg: Arc<Mutex<String>>) -> Self {
|
||||
pub fn new(name: Name, tmp_dir: &String, prog: Arc<Mutex<u8>>, msg: Arc<Mutex<String>>) -> Self {
|
||||
let link_metadata = match name {
|
||||
Gupax => GUPAX_METADATA,
|
||||
P2pool => P2POOL_METADATA,
|
||||
|
@ -408,42 +421,34 @@ impl Pkg {
|
|||
link_suffix,
|
||||
link_extension,
|
||||
tmp_dir: tmp_dir.to_string(),
|
||||
update_prog,
|
||||
update_msg,
|
||||
prog,
|
||||
msg,
|
||||
bytes: Arc::new(Mutex::new(bytes::Bytes::new())),
|
||||
version: Arc::new(Mutex::new(String::new())),
|
||||
}
|
||||
}
|
||||
|
||||
// Generate GET request based off input URI + fake user agent
|
||||
pub async fn get_request(self) -> Result<Request<Body>, anyhow::Error> {
|
||||
pub fn get_request(link: String) -> Result<Request<Body>, anyhow::Error> {
|
||||
let user_agent = FAKE_USER_AGENT[thread_rng().gen_range(0..50)];
|
||||
let request = Request::builder()
|
||||
.method("GET")
|
||||
.uri(self.link_metadata)
|
||||
.uri(link)
|
||||
.header(hyper::header::USER_AGENT, HeaderValue::from_static(user_agent))
|
||||
.body(Body::empty())?;
|
||||
Ok(request)
|
||||
}
|
||||
|
||||
// Get response using [Tor client] + [request]
|
||||
// and change the [version] under an Arc<Mutex>
|
||||
pub async fn get_tor_response(name: Name, version: Arc<Mutex<String>>, client: Client<ArtiHttpConnector<tor_rtcompat::PreferredRuntime, tls_api_native_tls::TlsConnector>>, request: Request<Body>) -> Result<(), Error> {
|
||||
// Get response using [Generic hyper::client<C>] & [Request]
|
||||
// and change [version, prog] under an Arc<Mutex>
|
||||
pub async fn get_response<C>(name: Name, version: Arc<Mutex<String>>, prog: Arc<Mutex<u8>>, client: Client<C>, request: Request<Body>) -> Result<(), Error>
|
||||
where C: hyper::client::connect::Connect + Clone + Send + Sync + 'static, {
|
||||
let mut response = client.request(request).await?;
|
||||
let body = hyper::body::to_bytes(response.body_mut()).await?;
|
||||
let body: Version = serde_json::from_slice(&body)?;
|
||||
*version.lock().unwrap() = body.tag_name.clone();
|
||||
info!("Update | Metadata | {} {} ... OK", name, body.tag_name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Same thing, but without Tor.
|
||||
pub async fn get_response(name: Name, version: Arc<Mutex<String>>, client: Client<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>, request: Request<Body>) -> Result<(), Error> {
|
||||
let mut response = client.request(request).await?;
|
||||
let body = hyper::body::to_bytes(response.body_mut()).await?;
|
||||
let body: Version = serde_json::from_slice(&body)?;
|
||||
*version.lock().unwrap() = body.tag_name.clone();
|
||||
info!("Update | Metadata | {} {} ... OK", name, body.tag_name);
|
||||
*prog.lock().unwrap() += 5;
|
||||
info!("Update | Metadata | {} {} ... {}%", name, body.tag_name, *prog.lock().unwrap());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue