//! Rhai wrappers for network module functions //! //! This module provides Rhai wrappers for network connectivity functions. use rhai::{Engine, EvalAltResult, Module}; /// Create a Rhai module with network functions pub fn create_module() -> Module { // For now, we'll use a simpler approach and register functions via engine // This ensures compatibility with Rhai's type system // The module is created but functions are registered through register_net_module Module::new() } /// Register network module functions with the Rhai engine pub fn register_net_module(engine: &mut Engine) -> Result<(), Box> { // TCP functions engine.register_fn("tcp_check", tcp_check); engine.register_fn("tcp_ping", tcp_ping); // HTTP functions engine.register_fn("http_check", http_check); engine.register_fn("http_status", http_status); // SSH functions engine.register_fn("ssh_execute", ssh_execute); engine.register_fn("ssh_execute_output", ssh_execute_output); engine.register_fn("ssh_ping", ssh_ping_host); Ok(()) } /// Check if a TCP port is open pub fn tcp_check(host: &str, port: i64) -> bool { // Use std::net::TcpStream for synchronous connection test use std::net::{SocketAddr, TcpStream}; use std::time::Duration; // Parse the address let addr_str = format!("{}:{}", host, port); if let Ok(socket_addr) = addr_str.parse::() { // Try to connect with a timeout TcpStream::connect_timeout(&socket_addr, Duration::from_secs(5)).is_ok() } else { // Try to resolve hostname first match std::net::ToSocketAddrs::to_socket_addrs(&addr_str) { Ok(mut addrs) => { if let Some(addr) = addrs.next() { TcpStream::connect_timeout(&addr, Duration::from_secs(5)).is_ok() } else { false } } Err(_) => false, } } } /// Ping a host using ICMP (cross-platform) pub fn tcp_ping(host: &str) -> bool { // Use system ping command for synchronous operation use std::process::Command; // Cross-platform ping implementation let mut cmd = Command::new("ping"); #[cfg(target_os = "windows")] { cmd.arg("-n").arg("1").arg("-w").arg("5000"); // Windows: -n count, -w timeout in ms } #[cfg(not(target_os = "windows"))] { cmd.arg("-c").arg("1").arg("-W").arg("5"); // Unix: -c count, -W timeout in seconds } cmd.arg(host); match cmd.output() { Ok(output) => output.status.success(), Err(_) => false, } } /// Check if an HTTP URL is reachable pub fn http_check(url: &str) -> bool { use std::time::Duration; // Create a blocking HTTP client with timeout let client = match reqwest::blocking::Client::builder() .timeout(Duration::from_secs(10)) .build() { Ok(client) => client, Err(_) => return false, }; // Try to make a HEAD request match client.head(url).send() { Ok(response) => response.status().is_success(), Err(_) => false, } } /// Get HTTP status code from a URL pub fn http_status(url: &str) -> i64 { use std::time::Duration; // Create a blocking HTTP client with timeout let client = match reqwest::blocking::Client::builder() .timeout(Duration::from_secs(10)) .build() { Ok(client) => client, Err(_) => return -1, }; // Try to make a HEAD request match client.head(url).send() { Ok(response) => response.status().as_u16() as i64, Err(_) => -1, } } /// Execute a command via SSH - returns exit code as i64 pub fn ssh_execute(host: &str, user: &str, command: &str) -> i64 { use std::process::Command; let mut cmd = Command::new("ssh"); cmd.arg("-o") .arg("ConnectTimeout=5") .arg("-o") .arg("StrictHostKeyChecking=no") .arg(format!("{}@{}", user, host)) .arg(command); match cmd.output() { Ok(output) => output.status.code().unwrap_or(-1) as i64, Err(_) => -1, } } /// Execute a command via SSH and get output - returns output as string pub fn ssh_execute_output(host: &str, user: &str, command: &str) -> String { use std::process::Command; let mut cmd = Command::new("ssh"); cmd.arg("-o") .arg("ConnectTimeout=5") .arg("-o") .arg("StrictHostKeyChecking=no") .arg(format!("{}@{}", user, host)) .arg(command); match cmd.output() { Ok(output) => String::from_utf8_lossy(&output.stdout).to_string(), Err(_) => "SSH command failed".to_string(), } } /// Test SSH connectivity to a host pub fn ssh_ping_host(host: &str, user: &str) -> bool { use std::process::Command; let mut cmd = Command::new("ssh"); cmd.arg("-o") .arg("ConnectTimeout=5") .arg("-o") .arg("StrictHostKeyChecking=no") .arg("-o") .arg("BatchMode=yes") // Non-interactive .arg(format!("{}@{}", user, host)) .arg("echo 'Connection successful'"); match cmd.output() { Ok(output) => output.status.success(), Err(_) => false, } }