Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run
- Add new sal-net package to the workspace. - Update MONOREPO_CONVERSION_PLAN.md to reflect the addition of the sal-net package and mark it as production-ready. - Add Cargo.toml and README.md for the sal-net package.
181 lines
5.1 KiB
Rust
181 lines
5.1 KiB
Rust
//! 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<EvalAltResult>> {
|
|
// 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::<SocketAddr>() {
|
|
// 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,
|
|
}
|
|
}
|