diff --git a/Cargo.lock b/Cargo.lock index 0f88bbd..c076abc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -139,7 +139,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -199,6 +199,12 @@ version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.10.1" @@ -344,7 +350,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.104", ] [[package]] @@ -355,7 +361,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -409,7 +415,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -927,7 +933,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -989,15 +995,17 @@ dependencies = [ "chrono", "figment", "julid-rs", + "local-ip-address", "mime", "mime_guess", "native-dialog", + "network-interface", "ratatui", "reqwest", "serde", "serde_json", "sha256", - "thiserror", + "thiserror 2.0.12", "tokio", "tower-http", ] @@ -1056,6 +1064,18 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +[[package]] +name = "local-ip-address" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "656b3b27f8893f7bbf9485148ff9a65f019e3f33bd5cdc87c83cab16b3fd9ec8" +dependencies = [ + "libc", + "neli", + "thiserror 2.0.12", + "windows-sys 0.59.0", +] + [[package]] name = "lock_api" version = "0.4.13" @@ -1147,7 +1167,7 @@ dependencies = [ "objc2-core-graphics", "objc2-foundation", "raw-window-handle", - "thiserror", + "thiserror 2.0.12", "versions", "wfd", "which", @@ -1171,6 +1191,44 @@ dependencies = [ "tempfile", ] +[[package]] +name = "neli" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9" +dependencies = [ + "byteorder", + "libc", + "log", + "neli-proc-macros", +] + +[[package]] +name = "neli-proc-macros" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe" +dependencies = [ + "either", + "proc-macro2", + "quote", + "serde", + "syn 1.0.109", +] + +[[package]] +name = "network-interface" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3329f515506e4a2de3aa6e07027a6758e22e0f0e8eaf64fa47261cec2282602" +dependencies = [ + "cc", + "libc", + "serde", + "thiserror 1.0.69", + "winapi", +] + [[package]] name = "nom" version = "8.0.0" @@ -1368,7 +1426,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1444,7 +1502,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1506,7 +1564,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", "version_check", "yansi", ] @@ -1600,7 +1658,7 @@ checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror", + "thiserror 2.0.12", ] [[package]] @@ -1789,7 +1847,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -1954,7 +2012,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 2.0.104", ] [[package]] @@ -1963,6 +2021,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.104" @@ -1991,7 +2060,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -2028,13 +2097,33 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", ] [[package]] @@ -2045,7 +2134,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -2086,7 +2175,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -2383,7 +2472,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 2.0.104", "wasm-bindgen-shared", ] @@ -2418,7 +2507,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2507,7 +2596,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -2518,7 +2607,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -2767,7 +2856,7 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", "synstructure", ] @@ -2788,7 +2877,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] [[package]] @@ -2808,7 +2897,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", "synstructure", ] @@ -2848,5 +2937,5 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.104", ] diff --git a/Cargo.toml b/Cargo.toml index 956db24..8f2e6b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,11 @@ axum = { version = "0.8", features = ["macros"] } chrono = "0.4" figment = { version = "0.10", features = ["toml", "test", "env"] } julid-rs = { version = "1", default-features = false, features = ["serde"] } +local-ip-address = "0.6" mime = "0.3" mime_guess = "2" native-dialog = "0.9" +network-interface = { version = "2", features = ["serde"] } ratatui = "0.29" reqwest = { version = "0.12", features = ["json"] } serde = { version = "1", features = ["derive"] } diff --git a/src/discovery/mod.rs b/src/discovery/mod.rs index 9faa60a..a37f2ee 100644 --- a/src/discovery/mod.rs +++ b/src/discovery/mod.rs @@ -22,7 +22,7 @@ impl Client { src.set_port(device.port); // Update the port to the one the device sent let mut peers = self.peers.lock().await; - peers.insert(device.fingerprint.clone(), (src.clone(), device.clone())); + peers.insert(device.fingerprint.clone(), (src, device.clone())); if device.announce != Some(true) { return; @@ -31,13 +31,13 @@ impl Client { // Announce in return upon receiving a valid device message and it wants // announcements if let Err(e) = self.announce_multicast().await { - eprintln!("Error during multicast announcement: {}", e); + eprintln!("Error during multicast announcement: {e}"); } if let Err(e) = self.announce_http(Some(src)).await { - eprintln!("Error during HTTP announcement: {}", e); + eprintln!("Error during HTTP announcement: {e}"); }; } else { - eprintln!("Received invalid message: {}", message); + eprintln!("Received invalid message: {message}"); } } } diff --git a/src/error.rs b/src/error.rs index c3b28ed..b73215a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -38,6 +38,9 @@ pub enum LocalSendError { #[error("Cancel Failed")] CancelFailed, + + #[error("No broadcast IP available")] + NoBroadcastIP, } pub type Result = std::result::Result; diff --git a/src/lib.rs b/src/lib.rs index b44b1f4..f17ccc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,7 +102,7 @@ impl Client { let client = self.clone(); tokio::spawn(async move { if let Err(e) = client.listen_multicast().await { - eprintln!("UDP listener error: {}", e); + eprintln!("UDP listener error: {e}"); } }) }; @@ -112,7 +112,7 @@ impl Client { tokio::spawn(async move { loop { if let Err(e) = client.announce(None).await { - eprintln!("Announcement error: {}", e); + eprintln!("Announcement error: {e}"); } tokio::time::sleep(std::time::Duration::from_secs(5)).await; } diff --git a/src/main.rs b/src/main.rs index 3fc6812..4d6afa1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,13 @@ -use joecalsend::{Client, models::device::DeviceInfo}; -use tokio::io; +#![feature(ip_as_octets)] +#![feature(slice_as_array)] +use std::net::Ipv4Addr; + +use joecalsend::{Client, error, models::device::DeviceInfo}; +use local_ip_address::local_ip; +use network_interface::{Addr, NetworkInterface, NetworkInterfaceConfig, V4IfAddr}; #[tokio::main] -async fn main() -> io::Result<()> { +async fn main() -> error::Result<()> { let device = DeviceInfo::default(); dbg!(&device); @@ -10,6 +15,27 @@ async fn main() -> io::Result<()> { .await .unwrap(); let (h1, h2, h3) = client.start().await.unwrap(); + let ip = local_ip().unwrap(); + if !ip.is_ipv4() { + return Err(error::LocalSendError::NoBroadcastIP); + } + let local_device_ip = Ipv4Addr::from_bits(u32::from_be_bytes( + ip.as_octets().as_array().unwrap().to_owned(), + )); + + let nifs = NetworkInterface::show().unwrap(); + let mut mask = Ipv4Addr::from_bits(u32::MAX); + 'outer: for nif in nifs { + for addr in nif.addr { + if let Addr::V4(V4IfAddr { ip, netmask, .. }) = addr + && ip == local_device_ip + { + mask = netmask.unwrap_or(mask); + break 'outer; + } + } + } + dbg!(mask); let _ = tokio::join!(h1, h2, h3); Ok(()) diff --git a/src/transfer/upload.rs b/src/transfer/upload.rs index ae2ef19..06bdd7d 100644 --- a/src/transfer/upload.rs +++ b/src/transfer/upload.rs @@ -60,7 +60,7 @@ impl Client { .send() .await?; - println!("Response: {:?}", response); + println!("Response: {response:?}"); let response: PrepareUploadResponse = response.json().await?; @@ -102,18 +102,16 @@ impl Client { let request = self .http_client - .post(&format!( - "{}://{}/api/localsend/v2/upload?sessionId={}&fileId={}&token={}", - session.receiver.protocol, session.addr, session_id, file_id, token - )) - //.post(&format!("https://webhook.site/2f23a529-b687-4375-ad5f-54906ab26ac7?session_id={}&file_id={}&token={}", session_id, file_id, token)) + .post(format!( + "{}://{}/api/localsend/v2/upload?sessionId={session_id}&fileId={file_id}&token={token}", + session.receiver.protocol, session.addr)) .body(body); - println!("Uploading file: {:?}", request); + println!("Uploading file: {request:?}"); let response = request.send().await?; if response.status() != 200 { - println!("Upload failed: {:?}", response); + println!("Upload failed: {response:?}"); return Err(LocalSendError::UploadFailed); } @@ -159,7 +157,7 @@ impl Client { let request = self .http_client - .post(&format!( + .post(format!( "{}://{}/api/localsend/v2/cancel?sessionId={}", session.receiver.protocol, session.addr, session_id )) @@ -193,8 +191,8 @@ pub async fn register_prepare_upload( let file_tokens: HashMap = req .files - .iter() - .map(|(id, _)| (id.clone(), Julid::new().to_string())) // Replace with actual token logic + .keys() + .map(|id| (id.clone(), Julid::new().to_string())) // Replace with actual token logic .collect(); let session = Session { @@ -213,16 +211,16 @@ pub async fn register_prepare_upload( .await .insert(session_id.clone(), session); - return ( + ( StatusCode::OK, Json(PrepareUploadResponse { session_id, files: file_tokens, }), ) - .into_response(); + .into_response() } else { - return StatusCode::FORBIDDEN.into_response(); + StatusCode::FORBIDDEN.into_response() } } @@ -269,7 +267,7 @@ pub async fn register_upload( if let Err(e) = tokio::fs::create_dir_all(&*download_dir).await { return ( StatusCode::INTERNAL_SERVER_ERROR, - format!("Failed to create directory: {}", e), + format!("Failed to create directory: {e}"), ) .into_response(); } @@ -281,7 +279,7 @@ pub async fn register_upload( if let Err(e) = tokio::fs::write(&file_path, body).await { return ( StatusCode::INTERNAL_SERVER_ERROR, - format!("Failed to write file: {}", e), + format!("Failed to write file: {e}"), ) .into_response(); }