v1.1
This commit is contained in:
@@ -2,15 +2,17 @@ use std::io;
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::command::entity::{DeviceItem, RouteItem, Status};
|
||||
|
||||
pub struct CommandClient {
|
||||
udp: UdpSocket,
|
||||
}
|
||||
|
||||
impl CommandClient {
|
||||
pub fn new() -> io::Result<Self> {
|
||||
let port = crate::config::read_command_port().unwrap();
|
||||
let port = crate::config::read_command_port()?;
|
||||
let udp = UdpSocket::bind("127.0.0.1:0")?;
|
||||
udp.set_read_timeout(Some(Duration::from_secs(5)))?;
|
||||
udp.set_read_timeout(Some(Duration::from_secs(2)))?;
|
||||
udp.connect(SocketAddr::V4(SocketAddrV4::new(
|
||||
Ipv4Addr::new(127, 0, 0, 1),
|
||||
port,
|
||||
@@ -20,16 +22,52 @@ impl CommandClient {
|
||||
}
|
||||
|
||||
impl CommandClient {
|
||||
pub fn list(&self) -> io::Result<String> {
|
||||
pub fn list(&self) -> io::Result<Vec<DeviceItem>> {
|
||||
self.udp.send(b"list")?;
|
||||
let mut buf = [0; 10240];
|
||||
let len = self.udp.recv(&mut buf)?;
|
||||
Ok(String::from_utf8(buf[..len].to_vec()).unwrap())
|
||||
match serde_json::from_slice::<Vec<DeviceItem>>(&buf[..len]) {
|
||||
Ok(val) => {
|
||||
Ok(val)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e);
|
||||
Err(io::Error::new(io::ErrorKind::Other, "data error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn status(&self) -> io::Result<String> {
|
||||
pub fn route(&self) -> io::Result<Vec<RouteItem>> {
|
||||
self.udp.send(b"route")?;
|
||||
let mut buf = [0; 10240];
|
||||
let len = self.udp.recv(&mut buf)?;
|
||||
match serde_json::from_slice::<Vec<RouteItem>>(&buf[..len]) {
|
||||
Ok(val) => {
|
||||
Ok(val)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}",e);
|
||||
Err(io::Error::new(io::ErrorKind::Other, "data error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn status(&self) -> io::Result<Status> {
|
||||
self.udp.send(b"status")?;
|
||||
let mut buf = [0; 10240];
|
||||
let len = self.udp.recv(&mut buf)?;
|
||||
match serde_json::from_slice::<Status>(&buf[..len]) {
|
||||
Ok(val) => {
|
||||
Ok(val)
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?},{:?}",&buf[..len],e);
|
||||
Err(io::Error::new(io::ErrorKind::Other, "data error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn stop(&self) -> io::Result<String> {
|
||||
self.udp.send(b"stop")?;
|
||||
let mut buf = [0; 10240];
|
||||
let len = self.udp.recv(&mut buf)?;
|
||||
Ok(String::from_utf8(buf[..len].to_vec()).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Status {
|
||||
pub name: String,
|
||||
pub virtual_ip: String,
|
||||
pub virtual_gateway: String,
|
||||
pub virtual_netmask: String,
|
||||
pub connect_status: String,
|
||||
pub relay_server: String,
|
||||
pub nat_type: String,
|
||||
pub public_ips: String,
|
||||
pub local_ip: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct RouteItem {
|
||||
pub destination: String,
|
||||
pub next_hop: String,
|
||||
pub metric: String,
|
||||
pub rt: String,
|
||||
pub interface: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct DeviceItem {
|
||||
pub name: String,
|
||||
pub virtual_ip: String,
|
||||
pub nat_type: String,
|
||||
pub public_ips: String,
|
||||
pub local_ip: String,
|
||||
pub nat_traversal_type: String,
|
||||
pub rt: String,
|
||||
pub status: String,
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod client;
|
||||
pub mod server;
|
||||
pub mod entity;
|
||||
|
||||
@@ -3,9 +3,9 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
|
||||
use std::sync::Arc;
|
||||
|
||||
use console::style;
|
||||
use switch::core::Switch;
|
||||
use crate::command::entity::{DeviceItem, RouteItem, Status};
|
||||
|
||||
use switch::handle::{PeerDeviceStatus, RouteType};
|
||||
use switch::Switch;
|
||||
|
||||
pub struct CommandServer {}
|
||||
|
||||
@@ -54,111 +54,137 @@ impl CommandServer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn command_route(switch: &Switch) -> Vec<RouteItem> {
|
||||
let route_table = switch.route_table();
|
||||
let mut route_list = Vec::with_capacity(route_table.len());
|
||||
for (destination, route) in route_table {
|
||||
let next_hop = switch.route_key(&route.route_key()).map_or(String::new(), |v| v.to_string());
|
||||
let metric = route.metric.to_string();
|
||||
let rt = if route.rt < 0 {
|
||||
"".to_string()
|
||||
} else {
|
||||
route.rt.to_string()
|
||||
};
|
||||
let interface = route.addr.to_string();
|
||||
let item = RouteItem {
|
||||
destination: destination.to_string(),
|
||||
next_hop,
|
||||
metric,
|
||||
rt,
|
||||
interface,
|
||||
};
|
||||
route_list.push(item);
|
||||
}
|
||||
route_list
|
||||
}
|
||||
|
||||
pub fn command_list(switch: &Switch) -> Vec<DeviceItem> {
|
||||
let device_list = switch.device_list();
|
||||
let mut list = Vec::new();
|
||||
for peer in device_list {
|
||||
let name = peer.name;
|
||||
let virtual_ip = peer.virtual_ip.to_string();
|
||||
let (nat_type, public_ips, local_ip) = if let Some(nat_info) = switch.peer_nat_info(&peer.virtual_ip) {
|
||||
let nat_type = format!("{:?}", nat_info.nat_type);
|
||||
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
|
||||
let public_ips = public_ips.join(",");
|
||||
let local_ip = nat_info.local_ip.to_string();
|
||||
(nat_type, public_ips, local_ip)
|
||||
} else {
|
||||
("".to_string(), "".to_string(), "".to_string())
|
||||
};
|
||||
let (nat_traversal_type, rt) = if let Some(route) = switch.route(&peer.virtual_ip) {
|
||||
let nat_traversal_type = if route.metric == 1 { "p2p" } else { "relay" }.to_string();
|
||||
let rt = if route.rt < 0 {
|
||||
"".to_string()
|
||||
} else {
|
||||
route.rt.to_string()
|
||||
};
|
||||
(nat_traversal_type, rt)
|
||||
} else {
|
||||
("relay".to_string(), "".to_string())
|
||||
};
|
||||
let status = format!("{:?}", peer.status);
|
||||
let item = DeviceItem {
|
||||
name,
|
||||
virtual_ip,
|
||||
nat_type,
|
||||
public_ips,
|
||||
local_ip,
|
||||
nat_traversal_type,
|
||||
rt,
|
||||
status,
|
||||
};
|
||||
list.push(item);
|
||||
}
|
||||
list
|
||||
}
|
||||
|
||||
pub fn command_status(switch: &Switch) -> Status {
|
||||
let current_device = switch.current_device();
|
||||
let nat_info = switch.nat_info();
|
||||
let name = switch.name().to_string();
|
||||
let virtual_ip = current_device.virtual_ip().to_string();
|
||||
let virtual_gateway = current_device.virtual_gateway().to_string();
|
||||
let virtual_netmask = current_device.virtual_netmask.to_string();
|
||||
let connect_status = format!("{:?}", switch.connection_status());
|
||||
let relay_server = current_device.connect_server.to_string();
|
||||
let nat_type = format!("{:?}", nat_info.nat_type);
|
||||
let public_ips: Vec<String> = nat_info.public_ips.iter().map(|v| v.to_string()).collect();
|
||||
let public_ips = public_ips.join(",");
|
||||
let local_ip = nat_info.local_ip.to_string();
|
||||
Status {
|
||||
name,
|
||||
virtual_ip,
|
||||
virtual_gateway,
|
||||
virtual_netmask,
|
||||
connect_status,
|
||||
relay_server,
|
||||
nat_type,
|
||||
public_ips,
|
||||
local_ip,
|
||||
}
|
||||
}
|
||||
|
||||
fn command(cmd: &str, switch: &Switch) -> io::Result<String> {
|
||||
let mut out_str = String::new();
|
||||
match cmd {
|
||||
"list" => {
|
||||
let server_rt = switch.server_rt();
|
||||
let device_list = switch.device_list();
|
||||
if device_list.is_empty() {
|
||||
return Ok("No other devices found\n".to_string());
|
||||
let out_str = match cmd {
|
||||
"route" => {
|
||||
match serde_json::to_string(&command_route(switch)) {
|
||||
Ok(str) => {
|
||||
str
|
||||
}
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
}
|
||||
for peer_device_info in device_list {
|
||||
let route = switch.route(&peer_device_info.virtual_ip);
|
||||
let str = if peer_device_info.status == PeerDeviceStatus::Online {
|
||||
if route.route_type == RouteType::P2P {
|
||||
let str = if route.rt >= 0 {
|
||||
format!(
|
||||
"[{}] {}(p2p delay:{}ms)\n",
|
||||
peer_device_info.name, peer_device_info.virtual_ip, route.rt
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"[{}] {}(p2p)",
|
||||
peer_device_info.name, peer_device_info.virtual_ip
|
||||
)
|
||||
};
|
||||
style(str).green().to_string()
|
||||
} else {
|
||||
let str = if server_rt >= 0 {
|
||||
format!(
|
||||
"[{}] {}(relay delay:{}ms)\n",
|
||||
peer_device_info.name,
|
||||
peer_device_info.virtual_ip,
|
||||
server_rt * 2
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"[{}] {}(relay)\n",
|
||||
peer_device_info.name, peer_device_info.virtual_ip
|
||||
)
|
||||
};
|
||||
style(str).blue().to_string()
|
||||
}
|
||||
} else {
|
||||
let str = format!(
|
||||
"[{}] {}(Offline)\n",
|
||||
peer_device_info.name, peer_device_info.virtual_ip
|
||||
);
|
||||
style(str).red().to_string()
|
||||
};
|
||||
out_str.push_str(&str);
|
||||
}
|
||||
"list" => {
|
||||
match serde_json::to_string(&command_list(switch)) {
|
||||
Ok(str) => {
|
||||
str
|
||||
}
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
"status" => {
|
||||
let server_rt = switch.server_rt();
|
||||
let current_device = switch.current_device();
|
||||
let str = format!("Virtual ip:{}\n", style(current_device.virtual_ip).green());
|
||||
out_str.push_str(&str);
|
||||
let str = format!(
|
||||
"Virtual gateway:{}\n",
|
||||
style(current_device.virtual_gateway).green()
|
||||
);
|
||||
out_str.push_str(&str);
|
||||
let str = format!(
|
||||
"Connection status :{}\n",
|
||||
style(format!("{:?}", switch.connection_status())).green()
|
||||
);
|
||||
out_str.push_str(&str);
|
||||
let str = format!(
|
||||
"Relay server :{}\n",
|
||||
style(current_device.connect_server).green()
|
||||
);
|
||||
out_str.push_str(&str);
|
||||
if server_rt >= 0 {
|
||||
let str = format!("Delay of relay server :{}ms\n", style(server_rt).green());
|
||||
out_str.push_str(&str);
|
||||
}
|
||||
if let Some(nat_info) = switch.nat_info() {
|
||||
let str = format!(
|
||||
"NAT type :{}",
|
||||
style(format!("{:?}", nat_info.nat_type)).green()
|
||||
);
|
||||
out_str.push_str(&str);
|
||||
match serde_json::to_string(&command_status(switch)) {
|
||||
Ok(str) => {
|
||||
str
|
||||
}
|
||||
Err(e) => {
|
||||
format!("{:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
"help" | "h" => {
|
||||
let str = format!("Options: \n");
|
||||
out_str.push_str(&str);
|
||||
let str = format!(
|
||||
"{} , Query the virtual IP of other devices\n",
|
||||
style("list").green()
|
||||
);
|
||||
out_str.push_str(&str);
|
||||
let str = format!("{} , View current device status\n", style("status").green());
|
||||
out_str.push_str(&str);
|
||||
let str = format!("{} , Exit the program\n", style("exit").green());
|
||||
out_str.push_str(&str);
|
||||
}
|
||||
"exit" => {
|
||||
switch.stop_async();
|
||||
"stop" => {
|
||||
switch.stop()?;
|
||||
"stopping".to_string()
|
||||
}
|
||||
_ => {
|
||||
let str = format!("command '{}' not fount. \n", style(cmd).red());
|
||||
out_str.push_str(&str);
|
||||
let str = format!("Try to enter: '{}'\n", style("help").green());
|
||||
out_str.push_str(&str);
|
||||
format!("command '{}' not fount. \n Try to enter: 'help'\n", cmd)
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(out_str)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user