Skip to content

Commit

Permalink
Detect OS before choosing IpNeighborScanner
Browse files Browse the repository at this point in the history
  • Loading branch information
seamlik committed Mar 12, 2024
1 parent 1db1da7 commit 2052341
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 4 deletions.
2 changes: 1 addition & 1 deletion main/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mockall = "0.12"
prost = "0.12"
tansa-protocol = { path = "../protocol/rust" }
thiserror = "1"
tokio = "1"
tokio = { version = "1", features = ["fs"] }
tokio-stream = { version = "0.1", features = ["net"] }
tokio-util = { version = "0.7", features = ["codec", "net"]}
tonic = "0.11"
Expand Down
1 change: 1 addition & 0 deletions main/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
//! Usually contains the socket address accessible within the LAN you connect.

mod network;
mod os;
mod packet;
mod response_collector;
mod response_sender;
Expand Down
14 changes: 13 additions & 1 deletion main/src/network/link_local/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
use crate::os::OperatingSystem;
use futures_util::future::BoxFuture;
use futures_util::FutureExt;
use mockall::automock;
use std::net::Ipv6Addr;
use std::net::SocketAddrV6;
use thiserror::Error;

pub async fn ip_neighbor_scanner() -> Box<dyn IpNeighborScanner> {
match crate::os::detect_operating_system().await {
Ok(OperatingSystem::Windows) => Box::new(DummyIpNeighborScanner), // TODO
Err(e) => {
log::warn!("Failed to detect operating system: {}", e);
log::info!("Unknown operating system, disabling IP neighbor discovery.");
Box::new(DummyIpNeighborScanner)
}
}
}

#[derive(Error, Debug)]
pub enum IpNeighborScanError {}

Expand All @@ -13,7 +25,7 @@ pub trait IpNeighborScanner {
fn scan(&self) -> BoxFuture<'static, Result<Vec<IpNeighbor>, IpNeighborScanError>>;
}

pub struct DummyIpNeighborScanner;
struct DummyIpNeighborScanner;

impl IpNeighborScanner for DummyIpNeighborScanner {
fn scan(&self) -> BoxFuture<'static, Result<Vec<IpNeighbor>, IpNeighborScanError>> {
Expand Down
42 changes: 42 additions & 0 deletions main/src/os.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::path::PathBuf;
use thiserror::Error;

#[derive(PartialEq, Eq)]
pub enum OperatingSystem {
Windows,
}

#[derive(Error, Debug)]
pub enum OperatingSystemDetectError {
#[error("Error in file system")]
FileSystem(#[from] std::io::Error),

#[error("Unknown operating system")]
UnknownOperatingSystem,
}

pub async fn detect_operating_system() -> Result<OperatingSystem, OperatingSystemDetectError> {
if is_file(&[r"C:\", "Windows", "System32", "ntoskrnl.exe"]).await? {
return Ok(OperatingSystem::Windows);
}
if is_file(&["/", "usr", "bin", "systemctl"]).await? {
return Ok(OperatingSystem::Windows);
}

Err(OperatingSystemDetectError::UnknownOperatingSystem)
}

async fn is_file(path: &[&'static str]) -> std::io::Result<bool> {
let path_buf: PathBuf = path.iter().collect();
Ok(tokio::fs::try_exists(&path_buf).await? && tokio::fs::metadata(&path_buf).await?.is_file())
}

#[cfg(test)]
mod test {
use super::*;

#[tokio::test]
async fn can_detect() {
detect_operating_system().await.expect("OS must be known");
}
}
3 changes: 1 addition & 2 deletions main/src/server.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::network::link_local::DummyIpNeighborScanner;
use crate::network::link_local::IpNeighbor;
use crate::network::link_local::IpNeighborScanError;
use crate::network::link_local::IpNeighborScanner;
Expand Down Expand Up @@ -39,7 +38,7 @@ pub async fn serve(discovery_port: u16, service_port: u16) -> Result<(), ServeEr
TokioMulticastReceiver,
GrpcResponseSender,
TokioUdpSender,
Box::new(DummyIpNeighborScanner),
crate::network::link_local::ip_neighbor_scanner().await,
)
.await
}
Expand Down

0 comments on commit 2052341

Please sign in to comment.