Skip to content

Commit 1bc25e0

Browse files
committed
✨ add config storage for scopes
1 parent 54d3066 commit 1bc25e0

File tree

6 files changed

+88
-8
lines changed

6 files changed

+88
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ homepage = "https://github.com/XDSEC/WebSocketReflectorX"
99
license = "MIT"
1010
repository = "https://github.com/XDSEC/WebSocketReflectorX"
1111
rust-version = "1.85.0"
12-
version = "0.4.2"
12+
version = "0.4.3"
1313

1414
[profile.release]
1515
codegen-units = 1

crates/desktop/src/daemon/api_controller.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct InstanceResponse {
108108
from: String,
109109
/// deprecated
110110
to: String,
111+
latency: i32,
111112
}
112113

113114
async fn get_instances(
@@ -128,6 +129,7 @@ async fn get_instances(
128129
local: instance.local.clone(),
129130
from: instance.local.clone(),
130131
to: instance.remote.clone(),
132+
latency: instance.latency,
131133
})
132134
} else {
133135
None

crates/desktop/src/daemon/mod.rs

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use std::{process, rc::Rc, sync::Arc};
33
use api_controller::router;
44

55
use directories::ProjectDirs;
6-
use model::ServerState;
7-
use slint::{ComponentHandle, VecModel};
6+
use model::{ScopeData, ServerState};
7+
use serde::{Deserialize, Serialize};
8+
use slint::{ComponentHandle, Model, VecModel};
89
use tokio::{net::TcpListener, sync::RwLock};
910

1011
use tracing::{debug, error, info, warn};
@@ -16,6 +17,11 @@ mod latency_worker;
1617
mod model;
1718
mod ui_controller;
1819

20+
#[derive(Clone, Debug, Serialize, Deserialize)]
21+
struct ScopesConfig {
22+
scopes: Vec<ScopeData>,
23+
}
24+
1925
pub fn setup(ui: &MainWindow) {
2026
use rustls::crypto;
2127

@@ -36,20 +42,50 @@ pub fn setup(ui: &MainWindow) {
3642
}
3743
}
3844

45+
// read config scope
46+
let proj_dirs = match ProjectDirs::from("org", "xdsec", "wsrx") {
47+
Some(dirs) => dirs,
48+
None => {
49+
error!("Unable to find project config directories");
50+
return;
51+
}
52+
};
53+
let config_file = proj_dirs.config_dir().join("scopes.toml");
54+
let config = match std::fs::read_to_string(&config_file) {
55+
Ok(config) => config,
56+
Err(_) => "".to_owned(),
57+
};
58+
let scopes: ScopesConfig = match toml::from_str(&config) {
59+
Ok(scopes) => scopes,
60+
Err(e) => {
61+
error!("Failed to parse config file: {}", e);
62+
ScopesConfig { scopes: vec![] }
63+
}
64+
};
65+
debug!("Loaded scopes: {:?}", scopes);
66+
3967
let handle = ui.as_weak();
4068

4169
let state_d = ServerState {
4270
ui: handle.clone(),
4371
instances: Arc::new(RwLock::new(vec![])),
44-
scopes: Arc::new(RwLock::new(vec![])),
72+
scopes: Arc::new(RwLock::new(scopes.scopes.clone())),
4573
};
4674
// Initialize the global state
4775
let instances: Rc<VecModel<Instance>> = Rc::new(VecModel::default());
48-
let scopes: Rc<VecModel<Scope>> = Rc::new(VecModel::default());
76+
let scopes_r: Rc<VecModel<Scope>> = Rc::new(VecModel::default());
77+
for scope in scopes.scopes.iter() {
78+
scopes_r.push(Scope {
79+
host: scope.host.clone().into(),
80+
name: scope.name.clone().into(),
81+
state: scope.state.clone().into(),
82+
features: scope.features.join(",").into(),
83+
});
84+
}
4985
let scoped_instances: Rc<VecModel<Instance>> = Rc::new(VecModel::default());
5086

5187
let instances_rc = slint::ModelRc::from(instances.clone());
52-
let scopes_rc = slint::ModelRc::from(scopes.clone());
88+
let scopes_rc = slint::ModelRc::from(scopes_r.clone());
5389
let scoped_instances_rc = slint::ModelRc::from(scoped_instances.clone());
5490

5591
let instance_bridge = ui.global::<InstanceBridge>();
@@ -190,3 +226,44 @@ pub fn setup(ui: &MainWindow) {
190226
}
191227
}
192228
}
229+
230+
pub fn save_scopes(ui: &slint::Weak<MainWindow>) {
231+
let window = ui.upgrade().unwrap();
232+
let scope_bridge = window.global::<ScopeBridge>();
233+
let scopes = scope_bridge.get_scopes();
234+
let scopes = scopes.as_any().downcast_ref::<VecModel<Scope>>().unwrap();
235+
let mut scopes_vec = vec![];
236+
for scope in scopes.iter() {
237+
scopes_vec.push(ScopeData {
238+
host: scope.host.to_string(),
239+
name: scope.name.to_string(),
240+
state: scope.state.to_string(),
241+
features: scope
242+
.features
243+
.split(",")
244+
.map(|s| s.trim().to_string())
245+
.collect(),
246+
});
247+
}
248+
let proj_dirs = match ProjectDirs::from("org", "xdsec", "wsrx") {
249+
Some(dirs) => dirs,
250+
None => {
251+
error!("Unable to find project config directories");
252+
return;
253+
}
254+
};
255+
let config_file = proj_dirs.config_dir().join("scopes.toml");
256+
let config_obj = ScopesConfig { scopes: scopes_vec };
257+
let config = toml::to_string(&config_obj).unwrap_or_else(|e| {
258+
error!("Failed to serialize scopes: {}", e);
259+
String::new()
260+
});
261+
if let Err(e) = std::fs::create_dir_all(proj_dirs.config_dir()) {
262+
error!("Failed to create config directory: {}", e);
263+
return;
264+
}
265+
if let Err(e) = std::fs::write(&config_file, config) {
266+
error!("Failed to write config file: {}", e);
267+
}
268+
debug!("Saved scopes to: {:?}", config_file);
269+
}

crates/desktop/src/daemon/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub fn default_label() -> String {
4646
format!("inst-{:06x}", rand::random::<u32>())
4747
}
4848

49-
#[derive(Debug, Serialize, Deserialize)]
49+
#[derive(Clone, Debug, Serialize, Deserialize)]
5050
pub struct ScopeData {
5151
pub host: String,
5252
pub name: String,

crates/desktop/src/launcher.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub fn setup() -> Result<MainWindow, PlatformError> {
6666
pub fn shutdown(ui: &slint::Weak<MainWindow>) {
6767
let window = ui.upgrade().unwrap();
6868
bridges::settings::save_config(&window);
69+
daemon::save_scopes(ui);
6970
let proj_dirs = match ProjectDirs::from("org", "xdsec", "wsrx") {
7071
Some(dirs) => dirs,
7172
None => {

windows/setup.nsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Unicode True
1111
!define DESCRIPTION "Controlled TCP-over-WebSocket forwarding tunnel."
1212
!define VERSIONMAJOR 0
1313
!define VERSIONMINOR 4
14-
!define VERSIONBUILD 2
14+
!define VERSIONBUILD 3
1515
!define INSTALL_DIR_DEFAULT "$PROGRAMFILES64\${APPNAME}"
1616
!define MUI_ABORTWARNING
1717
!define MUI_FINISHPAGE_RUN

0 commit comments

Comments
 (0)