Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,793 changes: 967 additions & 826 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions emissary-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ emissary-core = { path = "../emissary-core", version = "0.3.0" }
emissary-util = { path = "../emissary-util", version = "0.3.0", features = ["tokio"] }
futures = "0.3.31"
httparse = "1.10.1"
iced = { version = "0.13.1", features = ["advanced", "tokio", "svg"], optional = true }
plotters-iced = { version = "0.11.0", optional = true }
iced = { version = "0.14.0", features = ["advanced", "tokio", "svg", "canvas"], optional = true }
plotters-iced2 = { version = "0.14.0", optional = true }
plotters = { version = "0.3.7", optional = true }
serde_json = { version = "1.0.140", optional = true }
thiserror = "2.0.12"
Expand All @@ -44,6 +44,6 @@ fast-socks5 = { version = "0.10.0", features = ["socks4"] }

[features]
default = ["native-ui"]
native-ui = ["chrono", "iced", "plotters", "plotters-iced"]
native-ui = ["chrono", "iced", "plotters", "plotters-iced2"]
web-ui = ["axum", "serde_json", "tokio-tungstenite"]
metrics = ["emissary-util/metrics"]
23 changes: 13 additions & 10 deletions emissary-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,11 @@ fn main() -> anyhow::Result<()> {
Ok(())
}

