From b261d7ba4a35752836711d98ea9fcd7e1a234f3a Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Thu, 9 Dec 2021 16:21:14 +0000 Subject: [PATCH] :recycle: refactor: refactor the client a lot so I can reuse its code for new subcommands --- src/client.rs | 130 ++++++++++++++++++++++++++++--------------------- src/main.rs | 2 +- src/message.rs | 25 +++++----- src/prelude.rs | 6 +++ 4 files changed, 95 insertions(+), 68 deletions(-) diff --git a/src/client.rs b/src/client.rs index e394b5d..91202cb 100644 --- a/src/client.rs +++ b/src/client.rs @@ -5,66 +5,22 @@ struct ServerResponse { nickname: Option , } -pub async fn client > (mut args: I) -> Result <(), AppError> { - use rand::RngCore; +struct ClientParams { + common: app_common::Params, + bind_addrs: Vec , + timeout_ms: u64, +} + +pub async fn client > (args: I) -> Result <(), AppError> { + let params = configure_client (args)?; + let socket = make_socket (¶ms).await?; + let msg = Message::new_request1 ().to_vec ()?; - let common_params = app_common::Params::default (); - let mut bind_addrs = vec! []; - let mut timeout_ms = 500; - - while let Some (arg) = args.next () { - match arg.as_str () { - "--bind-addr" => { - bind_addrs.push (match args.next () { - None => return Err (CliArgError::MissingArgumentValue (arg).into ()), - Some (x) => Ipv4Addr::from_str (&x)?, - }); - }, - "--timeout-ms" => { - timeout_ms = match args.next () { - None => return Err (CliArgError::MissingArgumentValue (arg).into ()), - Some (x) => u64::from_str (&x)?, - }; - }, - _ => return Err (CliArgError::UnrecognizedArgument (arg).into ()), - } - } - - if bind_addrs.is_empty () { - bind_addrs = get_ips ()?; - } - - let socket = UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, 0)).await?; - - for bind_addr in bind_addrs { - if let Err (e) = socket.join_multicast_v4 (common_params.multicast_addr, bind_addr) { - println! ("Error joining multicast group with iface {}: {:?}", bind_addr, e); - } - } - - let mut idem_id = [0u8; 8]; - rand::thread_rng ().fill_bytes (&mut idem_id); - - let msg = Message::Request1 { - idem_id, - mac: None, - }.to_vec ()?; - - let socket = Arc::new (socket); - let socket2 = Arc::clone (&socket); - - tokio::spawn (async move { - for _ in 0..10 { - socket2.send_to (&msg, (common_params.multicast_addr, common_params.server_port)).await?; - sleep (Duration::from_millis (100)).await; - } - - Ok::<_, AppError> (()) - }); + tokio::spawn (send_requests (Arc::clone (&socket), params.common, msg)); let mut peers = HashMap::with_capacity (10); - timeout (Duration::from_millis (timeout_ms), listen_for_responses (&*socket, &mut peers)).await.ok (); + timeout (Duration::from_millis (params.timeout_ms), listen_for_responses (&*socket, &mut peers)).await.ok (); let mut peers: Vec <_> = peers.into_iter ().collect (); peers.sort_by_key (|(_, v)| v.mac); @@ -93,6 +49,68 @@ pub async fn client > (mut args: I) -> Result <(), Ap Ok (()) } +fn configure_client > (mut args: I) +-> Result +{ + let mut bind_addrs = vec! []; + let mut timeout_ms = 500; + + while let Some (arg) = args.next () { + match arg.as_str () { + "--bind-addr" => { + bind_addrs.push (match args.next () { + None => return Err (CliArgError::MissingArgumentValue (arg).into ()), + Some (x) => Ipv4Addr::from_str (&x)?, + }); + }, + "--timeout-ms" => { + timeout_ms = match args.next () { + None => return Err (CliArgError::MissingArgumentValue (arg).into ()), + Some (x) => u64::from_str (&x)?, + }; + }, + _ => return Err (CliArgError::UnrecognizedArgument (arg).into ()), + } + } + + if bind_addrs.is_empty () { + bind_addrs = get_ips ()?; + } + + Ok (ClientParams { + common: Default::default (), + bind_addrs, + timeout_ms, + }) +} + +async fn make_socket (params: &ClientParams) -> Result , AppError> { + let socket = UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, 0)).await?; + + for bind_addr in ¶ms.bind_addrs { + if let Err (e) = socket.join_multicast_v4 (params.common.multicast_addr, *bind_addr) { + println! ("Error joining multicast group with iface {}: {:?}", bind_addr, e); + } + } + + Ok (Arc::new (socket)) +} + +async fn send_requests ( + socket: Arc , + params: app_common::Params, + msg: Vec , +) +-> Result <(), AppError> +{ + for _ in 0..10 { + socket.send_to (&msg, (params.multicast_addr, params.server_port)).await?; + sleep (Duration::from_millis (100)).await; + } + + Ok::<_, AppError> (()) +} + async fn listen_for_responses ( socket: &UdpSocket, peers: &mut HashMap diff --git a/src/main.rs b/src/main.rs index d429ca8..1412bad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ mod ip; pub mod message; mod prelude; mod server; -mod tlv; +pub mod tlv; fn main () -> Result <(), AppError> { let rt = tokio::runtime::Builder::new_current_thread () diff --git a/src/message.rs b/src/message.rs index 85b782f..83ecfdb 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,13 +1,4 @@ -use std::{ - io::{ - Cursor, - Write, - }, -}; - -use crate::tlv; - -use thiserror::Error; +use crate::prelude::*; const MAGIC_NUMBER: [u8; 4] = [0x9a, 0x4a, 0x43, 0x81]; pub const PACKET_SIZE: usize = 1024; @@ -27,13 +18,25 @@ pub enum Message { Response2 (Response2), } +impl Message { + pub fn new_request1 () -> Message { + let mut idem_id = [0u8; 8]; + rand::thread_rng ().fill_bytes (&mut idem_id); + + Message::Request1 { + idem_id, + mac: None, + } + } +} + #[derive (Debug, PartialEq)] pub struct Response2 { pub idem_id: [u8; 8], pub nickname: String, } -#[derive (Debug, Error)] +#[derive (Debug, thiserror::Error)] pub enum MessageError { #[error (transparent)] Io (#[from] std::io::Error), diff --git a/src/prelude.rs b/src/prelude.rs index c4b83b1..7c35294 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,6 +1,10 @@ pub use std::{ collections::HashMap, env, + io::{ + Cursor, + Write, + }, net::{ Ipv4Addr, SocketAddr, @@ -18,6 +22,7 @@ pub use mac_address::{ MacAddress, get_mac_address, }; +pub use rand::RngCore; pub use tokio::{ net::UdpSocket, time::{ @@ -39,4 +44,5 @@ pub use crate::{ PACKET_SIZE, Message, }, + tlv, };