➕ add `my-ips` impl for Linux and refactor it into a module
							parent
							
								
									cf283a2eaa
								
							
						
					
					
						commit
						2b4695934e
					
				|  | @ -0,0 +1,62 @@ | ||||||
|  | use std::{ | ||||||
|  | 	net::Ipv4Addr, | ||||||
|  | 	process::Command, | ||||||
|  | 	str::FromStr, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use crate::AppError; | ||||||
|  | 
 | ||||||
|  | pub fn get_ip_addr_output () -> Result <String, AppError> { | ||||||
|  | 	let output = Command::new ("ip") | ||||||
|  | 	.arg ("addr") | ||||||
|  | 	.output ()?; | ||||||
|  | 	let output = output.stdout.as_slice (); | ||||||
|  | 	let output = String::from_utf8 (output.to_vec ())?; | ||||||
|  | 	Ok (output) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn parse_ip_addr_output (output: &str) -> Vec <Ipv4Addr> { | ||||||
|  | 	// I wrote this in FP style because I was bored.
 | ||||||
|  | 	
 | ||||||
|  | 	output.lines () 
 | ||||||
|  | 	.map (|l| l.trim_start ()) | ||||||
|  | 	.filter_map (|l| l.strip_prefix ("inet ")) | ||||||
|  | 	.filter_map (|l| l.find ('/').map (|x| &l [0..x])) | ||||||
|  | 	.filter_map (|l| Ipv4Addr::from_str (l).ok ()) | ||||||
|  | 	.collect () | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn get_ip_config_output () -> Result <String, AppError> { | ||||||
|  | 	let output = Command::new ("ipconfig") | ||||||
|  | 	.output ()?; | ||||||
|  | 	let output = output.stdout.as_slice (); | ||||||
|  | 	let output = String::from_utf8 (output.to_vec ())?; | ||||||
|  | 	Ok (output) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn parse_ip_config_output (output: &str) -> Vec <Ipv4Addr> { | ||||||
|  | 	let mut addrs = vec! []; | ||||||
|  | 	
 | ||||||
|  | 	for line in output.lines () { | ||||||
|  | 		let line = line.trim_start (); | ||||||
|  | 		
 | ||||||
|  | 		// Maybe only works on English locales?
 | ||||||
|  | 		if ! line.starts_with ("IPv4 Address") { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		let colon_pos = match line.find (':') { | ||||||
|  | 			None => continue, | ||||||
|  | 			Some (x) => x, | ||||||
|  | 		}; | ||||||
|  | 		let line = &line [colon_pos + 2..]; | ||||||
|  | 		
 | ||||||
|  | 		let addr = match Ipv4Addr::from_str (line) { | ||||||
|  | 			Err (_) => continue, | ||||||
|  | 			Ok (x) => x, | ||||||
|  | 		}; | ||||||
|  | 		
 | ||||||
|  | 		addrs.push (addr); | ||||||
|  | 	} | ||||||
|  | 	
 | ||||||
|  | 	addrs | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										53
									
								
								src/main.rs
								
								
								
								
							|  | @ -17,6 +17,7 @@ use mac_address::{ | ||||||
| }; | }; | ||||||
| use thiserror::Error; | use thiserror::Error; | ||||||
| 
 | 
 | ||||||
|  | mod ip; | ||||||
| mod message; | mod message; | ||||||
| mod tlv; | mod tlv; | ||||||
| 
 | 
 | ||||||
|  | @ -26,12 +27,14 @@ use message::{ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #[derive (Debug, Error)] | #[derive (Debug, Error)] | ||||||
| enum AppError { | pub enum AppError { | ||||||
| 	#[error (transparent)] | 	#[error (transparent)] | ||||||
| 	AddrParse (#[from] std::net::AddrParseError), | 	AddrParse (#[from] std::net::AddrParseError), | ||||||
| 	#[error (transparent)] | 	#[error (transparent)] | ||||||
| 	CliArgs (#[from] CliArgError), | 	CliArgs (#[from] CliArgError), | ||||||
| 	#[error (transparent)] | 	#[error (transparent)] | ||||||
|  | 	FromUtf8 (#[from] std::string::FromUtf8Error), | ||||||
|  | 	#[error (transparent)] | ||||||
| 	Io (#[from] std::io::Error), | 	Io (#[from] std::io::Error), | ||||||
| 	#[error (transparent)] | 	#[error (transparent)] | ||||||
| 	MacAddr (#[from] mac_address::MacAddressError), | 	MacAddr (#[from] mac_address::MacAddressError), | ||||||
|  | @ -44,7 +47,7 @@ enum AppError { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive (Debug, Error)] | #[derive (Debug, Error)] | ||||||
| enum CliArgError { | pub enum CliArgError { | ||||||
| 	#[error ("Missing value for argument `{0}`")] | 	#[error ("Missing value for argument `{0}`")] | ||||||
| 	MissingArgumentValue (String), | 	MissingArgumentValue (String), | ||||||
| 	#[error ("First argument should be a subcommand")] | 	#[error ("First argument should be a subcommand")] | ||||||
|  | @ -100,7 +103,15 @@ fn main () -> Result <(), AppError> { | ||||||
| 
 | 
 | ||||||
| #[cfg(target_os = "linux")] | #[cfg(target_os = "linux")] | ||||||
| fn my_ips () -> Result <(), AppError> { | fn my_ips () -> Result <(), AppError> { | ||||||
| 	println! ("my-ips subcommand not implemented for linux yet"); | 	let output = ip::get_ip_addr_output ()?; | ||||||
|  | 	
 | ||||||
|  | 	for addr in ip::parse_ip_addr_output (&output) | ||||||
|  | 	.iter () | ||||||
|  | 	.filter (|a| ! a.is_loopback ()) | ||||||
|  | 	{ | ||||||
|  | 		println! ("{:?}", addr); | ||||||
|  | 	} | ||||||
|  | 	
 | ||||||
| 	Ok (()) | 	Ok (()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -112,47 +123,15 @@ fn my_ips () -> Result <(), AppError> { | ||||||
| 
 | 
 | ||||||
| #[cfg(target_os = "windows")] | #[cfg(target_os = "windows")] | ||||||
| fn my_ips () -> Result <(), AppError> { | fn my_ips () -> Result <(), AppError> { | ||||||
| 	use std::process::Command; | 	let output = ip::get_ip_config_output ()?; | ||||||
| 	
 | 	
 | ||||||
| 	let output = Command::new ("ipconfig") | 	for addr in ip::parse_ip_config_output (&output) { | ||||||
| 	.output ()?; |  | ||||||
| 	let output = output.stdout.as_slice (); |  | ||||||
| 	let output = std::str::from_utf8 (output)?; |  | ||||||
| 	
 |  | ||||||
| 	for addr in parse_ip_config_output (output) { |  | ||||||
| 		println! ("{:?}", addr); | 		println! ("{:?}", addr); | ||||||
| 	} | 	} | ||||||
| 	
 | 	
 | ||||||
| 	Ok (()) | 	Ok (()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn parse_ip_config_output (output: &str) -> Vec <Ipv4Addr> { |  | ||||||
| 	let mut addrs = vec! []; |  | ||||||
| 	
 |  | ||||||
| 	for line in output.lines () { |  | ||||||
| 		let line = line.trim_start (); |  | ||||||
| 		
 |  | ||||||
| 		// Maybe only works on English locales?
 |  | ||||||
| 		if ! line.starts_with ("IPv4 Address") { |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 		let colon_pos = match line.find (":") { |  | ||||||
| 			None => continue, |  | ||||||
| 			Some (x) => x, |  | ||||||
| 		}; |  | ||||||
| 		let line = &line [colon_pos + 2..]; |  | ||||||
| 		
 |  | ||||||
| 		let addr = match Ipv4Addr::from_str (line) { |  | ||||||
| 			Err (_) => continue, |  | ||||||
| 			Ok (x) => x, |  | ||||||
| 		}; |  | ||||||
| 		
 |  | ||||||
| 		addrs.push (addr); |  | ||||||
| 	} |  | ||||||
| 	
 |  | ||||||
| 	addrs |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct ServerResponse { | struct ServerResponse { | ||||||
| 	mac: Option <[u8; 6]>, | 	mac: Option <[u8; 6]>, | ||||||
| 	nickname: Option <String>, | 	nickname: Option <String>, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 _
						_