Skip to content

Commit

Permalink
feat: finalize windows build
Browse files Browse the repository at this point in the history
  • Loading branch information
hlhr202 committed Mar 16, 2024
1 parent f497102 commit be6d69a
Show file tree
Hide file tree
Showing 22 changed files with 985 additions and 188 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@
.vscode/
._*
.DS_Store
vpnc-script-win.js
*.example.json
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"
home = "0.5.9"
libc = "0.2.153"
dunce = "1.0.4"
41 changes: 34 additions & 7 deletions crates/openconnect-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,41 @@ impl VpnClient {
.map(|s| CString::new(s).unwrap())
.map_or_else(|| DEFAULT_VPNCSCRIPT.as_ptr() as *const i8, |s| s.as_ptr());

let ret = openconnect_setup_tun_device(
(*client).vpninfo,
vpnc_script,
std::ptr::null_mut(),
);
#[cfg(target_os = "windows")]
{
// currently use wintun on windows
// https://gitlab.com/openconnect/openconnect-gui/-/blob/main/src/vpninfo.cpp?ref_type=heads#L407
// TODO: investigate tap ip address allocation, since it works well in Openconnect-GUI
let hostname = (*client).get_hostname();
let ifname = hostname.and_then(|hostname| {
let ifname = format!("tun_{}", hostname);
CString::new(ifname).ok()
});

if let Some(ifname) = ifname {
let ret = openconnect_setup_tun_device(
(*client).vpninfo,
vpnc_script,
ifname.as_ptr(),
);
// TODO: handle ret
println!("setup_tun_device ret: {}", ret);
} else {
panic!("setup_tun_device failed: ifname is None");
}
}

// TODO: handle ret
println!("setup_tun_device ret: {}", ret);
#[cfg(not(target_os = "windows"))]
{
let ret = openconnect_setup_tun_device(
(*client).vpninfo,
vpnc_script,
std::ptr::null(), // currently use tun/tap on linux
);

// TODO: handle ret
println!("setup_tun_device ret: {}", ret);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/openconnect-gui/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ custom-protocol = ["tauri/custom-protocol"]

[target.'cfg(windows)'.dependencies]
windows-sys = { workspace = true }
dunce = { workspace = true }
44 changes: 31 additions & 13 deletions crates/openconnect-gui/src-tauri/build.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
fn main() {
// this requires signing the app
let _windows_attributes = tauri_build::WindowsAttributes::new().app_manifest(
r#"<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
let profile = std::env::var("PROFILE").unwrap();

match profile.as_str() {
"release" => {
let mut windows = tauri_build::WindowsAttributes::new();

windows = windows.app_manifest(
r#"<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="true" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"#,
);

// this requires signing the app
// tauri_build::try_build(tauri_build::Attributes::new().windows_attributes(windows_attributes))
// .expect("error while building tauri application")

tauri_build::build();
</assembly>"#,
);
tauri_build::try_build(tauri_build::Attributes::new().windows_attributes(windows))
.expect("failed to run build script");
}
"debug" => {
tauri_build::build();
}
_ => {}
}
}
94 changes: 62 additions & 32 deletions crates/openconnect-gui/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@

mod oidc;
mod state;
use std::os::unix::fs::PermissionsExt;

use openconnect_core::storage::{StoredConfigs, StoredConfigsJson};
use openconnect_core::storage::{StoredConfigs, StoredConfigsJson, StoredServer};
use state::AppState;
use tauri::Manager;

Expand All @@ -16,14 +15,12 @@ fn greet(name: &str) -> String {
}

#[tauri::command(rename_all = "snake_case")]
async fn connect(
async fn connect_with_password(
app_state: tauri::State<'_, AppState>,
server: String,
username: String,
password: String,
server_name: String,
) -> anyhow::Result<(), String> {
app_state
.connect_with_user_pass(&server, &username, &password)
.connect_with_user_pass(&server_name)
.await
.map_err(|e| e.to_string())
}
Expand Down Expand Up @@ -64,6 +61,20 @@ async fn get_stored_configs() -> anyhow::Result<StoredConfigsJson, String> {
Ok(stored_configs.into())
}

#[tauri::command]
async fn upsert_stored_server(server: StoredServer) -> anyhow::Result<(), String> {
let mut stored_configs = StoredConfigs::new();
stored_configs
.read_from_file()
.await
.map_err(|e| e.to_string())?;
stored_configs
.upsert_server(server)
.await
.map_err(|e| e.to_string())?;
Ok(())
}

fn main() {
#[cfg(target_os = "linux")]
{
Expand Down Expand Up @@ -92,40 +103,59 @@ fn main() {
.body(b"Authenticated, close this window and return to the application.".to_vec())
})
.setup(|app| {
#[cfg(not(target_os = "windows"))]
{
let resource_path = app
.path_resolver()
.resolve_resource("vpnc-scripts/vpnc-script")
.expect("failed to resolve resource");

let file = std::fs::OpenOptions::new()
.write(false)
.create(false)
.append(false)
.read(true)
.open(resource_path)
.expect("failed to open file");

let permissions = file.metadata().unwrap().permissions();
let is_executable = permissions.mode() & 0o111 != 0;
if !is_executable {
let mut permissions = permissions;
permissions.set_mode(0o755);
file.set_permissions(permissions).unwrap();
let vpnc_script = {
#[cfg(target_os = "windows")]
{
let resource_path = app
.path_resolver()
.resolve_resource("vpnc-script-win.js")
.expect("failed to resolve resource");

dunce::canonicalize(resource_path)
.expect("failed to canonicalize path")
.to_string_lossy()
.to_string()
}
}

AppState::handle(app);
#[cfg(not(target_os = "windows"))]
{
use std::os::unix::fs::PermissionsExt;
let resource_path = app
.path_resolver()
.resolve_resource("vpnc-script")
.expect("failed to resolve resource");

let file = std::fs::OpenOptions::new()
.write(false)
.create(false)
.append(false)
.read(true)
.open(resource_path)
.expect("failed to open file");

let permissions = file.metadata().unwrap().permissions();
let is_executable = permissions.mode() & 0o111 != 0;
if !is_executable {
let mut permissions = permissions;
permissions.set_mode(0o755);
file.set_permissions(permissions).unwrap();
}

resource_path.to_string_lossy().to_string()
}
};

AppState::handle_with_vpnc_script(app, &vpnc_script);
Ok(())
})
.invoke_handler(tauri::generate_handler![
greet,
connect,
disconnect,
trigger_state_retrieve,
get_stored_configs,
upsert_stored_server,
connect_with_password,
connect_with_oidc,
get_stored_configs
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
Expand Down
43 changes: 29 additions & 14 deletions crates/openconnect-gui/src-tauri/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ impl From<Status> for StatusPayload {
pub struct AppState {
pub(crate) event_tx: Sender<VpnEvent>,
pub(crate) client: RwLock<Option<Arc<VpnClient>>>,
#[allow(dead_code)]
pub(crate) vpnc_sciprt: String,
}

impl AppState {
pub fn handle(app: &mut tauri::App) {
pub fn handle_with_vpnc_script(app: &mut tauri::App, vpnc_scipt: &str) {
let (event_tx, mut event_rx) = channel::<VpnEvent>(100);
let app_state = AppState::new(event_tx);
let app_state = AppState::new(event_tx, vpnc_scipt);
app.manage(app_state);

let handle = app.app_handle();
Expand Down Expand Up @@ -79,18 +81,25 @@ impl AppState {
}
}

pub async fn connect_with_user_pass(
&self,
server: &str,
username: &str,
password: &str,
) -> anyhow::Result<()> {
let config = ConfigBuilder::default().loglevel(LogLevel::Info).build()?;
pub async fn connect_with_user_pass(&self, server_name: &str) -> anyhow::Result<()> {
let mut stored_server = StoredConfigs::default();
let stored_server = stored_server
.read_from_file()
.await?
.get_server_as_password(server_name)
.ok_or(anyhow::anyhow!("Server not found"))?;

let mut config = ConfigBuilder::default();

#[cfg(not(target_os = "windows"))]
let mut config = config.vpncscript(&self.vpnc_sciprt);

let config = config.loglevel(LogLevel::Info).build()?;

let entrypoint = EntrypointBuilder::new()
.server(server)
.username(username)
.password(password)
.server(&stored_server.server)
.username(&stored_server.username)
.password(&stored_server.password)
.enable_udp(true)
.build()?;

Expand Down Expand Up @@ -148,7 +157,12 @@ impl AppState {
.await
.ok_or(anyhow::anyhow!("Failed to obtain cookie from server"))?;

let config = ConfigBuilder::default().loglevel(LogLevel::Info).build()?;
let mut config = ConfigBuilder::default();

#[cfg(not(target_os = "windows"))]
let mut config = config.vpncscript(&self.vpnc_sciprt);

let config = config.loglevel(LogLevel::Info).build()?;

let entrypoint = EntrypointBuilder::new()
.server(&stored_server.server)
Expand Down Expand Up @@ -189,10 +203,11 @@ impl AppState {
Ok(())
}

pub fn new(event_tx: Sender<VpnEvent>) -> Self {
pub fn new(event_tx: Sender<VpnEvent>, vpnc_scipt: &str) -> Self {
Self {
event_tx,
client: RwLock::new(None),
vpnc_sciprt: vpnc_scipt.to_string(),
}
}
}
8 changes: 5 additions & 3 deletions crates/openconnect-gui/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
"windows": [
{
"title": "openconnect-gui",
"width": 800,
"height": 600,
"width": 900,
"height": 800,
"transparent": true,
"decorations": false
}
Expand All @@ -56,7 +56,9 @@
"icons/icon.ico"
],
"resources": [
"vpnc-scripts/*"
"vpnc-script",
"vpnc-script-win.js",
"wintun.dll"
]
}
}
Expand Down
Loading

0 comments on commit be6d69a

Please sign in to comment.