use crate::common::expr::Expr; use std::io::Read; use std::io::Write; use std::net::TcpStream; use std::process::ExitCode; use std::str; pub const USAGE: &str = " Usage: blom query Sends to the blom server and prints the response to stdout. Examples: $ blom query 'CHILDREN 1.2.3.0/24' 1.2.3.4/26 1.2.3.4/32 $ blom query --raw 'CHILDREN 1.2.3.0/24' +1.2.3.4/26\n +1.2.3.4/32\n $ blom query 'INFO 1.2.3.0/24' Start: 1.2.3.0 End: 1.2.3.255 Size: 256 Parents: 3 Children: 364 Meta: \"{\\\"owner\\\": \\\"acme\\\"}\" Options: -r, --raw Do not parse the response and prints the raw output from the server instead. -v, --verbose Print the request send to the server in addition to the response. -b, --bind Bind to the given ADDRESS:PORT. Default is 0.0.0.0:4902 "; pub fn cmd(args: &[String]) -> ExitCode { let mut addr = "0.0.0.0:4902"; let mut query: Option<&str> = None; let mut arg_index: usize = 0; while arg_index < args.len() { match args[arg_index].as_str() { "--bind" | "-b" => { addr = args .get(arg_index + 1) .expect("Missing address after --bind.") .as_str(); arg_index += 1; } q => { if query.is_some() { println!("Too many arguments."); return ExitCode::FAILURE; } query = Some(q); } } arg_index += 1; } if let Some(q) = query { handle_query(addr, q); return ExitCode::SUCCESS; } println!("Missing query."); ExitCode::FAILURE } fn handle_query(addr: &str, query: &str) { let expr = Expr::from_query(query).encode(); match TcpStream::connect(addr) { Ok(mut stream) => { let _ = stream.write(&expr).unwrap(); let mut data = [0u8; 64]; match stream.read(&mut data) { Ok(_) => { let resp = str::from_utf8(&data).unwrap(); println!("{resp:?}"); } Err(e) => println!("Read failure: {e:?}"), } } Err(e) => println!("Connection failure: {e:?}"), } }