First
This commit is contained in:
131
src/client.rs
Normal file
131
src/client.rs
Normal file
@@ -0,0 +1,131 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Args;
|
||||
use ipnet::Ipv4Net;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
net::tcp::{OwnedReadHalf, OwnedWriteHalf},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use crate::router::{CLIENT_REGISTER_TIMEOUT, CliRegMessages, RouterMessages, SERVER_PACKET_SIZE};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Args)]
|
||||
pub struct ClientCfg {
|
||||
/// The server endpoint to connect to in host:port or ip:port format.
|
||||
#[arg(long, short)]
|
||||
pub server: String,
|
||||
|
||||
/// The local interface IP address (example: 10.8.0.2).
|
||||
#[arg(long = "interface-ip")]
|
||||
pub interface_ip: IpAddr,
|
||||
|
||||
/// The local interface name.
|
||||
#[arg(long = "interface-name", default_value = "xvpn0")]
|
||||
pub interface_name: String,
|
||||
|
||||
/// Local routes in CIDR format.
|
||||
/// Example: --local-route 1.1.1.1/32,10.0.0.0/24
|
||||
#[arg(long = "local-route", visible_alias = "lr", value_delimiter = ',')]
|
||||
pub local_routes: Vec<Ipv4Net>,
|
||||
}
|
||||
|
||||
pub async fn start(config: ClientCfg) -> Result<()> {
|
||||
println!("Starting client with config: {:?}", config);
|
||||
|
||||
let stream = tokio::net::TcpStream::connect(&config.server).await?;
|
||||
//stream.set_nodelay(true)?;
|
||||
let (mut rx, mut tx) = stream.into_split();
|
||||
// let client_stream = ClientStream::new(tx);
|
||||
|
||||
let mut buf = vec![0u8; SERVER_PACKET_SIZE];
|
||||
register_client(&mut rx, &mut tx, config, &mut buf).await?;
|
||||
|
||||
println!("Client registration successful. Entering main loop to receive messages from router...");
|
||||
loop {
|
||||
tokio::select! {
|
||||
msg = rx.read(&mut buf) => {
|
||||
match msg {
|
||||
Ok(0) => {
|
||||
println!("Connection to router closed by peer.");
|
||||
return Ok(());
|
||||
}
|
||||
Ok(n) => {
|
||||
println!("Received {} bytes from router: {:?}", n, RouterMessages::from_slice(&buf[..n]));
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from router: {}", e);
|
||||
return Err(anyhow::anyhow!(format!("Error reading from router: {}", e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ok(())
|
||||
}
|
||||
|
||||
pub async fn register_client(
|
||||
rx: &mut OwnedReadHalf,
|
||||
tx: &mut OwnedWriteHalf,
|
||||
config: ClientCfg,
|
||||
buf: &mut [u8],
|
||||
) -> Result<()> {
|
||||
let register_msg = RouterMessages::CliReg(CliRegMessages::Reg(config));
|
||||
let mut client_registration_timeout =
|
||||
tokio::time::interval_at(Instant::now() + CLIENT_REGISTER_TIMEOUT, CLIENT_REGISTER_TIMEOUT);
|
||||
tx.write_all(®ister_msg.to_bytes()).await?;
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
msg = rx.read(buf) => {
|
||||
match msg {
|
||||
Ok(0) => {
|
||||
let msg = "Connection closed by router while waiting for registration confirmation.";
|
||||
eprintln!("{}", msg);
|
||||
return Err(anyhow::anyhow!(msg));
|
||||
}
|
||||
Ok(n) => {
|
||||
let response = RouterMessages::from_slice(&buf[..n]);
|
||||
println!("Received registration response from router: {:?}", response);
|
||||
match response {
|
||||
RouterMessages::CliReg(CliRegMessages::RegOk(uuid)) => {
|
||||
println!("Client registration successful with UUID: {}", uuid);
|
||||
return Ok(());
|
||||
}
|
||||
RouterMessages::CliReg(CliRegMessages::RegFailed(err_msg)) => {
|
||||
eprintln!("Client registration failed: {}", err_msg);
|
||||
return Err(anyhow::anyhow!(format!("Client registration failed: {}", err_msg)));
|
||||
}
|
||||
_ => {
|
||||
let msg = "Unexpected message type received during client registration.";
|
||||
eprintln!("{}", msg);
|
||||
return Err(anyhow::anyhow!(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from router during client registration: {}", e);
|
||||
return Err(anyhow::anyhow!(format!("Error reading from router: {}", e)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
_= client_registration_timeout.tick() => {
|
||||
let msg = "Client registration timed out waiting for confirmation from router.";
|
||||
eprintln!("{}", msg);
|
||||
eprintln!("Closing connection with Server");
|
||||
tx.shutdown().await?;
|
||||
return Err(anyhow::anyhow!(msg));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
// Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user