129 lines
3.9 KiB
Rust
129 lines
3.9 KiB
Rust
pub mod discovery;
|
|
pub mod error;
|
|
pub mod models;
|
|
pub mod server;
|
|
pub mod transfer;
|
|
|
|
use std::{
|
|
collections::HashMap,
|
|
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
|
sync::Arc,
|
|
};
|
|
|
|
use tokio::{net::UdpSocket, sync::Mutex, task::JoinHandle};
|
|
use transfer::session::Session;
|
|
|
|
use crate::models::device::DeviceInfo;
|
|
|
|
#[derive(Clone)]
|
|
pub struct Client {
|
|
pub device: DeviceInfo,
|
|
pub socket: Arc<UdpSocket>,
|
|
pub multicast_addr: SocketAddrV4,
|
|
pub port: u16,
|
|
pub peers: Arc<Mutex<HashMap<String, (SocketAddr, DeviceInfo)>>>,
|
|
pub sessions: Arc<Mutex<HashMap<String, Session>>>, // Session ID to Session
|
|
pub http_client: reqwest::Client,
|
|
pub download_dir: String,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct JoecalState {
|
|
pub device: DeviceInfo,
|
|
pub peers: Arc<Mutex<HashMap<String, (SocketAddr, DeviceInfo)>>>,
|
|
pub sessions: Arc<Mutex<HashMap<String, Session>>>, // Session ID to Session
|
|
}
|
|
|
|
impl Client {
|
|
pub async fn default() -> crate::error::Result<Self> {
|
|
let device = DeviceInfo::default();
|
|
let socket = UdpSocket::bind("0.0.0.0:53317").await?;
|
|
socket.set_multicast_loop_v4(true)?;
|
|
socket.set_multicast_ttl_v4(255)?;
|
|
socket.join_multicast_v4(Ipv4Addr::new(224, 0, 0, 167), Ipv4Addr::new(0, 0, 0, 0))?;
|
|
let multicast_addr = SocketAddrV4::new(Ipv4Addr::new(224, 0, 0, 167), 53317);
|
|
let port = 53317;
|
|
let peers = Arc::new(Mutex::new(HashMap::new()));
|
|
let http_client = reqwest::Client::new();
|
|
let sessions = Arc::new(Mutex::new(HashMap::new()));
|
|
let download_dir = "/home/localsend".to_string();
|
|
|
|
Ok(Self {
|
|
device,
|
|
socket: socket.into(),
|
|
multicast_addr,
|
|
port,
|
|
peers,
|
|
http_client,
|
|
sessions,
|
|
download_dir,
|
|
})
|
|
}
|
|
|
|
pub async fn with_config(
|
|
info: DeviceInfo,
|
|
port: u16,
|
|
download_dir: String,
|
|
) -> crate::error::Result<Self> {
|
|
let socket = UdpSocket::bind(format!("0.0.0.0:{}", port.clone())).await?;
|
|
socket.set_multicast_loop_v4(true)?;
|
|
socket.set_multicast_ttl_v4(255)?;
|
|
socket.join_multicast_v4(Ipv4Addr::new(224, 0, 0, 167), Ipv4Addr::new(0, 0, 0, 0))?;
|
|
let multicast_addr = SocketAddrV4::new(Ipv4Addr::new(224, 0, 0, 167), port);
|
|
let peers = Arc::new(Mutex::new(HashMap::new()));
|
|
let http_client = reqwest::Client::new();
|
|
let sessions = Arc::new(Mutex::new(HashMap::new()));
|
|
|
|
Ok(Self {
|
|
device: info,
|
|
socket: socket.into(),
|
|
multicast_addr,
|
|
port,
|
|
peers,
|
|
http_client,
|
|
sessions,
|
|
download_dir,
|
|
})
|
|
}
|
|
|
|
pub async fn start(
|
|
&self,
|
|
) -> crate::error::Result<(JoinHandle<()>, JoinHandle<()>, JoinHandle<()>)> {
|
|
let server_handle = {
|
|
let client = self.clone();
|
|
tokio::spawn(async move {
|
|
if let Err(e) = client.start_http_server().await {
|
|
eprintln!("HTTP server error: {e}");
|
|
}
|
|
})
|
|
};
|
|
|
|
let udp_handle = {
|
|
let client = self.clone();
|
|
tokio::spawn(async move {
|
|
if let Err(e) = client.listen_multicast().await {
|
|
eprintln!("UDP listener error: {}", e);
|
|
}
|
|
})
|
|
};
|
|
|
|
let announcement_handle = {
|
|
let client = self.clone();
|
|
tokio::spawn(async move {
|
|
loop {
|
|
if let Err(e) = client.announce(None).await {
|
|
eprintln!("Announcement error: {}", e);
|
|
}
|
|
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
|
}
|
|
})
|
|
};
|
|
|
|
Ok((server_handle, udp_handle, announcement_handle))
|
|
}
|
|
|
|
pub async fn refresh_peers(&self) {
|
|
let mut peers = self.peers.lock().await;
|
|
peers.clear();
|
|
}
|
|
}
|