mirror of
https://github.com/creating2morrow/neveko.git
synced 2024-12-22 11:39:22 +00:00
use i2p-zero and remove i2pd dependencies
This commit is contained in:
parent
6832696365
commit
bf147355e6
6 changed files with 63 additions and 130 deletions
|
@ -37,7 +37,7 @@ pub struct Args {
|
|||
#[arg(
|
||||
long,
|
||||
help = "Absolute path to i2p-zero directroy",
|
||||
default_value = "/home/user/i2p-zero-linux.v1.20"
|
||||
default_value = "/home/user/i2p-zero-linux.v1.21"
|
||||
)]
|
||||
pub i2p_zero_dir: String,
|
||||
/// Monero RPC daemon host
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::{
|
|||
use clap::Parser;
|
||||
use log::{
|
||||
debug,
|
||||
error,
|
||||
info,
|
||||
warn,
|
||||
};
|
||||
|
@ -20,29 +19,12 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
// TODO(c2m): debug i2p-zero http proxy
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum I2pStatus {
|
||||
Accept,
|
||||
Reject,
|
||||
}
|
||||
|
||||
impl I2pStatus {
|
||||
pub fn value(&self) -> String {
|
||||
match *self {
|
||||
I2pStatus::Accept => String::from("Accepting tunnels"),
|
||||
I2pStatus::Reject => String::from("Rejecting tunnels: Starting up"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct HttpProxyStatus {
|
||||
pub open: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Serialize, PartialEq)]
|
||||
pub enum ProxyStatus {
|
||||
Opening,
|
||||
Open,
|
||||
|
@ -86,27 +68,32 @@ async fn find_tunnels() {
|
|||
let contents = fs::read_to_string(file_path).unwrap_or(utils::empty_string());
|
||||
debug!("i2p tunnels: {}", contents);
|
||||
let has_app_tunnel = contents.contains(&format!("{}", app_port));
|
||||
// let has_http_tunnel = contents.contains("4444");
|
||||
if !has_app_tunnel {
|
||||
let proxy_port = get_i2p_proxy_port();
|
||||
let has_http_tunnel = contents.contains(&proxy_port);
|
||||
if !has_app_tunnel || !has_http_tunnel {
|
||||
tokio::time::sleep(Duration::new(120, 0)).await;
|
||||
}
|
||||
if !has_app_tunnel {
|
||||
debug!("creating app tunnel");
|
||||
create_tunnel();
|
||||
}
|
||||
// TODO(c2m): why is i2p-zero http proxy always giving "destination not
|
||||
// found" error? if !has_http_tunnel { create_http_proxy(); }
|
||||
if !has_http_tunnel {
|
||||
debug!("creating http tunnel");
|
||||
create_http_proxy();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn start() {
|
||||
info!("starting i2p-zero");
|
||||
let args = args::Args::parse();
|
||||
let path = args.i2p_zero_dir;
|
||||
let output = Command::new(format!("{}/router/bin/i2p-zero", path))
|
||||
.spawn();
|
||||
let output = Command::new(format!("{}/router/bin/i2p-zero", path)).spawn();
|
||||
match output {
|
||||
Ok(child) => debug!("{:?}", child.stdout),
|
||||
_=> {
|
||||
_ => {
|
||||
warn!("i2p-zero not installed, manual tunnel creation required");
|
||||
()
|
||||
},
|
||||
}
|
||||
}
|
||||
find_tunnels().await;
|
||||
{
|
||||
|
@ -135,16 +122,26 @@ fn create_tunnel() {
|
|||
debug!("{:?}", output.stdout);
|
||||
}
|
||||
|
||||
// TODO(c2m): use i2p-zero http proxy
|
||||
// fn create_http_proxy() {
|
||||
// info!("creating http proxy");
|
||||
// let output =
|
||||
// Command::new("./i2p-zero-linux.v1.20/router/bin/tunnel-control.sh")
|
||||
// .args(["http.create", "4444"])
|
||||
// .spawn()
|
||||
// .expect("i2p-zero failed to create a http proxy");
|
||||
// debug!("{:?}", output.stdout);
|
||||
// }
|
||||
/// Extract i2p port from command line arg
|
||||
fn get_i2p_proxy_port() -> String {
|
||||
let proxy_host = utils::get_i2p_http_proxy();
|
||||
let values = proxy_host.split(":");
|
||||
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
|
||||
let port = v.remove(2);
|
||||
port
|
||||
}
|
||||
/// Create the http proxy if it doesn't exist
|
||||
fn create_http_proxy() {
|
||||
let args = args::Args::parse();
|
||||
let path = args.i2p_zero_dir;
|
||||
info!("creating http proxy");
|
||||
let port = get_i2p_proxy_port();
|
||||
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
|
||||
.args(["http.create", &port])
|
||||
.spawn()
|
||||
.expect("i2p-zero failed to create a http proxy");
|
||||
debug!("{:?}", output.stdout);
|
||||
}
|
||||
|
||||
pub fn get_destination() -> String {
|
||||
let file_path = format!(
|
||||
|
@ -171,45 +168,18 @@ pub fn get_destination() -> String {
|
|||
utils::empty_string()
|
||||
}
|
||||
|
||||
pub async fn check_connection() -> HttpProxyStatus {
|
||||
let client: reqwest::Client = reqwest::Client::new();
|
||||
let host: &str = "http://localhost:7657/tunnels";
|
||||
match client.get(host).send().await {
|
||||
Ok(response) => {
|
||||
// do some parsing here to check the status
|
||||
let res = response.text().await;
|
||||
match res {
|
||||
Ok(res) => {
|
||||
// split the html from the local i2p tunnels page
|
||||
let split1 = res.split("<h4><span class=\"tunnelBuildStatus\">");
|
||||
let mut v1: Vec<String> = split1.map(|s| String::from(s)).collect();
|
||||
let s1 = v1.remove(1);
|
||||
let v2 = s1.split("</span></h4>");
|
||||
let mut split2: Vec<String> = v2.map(|s| String::from(s)).collect();
|
||||
let status: String = split2.remove(0);
|
||||
if status == I2pStatus::Accept.value() {
|
||||
info!("i2p is currently accepting tunnels");
|
||||
return HttpProxyStatus { open: true };
|
||||
} else if status == I2pStatus::Reject.value() {
|
||||
info!("i2p is currently rejecting tunnels");
|
||||
return HttpProxyStatus { open: false };
|
||||
} else {
|
||||
info!("i2p is unstable");
|
||||
return HttpProxyStatus { open: true };
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("i2p status check failure");
|
||||
return HttpProxyStatus { open: false };
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("i2p-zero http proxy is degraded");
|
||||
warn!("please install i2pd from geti2p.org");
|
||||
warn!("start i2p with /path-to-i2p/i2prouter start");
|
||||
error!("{}", e.to_string());
|
||||
return HttpProxyStatus { open: false };
|
||||
}
|
||||
pub async fn check_connection() -> ProxyStatus {
|
||||
let args = args::Args::parse();
|
||||
let path = args.i2p_zero_dir;
|
||||
let port = get_i2p_proxy_port();
|
||||
let output = Command::new(format!("{}/router/bin/tunnel-control.sh", path))
|
||||
.args(["http.state", &port])
|
||||
.output()
|
||||
.expect("check i2p connection failed");
|
||||
let str_status = String::from_utf8(output.stdout).unwrap();
|
||||
if str_status == ProxyStatus::Open.value() {
|
||||
ProxyStatus::Open
|
||||
} else {
|
||||
ProxyStatus::Opening
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ pub const MONERO_RELEASE_VERSION: &str = "monero-linux-x64-v0.18.2.2.tar.bz2";
|
|||
pub const MONERO_RELEASE_HASH: &str =
|
||||
"186800de18f67cca8475ce392168aabeb5709a8f8058b0f7919d7c693786d56b";
|
||||
/// The latest i2p-zero release version
|
||||
pub const I2P_ZERO_RELEASE_VERSION: &str = "v1.20";
|
||||
pub const I2P_ZERO_RELEASE_VERSION: &str = "v1.21";
|
||||
pub const I2P_ZERO_RELEASH_HASH: &str =
|
||||
"7e7216b281624ec464b55217284017576d109eaba7b35f7e4994ae2a78634de7";
|
||||
"14f34052ad6abb0c24b048816b0ea86b696ae350dd139dd1e90a67ca88e1d07a";
|
||||
/// The latest i2pd release version
|
||||
pub const I2P_RELEASE_VERSION: &str = "2.2.1";
|
||||
pub const I2P_RELEASE_HASH: &str =
|
||||
|
|
|
@ -23,7 +23,6 @@ use std::time::Duration;
|
|||
/// Enum for selecting hash validation
|
||||
#[derive(PartialEq)]
|
||||
enum ExternalSoftware {
|
||||
I2P,
|
||||
I2PZero,
|
||||
XMR,
|
||||
}
|
||||
|
@ -31,7 +30,6 @@ enum ExternalSoftware {
|
|||
/// Handles the state for the installation manager popup
|
||||
pub struct Installations {
|
||||
pub xmr: bool,
|
||||
pub i2p: bool,
|
||||
pub i2p_zero: bool,
|
||||
}
|
||||
|
||||
|
@ -39,7 +37,6 @@ impl Default for Installations {
|
|||
fn default() -> Self {
|
||||
Installations {
|
||||
xmr: false,
|
||||
i2p: false,
|
||||
i2p_zero: false,
|
||||
}
|
||||
}
|
||||
|
@ -485,41 +482,14 @@ pub fn stage_cleanup(f: String) {
|
|||
///
|
||||
/// clearnet. TODO(c2m): trusted download locations over i2p.
|
||||
pub async fn install_software(installations: Installations) -> bool {
|
||||
let mut valid_i2p_hash = true;
|
||||
let mut valid_i2p_zero_hash = true;
|
||||
let mut valid_xmr_hash = true;
|
||||
if installations.i2p {
|
||||
info!("installing i2p");
|
||||
let i2p_version = crate::I2P_RELEASE_VERSION;
|
||||
let i2p_jar = format!("i2pinstall_{}.jar", i2p_version);
|
||||
let link = format!(
|
||||
"https://download.i2p2.no/releases/{}/{}",
|
||||
i2p_version, i2p_jar
|
||||
);
|
||||
let curl = std::process::Command::new("curl")
|
||||
.args(["-O#", &link])
|
||||
.status();
|
||||
match curl {
|
||||
Ok(curl_output) => {
|
||||
debug!("{:?}", curl_output);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
let jar_output = std::process::Command::new("java")
|
||||
.args(["-jar", &i2p_jar])
|
||||
.spawn()
|
||||
.expect("i2p gui installation failed");
|
||||
debug!("{:?}", jar_output.stdout);
|
||||
}
|
||||
_ => error!("i2p download failed"),
|
||||
}
|
||||
valid_i2p_hash = validate_installation_hash(ExternalSoftware::I2P, &i2p_jar);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
}
|
||||
if installations.i2p_zero {
|
||||
info!("installing i2p-zero");
|
||||
let i2p_version = crate::I2P_ZERO_RELEASE_VERSION;
|
||||
let i2p_zero_zip = format!("i2p-zero-linux.{}.zip", i2p_version);
|
||||
let link = format!(
|
||||
"https://github.com/i2p-zero/i2p-zero/releases/download/{}/{}",
|
||||
"https://github.com/creating2morrow/i2p-zero/releases/download/{}/{}",
|
||||
i2p_version, i2p_zero_zip
|
||||
);
|
||||
let curl = std::process::Command::new("curl")
|
||||
|
@ -567,15 +537,13 @@ pub async fn install_software(installations: Installations) -> bool {
|
|||
);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
}
|
||||
valid_i2p_hash && valid_i2p_zero_hash && valid_xmr_hash
|
||||
valid_i2p_zero_hash && valid_xmr_hash
|
||||
}
|
||||
|
||||
/// Linux specific hash validation using the command `sha256sum`
|
||||
fn validate_installation_hash(sw: ExternalSoftware, filename: &String) -> bool {
|
||||
debug!("validating hash");
|
||||
let expected_hash = if sw == ExternalSoftware::I2P {
|
||||
String::from(crate::I2P_RELEASE_HASH)
|
||||
} else if sw == ExternalSoftware::I2PZero {
|
||||
let expected_hash = if sw == ExternalSoftware::I2PZero {
|
||||
String::from(crate::I2P_ZERO_RELEASH_HASH)
|
||||
} else {
|
||||
String::from(crate::MONERO_RELEASE_HASH)
|
||||
|
|
|
@ -27,8 +27,8 @@ pub struct HomeApp {
|
|||
is_timeout: bool,
|
||||
is_updated: bool,
|
||||
// Sender/Receiver for async notifications.
|
||||
i2p_status_tx: Sender<i2p::HttpProxyStatus>,
|
||||
i2p_status_rx: Receiver<i2p::HttpProxyStatus>,
|
||||
i2p_status_tx: Sender<i2p::ProxyStatus>,
|
||||
i2p_status_rx: Receiver<i2p::ProxyStatus>,
|
||||
xmrd_get_info_tx: Sender<reqres::XmrDaemonGetInfoResponse>,
|
||||
xmrd_get_info_rx: Receiver<reqres::XmrDaemonGetInfoResponse>,
|
||||
xmr_address_tx: Sender<reqres::XmrRpcAddressResponse>,
|
||||
|
@ -44,7 +44,7 @@ pub struct HomeApp {
|
|||
s_xmr_balance: reqres::XmrRpcBalanceResponse,
|
||||
s_xmr_rpc_ver: reqres::XmrRpcVersionResponse,
|
||||
s_xmrd_get_info: reqres::XmrDaemonGetInfoResponse,
|
||||
s_i2p_status: bool,
|
||||
s_i2p_status: i2p::ProxyStatus,
|
||||
s_can_refresh: bool,
|
||||
// logos
|
||||
logo_i2p: egui_extras::RetainedImage,
|
||||
|
@ -75,7 +75,7 @@ impl Default for HomeApp {
|
|||
let s_xmr_address = Default::default();
|
||||
let s_xmr_balance = Default::default();
|
||||
let s_xmrd_get_info = Default::default();
|
||||
let s_i2p_status = false;
|
||||
let s_i2p_status = i2p::ProxyStatus::Opening;
|
||||
let s_can_refresh = false;
|
||||
let c_xmr_logo = std::fs::read("./assets/xmr.png").unwrap_or(Vec::new());
|
||||
let logo_xmr =
|
||||
|
@ -140,7 +140,7 @@ impl eframe::App for HomeApp {
|
|||
self.s_can_refresh = can_refresh;
|
||||
}
|
||||
if let Ok(i2p_status) = self.i2p_status_rx.try_recv() {
|
||||
self.s_i2p_status = i2p_status.open;
|
||||
self.s_i2p_status = i2p_status;
|
||||
}
|
||||
if let Ok(info) = self.xmrd_get_info_rx.try_recv() {
|
||||
self.s_xmrd_get_info = info;
|
||||
|
@ -243,12 +243,8 @@ impl eframe::App for HomeApp {
|
|||
.open(&mut is_installing)
|
||||
.vscroll(true)
|
||||
.show(&ctx, |ui| {
|
||||
let mut wants_i2p = self.installations.i2p;
|
||||
let mut wants_i2p_zero = self.installations.i2p_zero;
|
||||
let mut wants_xmr = self.installations.xmr;
|
||||
if ui.checkbox(&mut wants_i2p, "i2p").changed() {
|
||||
self.installations.i2p = !self.installations.i2p;
|
||||
}
|
||||
if ui.checkbox(&mut wants_i2p_zero, "i2p-zero").changed() {
|
||||
self.installations.i2p_zero = !self.installations.i2p_zero;
|
||||
}
|
||||
|
@ -256,7 +252,7 @@ impl eframe::App for HomeApp {
|
|||
self.installations.xmr = !self.installations.xmr;
|
||||
}
|
||||
let install = &self.installations;
|
||||
if install.i2p || install.i2p_zero || install.xmr {
|
||||
if install.i2p_zero || install.xmr {
|
||||
if !self.is_loading {
|
||||
if ui.button("Install").clicked() {
|
||||
self.is_loading = true;
|
||||
|
@ -295,7 +291,7 @@ impl eframe::App for HomeApp {
|
|||
}
|
||||
}
|
||||
let mut str_i2p_status = String::from("offline");
|
||||
if self.s_i2p_status {
|
||||
if self.s_i2p_status == i2p::ProxyStatus::Open {
|
||||
str_i2p_status = String::from("online");
|
||||
}
|
||||
ui.horizontal(|ui| {
|
||||
|
@ -337,7 +333,7 @@ impl eframe::App for HomeApp {
|
|||
}
|
||||
}
|
||||
if !self.is_core_running && !self.is_installing
|
||||
&& (self.s_xmr_rpc_ver.result.version == 0 || self.s_i2p_status) {
|
||||
&& (self.s_xmr_rpc_ver.result.version == 0 || self.s_i2p_status == i2p::ProxyStatus::Opening) {
|
||||
if !self.is_loading {
|
||||
if ui.button("Install Software").clicked() {
|
||||
self.is_installing = true;
|
||||
|
@ -382,7 +378,7 @@ fn send_balance_req(tx: Sender<reqres::XmrRpcBalanceResponse>, ctx: egui::Contex
|
|||
});
|
||||
}
|
||||
|
||||
fn send_i2p_status_req(tx: Sender<i2p::HttpProxyStatus>, ctx: egui::Context) {
|
||||
fn send_i2p_status_req(tx: Sender<i2p::ProxyStatus>, ctx: egui::Context) {
|
||||
tokio::spawn(async move {
|
||||
let status = i2p::check_connection().await;
|
||||
let _ = tx.send(status);
|
||||
|
@ -420,7 +416,6 @@ fn install_software_req(
|
|||
installations: &utils::Installations,
|
||||
) {
|
||||
let req_install: utils::Installations = utils::Installations {
|
||||
i2p: installations.i2p,
|
||||
i2p_zero: installations.i2p_zero,
|
||||
xmr: installations.xmr,
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ pub async fn get_version(_jwp: proof::PaymentProof) -> Custom<Json<reqres::XmrRp
|
|||
///
|
||||
/// This also functions as a health check
|
||||
#[get("/status")]
|
||||
pub async fn get_i2p_status() -> Custom<Json<i2p::HttpProxyStatus>> {
|
||||
pub async fn get_i2p_status() -> Custom<Json<i2p::ProxyStatus>> {
|
||||
Custom(Status::Ok, Json(i2p::check_connection().await))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue