mirror of
https://github.com/cubixle/radius-rs.git
synced 2026-04-24 22:54:43 +01:00
Add client impl
This commit is contained in:
69
src/client.rs
Normal file
69
src/client.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use thiserror::Error;
|
||||
use tokio::net::UdpSocket;
|
||||
|
||||
use crate::client::ClientError::{FailedConnection, FailedParsingUDPResponse, FailedRadiusPacketEncoding, FailedReceivingResponse, FailedSendingPacket, FailedUdpSocketBinding};
|
||||
use crate::packet::Packet;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ClientError {
|
||||
#[error("failed to bind a UDP socket => `{0}`")]
|
||||
FailedUdpSocketBinding(String),
|
||||
#[error("failed to connect to `{0}` => `{1}`")]
|
||||
FailedConnection(String, String),
|
||||
#[error("failed to encode a RADIUS request => `{0}`")]
|
||||
FailedRadiusPacketEncoding(String),
|
||||
#[error("failed to send a UDP datagram to `{0}` => `{1}`")]
|
||||
FailedSendingPacket(String, String),
|
||||
#[error("failed to receive the UDP response from `{0}` => `{1}`")]
|
||||
FailedReceivingResponse(String, String),
|
||||
#[error("failed to parse a UDP response into a RADIUS packet => `{0}`")]
|
||||
FailedParsingUDPResponse(String),
|
||||
}
|
||||
|
||||
pub struct Client {}
|
||||
|
||||
impl Client {
|
||||
const MAX_DATAGRAM_SIZE: usize = 65507;
|
||||
|
||||
pub async fn send_packet(remote_addr: &SocketAddr, request_packet: &Packet) -> Result<Packet, ClientError> {
|
||||
// TODO retransmission
|
||||
|
||||
let local_addr: SocketAddr = if remote_addr.is_ipv4() {
|
||||
"0.0.0.0:0"
|
||||
} else {
|
||||
"[::]:0"
|
||||
}.parse().unwrap();
|
||||
|
||||
let conn = match UdpSocket::bind(local_addr).await {
|
||||
Ok(conn) => conn,
|
||||
Err(e) => return Err(FailedUdpSocketBinding(e.to_string())),
|
||||
};
|
||||
match conn.connect(remote_addr).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => return Err(FailedConnection(remote_addr.to_string(), e.to_string()))
|
||||
};
|
||||
|
||||
let request_data = match request_packet.encode() {
|
||||
Ok(encoded) => encoded,
|
||||
Err(e) => return Err(FailedRadiusPacketEncoding(e.to_string()))
|
||||
};
|
||||
|
||||
match conn.send(request_data.as_slice()).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => return Err(FailedSendingPacket(remote_addr.to_string(), e.to_string()))
|
||||
};
|
||||
|
||||
let mut buf = vec![0; Self::MAX_DATAGRAM_SIZE];
|
||||
let len = match conn.recv(&mut buf).await {
|
||||
Ok(len) => len,
|
||||
Err(e) => return Err(FailedReceivingResponse(remote_addr.to_string(), e.to_string()))
|
||||
};
|
||||
|
||||
match Packet::parse(&buf[..len].to_vec(), request_packet.get_secret()) {
|
||||
Ok(response_packet) => Ok(response_packet),
|
||||
Err(e) => Err(FailedParsingUDPResponse(e.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,4 @@ pub mod server;
|
||||
pub mod secret_provider;
|
||||
pub mod request_handler;
|
||||
pub mod request;
|
||||
pub mod client;
|
||||
|
||||
@@ -29,10 +29,14 @@ impl Packet {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_identifier(&self) -> u8 {
|
||||
pub fn get_identifier(&self) -> u8 {
|
||||
self.identifier
|
||||
}
|
||||
|
||||
pub fn get_secret(&self) -> &Vec<u8> {
|
||||
&self.secret
|
||||
}
|
||||
|
||||
pub fn parse(bs: &Vec<u8>, secret: &Vec<u8>) -> Result<Self, String> {
|
||||
if bs.len() < 20 {
|
||||
return Err("radius packet doesn't have enough length of bytes; that has to be at least 20 bytes".to_owned());
|
||||
|
||||
@@ -118,6 +118,7 @@ impl Server {
|
||||
Err(e) => {
|
||||
error!("failed to parse given request data to pack into the RADIUS packet; {}", e);
|
||||
debug!("failed request data => {:?}", request_data);
|
||||
// TODO error handler?
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user