/// A main function which should be run within an async context.
#[cfg(feature = "native-ui")]
fn main() -> anyhow::Result<()> {
let runtime = tokio::runtime::Runtime::new()?;
async fn native_main() -> anyhow::Result<()> {
let (shutdown_tx, shutdown_rx) = channel(1);
let arguments = runtime.block_on(parse_arguments());
let arguments = parse_arguments().await;
let RouterContext {
router,
port_mapper,
Expand All @@ -442,20 +442,17 @@ fn main() -> anyhow::Result<()> {
base_path,
address_book_handle,
router_id,
} = runtime.block_on(setup_router::<TokioRuntime>(arguments))?;

} = setup_router::<TokioRuntime>(arguments).await?;
match router_ui_config {
None => {
runtime.block_on(router_event_loop(router, port_mapper, shutdown_rx));

router_event_loop(router, port_mapper, shutdown_rx).await;
Ok(())
}
Some(RouterUiConfig { .. }) => {
std::thread::spawn(move || {
runtime.block_on(router_event_loop(router, port_mapper, shutdown_rx));
tokio::spawn(async {
router_event_loop(router, port_mapper, shutdown_rx).await;
std::process::exit(0);
});

ui::native::RouterUi::start(
events,
config,
Expand All @@ -467,3 +464,9 @@ fn main() -> anyhow::Result<()> {
}
}
}

#[cfg(feature = "native-ui")]
fn main() -> anyhow::Result<()> {
let runtime = tokio::runtime::Runtime::new()?;
runtime.block_on(native_main())
}
2 changes: 1 addition & 1 deletion emissary-cli/src/ui/native/bandwidth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use iced::{
widget::{button, column, container, row, Column, Container, Row},
Border, Color, Element, Length, Theme,
};
use plotters_iced::ChartWidget;
use plotters_iced2::ChartWidget;

fn time_button<'a>(
label: &'a str,
Expand Down
22 changes: 11 additions & 11 deletions emissary-cli/src/ui/native/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use iced::{
widget::{button, column, container, row, Column, Container, Row, Space},
Border, Color, Element, Length, Theme,
};
use plotters_iced::ChartWidget;
use plotters_iced2::ChartWidget;

impl RouterUi {
pub fn dashboard(&self) -> Element<'_, Message> {
Expand Down Expand Up @@ -110,7 +110,7 @@ impl RouterUi {
.push(
Text::new("HTTP Proxy").color(Color::from_rgb(0.8392, 0.8392, 0.8392)),
)
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(http_proxy)
.width(Length::Fill),
)
Expand All @@ -119,28 +119,28 @@ impl RouterUi {
.push(
Text::new("SOCKS Proxy").color(Color::from_rgb(0.8392, 0.8392, 0.8392)),
)
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(socks_proxy)
.width(Length::Fill),
)
.push(
Row::new()
.push(Text::new("I2CP").color(Color::from_rgb(0.8392, 0.8392, 0.8392)))
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(i2cp)
.width(Length::Fill),
)
.push(
Row::new()
.push(Text::new("SAMv3 TCP").color(Color::from_rgb(0.8392, 0.8392, 0.8392)))
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(sam_tcp)
.width(Length::Fill),
)
.push(
Row::new()
.push(Text::new("SAMv3 UDP").color(Color::from_rgb(0.8392, 0.8392, 0.8392)))
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(sam_udp)
.width(Length::Fill),
)
Expand Down Expand Up @@ -171,7 +171,7 @@ impl RouterUi {
Text::new("Router version")
.color(Color::from_rgb(0.8392, 0.8392, 0.8392)),
)
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(
Text::new(format!("v{}", env!("CARGO_PKG_VERSION")))
.color(Color::from_rgb(0.8392, 0.8392, 0.8392)),
Expand All @@ -181,7 +181,7 @@ impl RouterUi {
.push(
Row::new()
.push(Text::new("Router ID").color(Color::from_rgb(0.8392, 0.8392, 0.8392)))
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(
button(if self.show_router_id {
Text::new(&self.router_id)
Expand All @@ -205,7 +205,7 @@ impl RouterUi {
.push(
Text::new("IPv4 status").color(Color::from_rgb(0.8392, 0.8392, 0.8392)),
)
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(Text::new("OK").color(Color::from_rgb(0.8392, 0.8392, 0.8392)))
.width(Length::Fill),
)
Expand All @@ -214,14 +214,14 @@ impl RouterUi {
.push(
Text::new("IPv6 status").color(Color::from_rgb(0.8392, 0.8392, 0.8392)),
)
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push(Text::new("Disabled").color(Color::from_rgb(0.8392, 0.8392, 0.8392)))
.width(Length::Fill),
)
.push(
Row::new()
.push(Text::new("Uptime").color(Color::from_rgb(0.8392, 0.8392, 0.8392)))
.push(Space::with_width(Length::Fill))
.push(Space::new().width(Length::Fill))
.push({
let mut uptime = self.uptime.elapsed().as_secs();
if uptime == 0 {
Expand Down
4 changes: 2 additions & 2 deletions emissary-cli/src/ui/native/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ use plotters::{
prelude::*,
style::{ShapeStyle, WHITE},
};
use plotters_iced::Chart;
use plotters_iced2::Chart;

impl Chart<Message> for RouterUi {
type State = ();

#[inline]
fn draw<R: plotters_iced::Renderer, F: Fn(&mut iced::widget::canvas::Frame)>(
fn draw<R: plotters_iced2::Renderer, F: Fn(&mut iced::widget::canvas::Frame)>(
&self,
renderer: &R,
bounds: iced::Size,
Expand Down
64 changes: 52 additions & 12 deletions emissary-cli/src/ui/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,14 @@ use iced::{
border::Radius,
time,
widget::{canvas::Cache, container, row, svg, Column, Container, Row},
Alignment, Background, Border, Color, Element,
Alignment, Background, Border, Color, Element, Executor,
Length::{self, FillPortion},
Subscription, Task, Theme,
};
use tokio::sync::mpsc::Sender;

use std::{
cell::RefCell,
collections::BTreeMap,
path::PathBuf,
sync::Arc,
Expand Down Expand Up @@ -188,6 +189,38 @@ pub struct RouterUi {
address_book_handle: Option<Arc<AddressBookHandle>>,
}

/// A custom executor for iced. We'll need this primarily because iced calls
/// `block_on` at some point, which ends up panicing because it's called in
/// an async context [0].
///
/// [0]: https://docs.rs/tokio/1.32.0/tokio/runtime/struct.Runtime.html#panics
struct TaskExecutor {}

impl Executor for TaskExecutor {
fn new() -> Result<Self, futures::io::Error>
where
Self: Sized,
{
Ok(Self {})
}

fn spawn(
&self,
future: impl std::future::Future<Output = ()>
+ iced::advanced::graphics::futures::MaybeSend
+ 'static,
) {
tokio::spawn(future);
}

// Annotation from iced:
// https://docs.rs/iced_futures/0.14.0/src/iced_futures/executor.rs.html#16
#[cfg(not(target_arch = "wasm32"))]
fn block_on<T>(&self, future: impl std::future::Future<Output = T>) -> T {
tokio::task::block_in_place(|| tokio::runtime::Handle::current().block_on(future))
}
}

impl RouterUi {
fn new(
events: EventSubscriber,
Expand Down Expand Up @@ -351,19 +384,26 @@ impl RouterUi {
router_id: RouterId,
shutdown_tx: Sender<()>,
) -> anyhow::Result<()> {
iced::application("emissary", RouterUi::update, RouterUi::view)
// Upstream: https://github.com/iced-rs/iced/issues/3080
// Adapted from: https://discourse.iced.rs/t/solved-new-boot-trait-no-longer-able-to-use-a-capturing-closure-to-initialize-application-state/1012/6
let boot_once = RefCell::new(Some(RouterUi::new(
events,
config,
base_path,
address_book_handle,
router_id,
shutdown_tx,
)));
let boot = move || match boot_once.borrow_mut().take() {
Some(v) => v,
None => unreachable!(),
};
iced::application(boot, RouterUi::update, RouterUi::view)
.title("emissary")
.subscription(RouterUi::subscription)
.executor::<TaskExecutor>()
.theme(RouterUi::theme)
.run_with(move || {
RouterUi::new(
events,
config,
base_path,
address_book_handle,
router_id,
shutdown_tx,
)
})
.run()
.map_err(From::from)
}

Expand Down
9 changes: 6 additions & 3 deletions emissary-cli/src/ui/native/settings/advanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ impl RouterUi {
Column::new()
.push(Text::new("NetDB"))
.push(
Checkbox::new("Run the router as floodfill", self.advanced.floodfill())
Checkbox::new(self.advanced.floodfill())
.label("Run the router as floodfill")
.size(15)
.on_toggle(Message::FloodfillEnabled)
.style(|_theme: &Theme, status: _| iced::widget::checkbox::Style {
Expand Down Expand Up @@ -101,7 +102,8 @@ impl RouterUi {
Column::new()
.push(Text::new("Development"))
.push(
Checkbox::new("Allow use of local addresses", self.advanced.allow_local())
Checkbox::new(self.advanced.allow_local())
.label("Allow use of local addresses")
.size(15)
.on_toggle(Message::LocalAddressesEnabled)
.style(|_theme: &Theme, status: _| iced::widget::checkbox::Style {
Expand All @@ -122,7 +124,8 @@ impl RouterUi {
}),
)
.push(
Checkbox::new("Enable insecure tunnels", self.advanced.insecure_tunnels())
Checkbox::new(self.advanced.insecure_tunnels())
.label("Enable insecure tunnels")
.size(15)
.on_toggle(Message::InsecureTunnelsEnabled)
.style(|_theme: &Theme, status: _| iced::widget::checkbox::Style {
Expand Down
6 changes: 4 additions & 2 deletions emissary-cli/src/ui/native/settings/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ impl RouterUi {
),
)
.push(
Checkbox::new("Enable", self.i2cp.enabled())
Checkbox::new(self.i2cp.enabled())
.label("Enable")
.size(15)
.on_toggle(Message::I2cpEnabled)
.style(|_theme: &Theme, status: _| iced::widget::checkbox::Style {
Expand Down Expand Up @@ -327,7 +328,8 @@ impl RouterUi {
),
)
.push(
Checkbox::new("Enable", self.sam.enabled())
Checkbox::new(self.sam.enabled())
.label("Enable")
.text_size(15)
.on_toggle(Message::SamEnabled)
.style(|_theme: &Theme, status: _| iced::widget::checkbox::Style {
Expand Down
6 changes: 4 additions & 2 deletions emissary-cli/src/ui/native/settings/proxies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,8 @@ impl RouterUi {
),
)
.push(
Checkbox::new("Enable", self.http_proxy.enabled())
Checkbox::new(self.http_proxy.enabled())
.label("Enable")
.size(15)
.on_toggle(Message::HttpEnabled)
.style(|_theme: &Theme, status: _| iced::widget::checkbox::Style {
Expand Down Expand Up @@ -541,7 +542,8 @@ impl RouterUi {
),
)
.push(
Checkbox::new("Enable", self.socks_proxy.enabled())
Checkbox::new(self.socks_proxy.enabled())
.label("Enable")
.size(15)
.on_toggle(Message::SocksEnabled)
.style(|_theme: &Theme, status: _| iced::widget::checkbox::Style {
Expand Down
Loading
Loading