107 lines
3.5 KiB
Rust
107 lines
3.5 KiB
Rust
#![windows_subsystem = "windows"]
|
|
use async_tftp::server::TftpServerBuilder;
|
|
use async_tftp::Result;
|
|
use rfd::FileDialog;
|
|
use slint::SharedString;
|
|
use std::path::PathBuf;
|
|
use tokio::task::{AbortHandle, JoinHandle};
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
slint::include_modules!();
|
|
struct ServerState {
|
|
abort_handle: Option<AbortHandle>,
|
|
}
|
|
async fn start_tftp_server(dir: PathBuf) -> Result<(JoinHandle<()>, AbortHandle)> {
|
|
let task = tokio::spawn(async move {
|
|
println!("Starting TFTP server at: {:?}", dir);
|
|
let tftpd = TftpServerBuilder::with_dir_ro(&dir)
|
|
.expect("Failed to create server")
|
|
.build()
|
|
.await
|
|
.expect("Failed to bind socket");
|
|
|
|
if let Err(e) = tftpd.serve().await {
|
|
eprintln!("Server error: {}", e);
|
|
}
|
|
});
|
|
|
|
let abort_handle = task.abort_handle();
|
|
Ok((task, abort_handle))
|
|
}
|
|
#[tokio::main]
|
|
async fn main() {
|
|
let ui = MainWindow::new().unwrap();
|
|
let state = Arc::new(Mutex::new(ServerState { abort_handle: None }));
|
|
let folder_path = Arc::new(Mutex::new(String::new()));
|
|
let path_clone = folder_path.clone();
|
|
let ui_weak = ui.as_weak();
|
|
|
|
//选择路径按钮的回调函数
|
|
ui.on_BrowserFolder(move || {
|
|
let result = FileDialog::new()
|
|
.set_directory("/")
|
|
.pick_folder();
|
|
let mut path = result.map(|p| p.to_string_lossy().into_owned())
|
|
.unwrap_or_default();
|
|
if path == "" {
|
|
println!("TFTP Dir Empty !");
|
|
if let Some(ui) = ui_weak.upgrade() {
|
|
ui.set_StartEnable(false);
|
|
}
|
|
path = String::from("");
|
|
}
|
|
else {
|
|
if let Some(ui) = ui_weak.upgrade() {
|
|
ui.set_StartEnable(true);
|
|
}
|
|
}
|
|
*path_clone.lock().unwrap() = path.clone(); // 存储到变量
|
|
SharedString::from(path)
|
|
});
|
|
//启动按钮的回调函数
|
|
let state_clone = state.clone();
|
|
let path_clone = Arc::clone(&folder_path);
|
|
let ui_weak = ui.as_weak();
|
|
ui.on_StartTftp(move || {
|
|
let dir = PathBuf::from(&*path_clone.lock().unwrap());
|
|
if dir.iter().count() == 0 {
|
|
println!("TFTP Dir Empty !");
|
|
if let Some(ui) = ui_weak.upgrade() {
|
|
ui.set_StartEnable(true);
|
|
ui.set_StopEnable(false);
|
|
}
|
|
}
|
|
else {
|
|
if let Some(ui) = ui_weak.upgrade() {
|
|
ui.set_StartEnable(false);
|
|
ui.set_StopEnable(true);
|
|
}
|
|
println!("{:?}",dir);
|
|
let state = state_clone.clone();
|
|
tokio::spawn(async move {
|
|
match start_tftp_server(dir).await {
|
|
Ok((_handle, abort_handle)) => {
|
|
println!("Server started");
|
|
// 存储 abort_handle 以便停止
|
|
state.lock().unwrap().abort_handle = Some(abort_handle);
|
|
}
|
|
Err(e) => eprintln!("Error: {}", e),
|
|
}
|
|
});
|
|
}
|
|
});
|
|
//停止按钮的回调函数
|
|
let ui_weak = ui.as_weak();
|
|
let state_clone = state.clone();
|
|
ui.on_StopTftp(move || {
|
|
if let Some(ui) = ui_weak.upgrade() {
|
|
ui.set_StartEnable(true);
|
|
ui.set_StopEnable(false);
|
|
}
|
|
if let Some(handle) = state_clone.lock().unwrap().abort_handle.take() {
|
|
handle.abort();
|
|
println!("Server stopped");
|
|
}
|
|
});
|
|
ui.run().unwrap();
|
|
} |