Compare commits
	
		
			No commits in common. "ed58df2e6be62cdde3638650f32f6c042ecd8455" and "a0a64cd79c7633bf0f602f3c011b4864871c41b0" have entirely different histories. 
		
	
	
		
			ed58df2e6b
			...
			a0a64cd79c
		
	
		| 
						 | 
					@ -26,32 +26,6 @@ version = "1.0.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 | 
					checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "configparser"
 | 
					 | 
				
			||||||
version = "3.0.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "06821ea598337a8412cf47c5b71c3bc694a7f0aed188ac28b836fab164a2c202"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "directories"
 | 
					 | 
				
			||||||
version = "4.0.1"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "dirs-sys",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "dirs-sys"
 | 
					 | 
				
			||||||
version = "0.3.6"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "libc",
 | 
					 | 
				
			||||||
 "redox_users",
 | 
					 | 
				
			||||||
 "winapi",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "getrandom"
 | 
					name = "getrandom"
 | 
				
			||||||
version = "0.2.3"
 | 
					version = "0.2.3"
 | 
				
			||||||
| 
						 | 
					@ -80,10 +54,8 @@ dependencies = [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "lookaround"
 | 
					name = "lookaround"
 | 
				
			||||||
version = "0.1.6"
 | 
					version = "0.1.5"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "configparser",
 | 
					 | 
				
			||||||
 "directories",
 | 
					 | 
				
			||||||
 "mac_address",
 | 
					 "mac_address",
 | 
				
			||||||
 "rand",
 | 
					 "rand",
 | 
				
			||||||
 "thiserror",
 | 
					 "thiserror",
 | 
				
			||||||
| 
						 | 
					@ -223,25 +195,6 @@ dependencies = [
 | 
				
			||||||
 "rand_core",
 | 
					 "rand_core",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "redox_syscall"
 | 
					 | 
				
			||||||
version = "0.2.10"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "bitflags",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "redox_users"
 | 
					 | 
				
			||||||
version = "0.4.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "getrandom",
 | 
					 | 
				
			||||||
 "redox_syscall",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "syn"
 | 
					name = "syn"
 | 
				
			||||||
version = "1.0.82"
 | 
					version = "1.0.82"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,11 +9,9 @@ license = "AGPL-3.0"
 | 
				
			||||||
name = "lookaround"
 | 
					name = "lookaround"
 | 
				
			||||||
readme = "README.md"
 | 
					readme = "README.md"
 | 
				
			||||||
repository = "https://six-five-six-four.com/git/reactor/lookaround"
 | 
					repository = "https://six-five-six-four.com/git/reactor/lookaround"
 | 
				
			||||||
version = "0.1.6"
 | 
					version = "0.1.5"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
configparser = "3.0.0"
 | 
					 | 
				
			||||||
directories = "4.0.1"
 | 
					 | 
				
			||||||
mac_address = "1.1.2"
 | 
					mac_address = "1.1.2"
 | 
				
			||||||
rand = "0.8.4"
 | 
					rand = "0.8.4"
 | 
				
			||||||
thiserror = "1.0.30"
 | 
					thiserror = "1.0.30"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										53
									
								
								README.md
								
								
								
								
							
							
						
						
									
										53
									
								
								README.md
								
								
								
								
							| 
						 | 
					@ -19,48 +19,29 @@ Found 3 peers:
 | 
				
			||||||
LookAround is a Rust program for looking up your computers' MAC and IP addresses
 | 
					LookAround is a Rust program for looking up your computers' MAC and IP addresses
 | 
				
			||||||
within a LAN. There's no central server, so it's not a look-up, it's a look-around.
 | 
					within a LAN. There's no central server, so it's not a look-up, it's a look-around.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Installing
 | 
					The client uses IP multicast to find servers within the
 | 
				
			||||||
 | 
					same multicast domain, similar to Avahi and Bonjour.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Make sure Cargo is installed from [RustUp.](https://rustup.rs/)
 | 
					Systems self-identify by MAC address and nicknames. Public keys with
 | 
				
			||||||
 | 
					TOFU semantics are intended before v1.0.0.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use the Cargo package manager from [Rust](https://rustup.rs/) to install LookAround.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# Install LookAround with Cargo
 | 
					 | 
				
			||||||
cargo install lookaround
 | 
					cargo install lookaround
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Find your config directory
 | 
					 | 
				
			||||||
# Prints something like `Using config dir "/home/user/.config/lookaround"`
 | 
					 | 
				
			||||||
lookaround config
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Create the files `client.ini` and/or `server.ini` in that directory
 | 
					To auto-start the server as a normal user. 
 | 
				
			||||||
(e.g. /home/user/.config/lookaround/server.ini)
 | 
					put this systemd unit in `~/.config/systemd/user/lookaround.service`:
 | 
				
			||||||
 | 
					 | 
				
			||||||
```ini
 | 
					 | 
				
			||||||
# Clients can store MAC-nickname pairs in client.ini, like a hosts file.
 | 
					 | 
				
			||||||
# This is useful if your servers are short-lived and you want the clients
 | 
					 | 
				
			||||||
# to be the source of truth for nicknames.
 | 
					 | 
				
			||||||
[nicknames]
 | 
					 | 
				
			||||||
11-11-11-11-11-11 = laptop
 | 
					 | 
				
			||||||
22-22-22-22-22-22 = desktop
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```ini
 | 
					 | 
				
			||||||
# Long-lived servers can have their nickname configured in server.ini
 | 
					 | 
				
			||||||
[server]
 | 
					 | 
				
			||||||
nickname = my-computer
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Auto-Start (Linux)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Put this systemd unit in `~/.config/systemd/user/lookaround.service`:
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
```ini
 | 
					```ini
 | 
				
			||||||
[Unit]
 | 
					[Unit]
 | 
				
			||||||
Description=LookAround
 | 
					Description=LookAround
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[Service]
 | 
					[Service]
 | 
				
			||||||
ExecStart=/home/user/.cargo/bin/lookaround server
 | 
					ExecStart=/home/user/.cargo/bin/lookaround server --nickname my-desktop
 | 
				
			||||||
Restart=always
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
[Install]
 | 
					[Install]
 | 
				
			||||||
WantedBy=default.target
 | 
					WantedBy=default.target
 | 
				
			||||||
| 
						 | 
					@ -75,19 +56,11 @@ systemctl --user status lookaround
 | 
				
			||||||
systemctl --user enable lookaround
 | 
					systemctl --user enable lookaround
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Auto-Start (Windows)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
(untested)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Create a shortcut to the LookAround exe
 | 
					 | 
				
			||||||
- Change the shortcut's target to end in `lookaround.exe server` so it will run the server
 | 
					 | 
				
			||||||
- Cut-paste the shortcut into the Startup folder in `C:\ProgramData\somewhere`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Usage
 | 
					## Usage
 | 
				
			||||||
Run the server manually: (To test before installing)
 | 
					Run the server manually: (If you didn't configure auto-start)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
lookaround server --nickname my-computer
 | 
					lookaround server --nickname my-desktop
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
On a client computer:
 | 
					On a client computer:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,5 @@
 | 
				
			||||||
use crate::prelude::*;
 | 
					use crate::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const LOOKAROUND_VERSION: &'static str = env! ("CARGO_PKG_VERSION");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn find_project_dirs () -> Option <ProjectDirs> {
 | 
					 | 
				
			||||||
	ProjectDirs::from ("", "ReactorScram", "LookAround")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive (Debug, thiserror::Error)]
 | 
					#[derive (Debug, thiserror::Error)]
 | 
				
			||||||
pub enum AppError {
 | 
					pub enum AppError {
 | 
				
			||||||
	#[error (transparent)]
 | 
						#[error (transparent)]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										124
									
								
								src/client.rs
								
								
								
								
							
							
						
						
									
										124
									
								
								src/client.rs
								
								
								
								
							| 
						 | 
					@ -5,14 +5,9 @@ struct ServerResponse {
 | 
				
			||||||
	nickname: Option <String>,
 | 
						nickname: Option <String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ConfigFile {
 | 
					 | 
				
			||||||
	nicknames: HashMap <String, String>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ClientParams {
 | 
					struct ClientParams {
 | 
				
			||||||
	common: app_common::Params,
 | 
						common: app_common::Params,
 | 
				
			||||||
	bind_addrs: Vec <Ipv4Addr>,
 | 
						bind_addrs: Vec <Ipv4Addr>,
 | 
				
			||||||
	nicknames: HashMap <String, String>,
 | 
					 | 
				
			||||||
	timeout_ms: u64,
 | 
						timeout_ms: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,13 +21,13 @@ pub async fn client <I: Iterator <Item=String>> (args: I) -> Result <(), AppErro
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let params = configure_client (args)?;
 | 
						let params = configure_client (args)?;
 | 
				
			||||||
	let socket = make_socket (¶ms.common, params.bind_addrs).await?;
 | 
						let socket = make_socket (¶ms).await?;
 | 
				
			||||||
	let msg = Message::new_request1 ().to_vec ()?;
 | 
						let msg = Message::new_request1 ().to_vec ()?;
 | 
				
			||||||
	tokio::spawn (send_requests (Arc::clone (&socket), params.common, msg));
 | 
						tokio::spawn (send_requests (Arc::clone (&socket), params.common, msg));
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let mut peers = HashMap::with_capacity (10);
 | 
						let mut peers = HashMap::with_capacity (10);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	timeout (Duration::from_millis (params.timeout_ms), listen_for_responses (&*socket, params.nicknames, &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 ();
 | 
						let mut peers: Vec <_> = peers.into_iter ().collect ();
 | 
				
			||||||
	peers.sort_by_key (|(_, v)| v.mac);
 | 
						peers.sort_by_key (|(_, v)| v.mac);
 | 
				
			||||||
| 
						 | 
					@ -65,9 +60,6 @@ pub async fn find_nick <I: Iterator <Item=String>> (mut args: I) -> Result <(),
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	let mut nick = None;
 | 
						let mut nick = None;
 | 
				
			||||||
	let mut timeout_ms = 500;
 | 
						let mut timeout_ms = 500;
 | 
				
			||||||
	let ConfigFile {
 | 
					 | 
				
			||||||
		nicknames,
 | 
					 | 
				
			||||||
	} = load_config_file ();
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	while let Some (arg) = args.next () {
 | 
						while let Some (arg) = args.next () {
 | 
				
			||||||
		match arg.as_str () {
 | 
							match arg.as_str () {
 | 
				
			||||||
| 
						 | 
					@ -84,13 +76,17 @@ pub async fn find_nick <I: Iterator <Item=String>> (mut args: I) -> Result <(),
 | 
				
			||||||
	let needle_nick = nick.ok_or_else (|| CliArgError::MissingRequiredArg ("nickname".to_string ()))?;
 | 
						let needle_nick = nick.ok_or_else (|| CliArgError::MissingRequiredArg ("nickname".to_string ()))?;
 | 
				
			||||||
	let needle_nick = Some (needle_nick);
 | 
						let needle_nick = Some (needle_nick);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let common_params = Default::default ();
 | 
						let params = ClientParams {
 | 
				
			||||||
 | 
							common: Default::default (),
 | 
				
			||||||
 | 
							bind_addrs: get_ips ()?,
 | 
				
			||||||
 | 
							timeout_ms,
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let socket = make_socket (&common_params, get_ips ()?).await?;
 | 
						let socket = make_socket (¶ms).await?;
 | 
				
			||||||
	let msg = Message::new_request1 ().to_vec ()?;
 | 
						let msg = Message::new_request1 ().to_vec ()?;
 | 
				
			||||||
	tokio::spawn (send_requests (Arc::clone (&socket), common_params, msg));
 | 
						tokio::spawn (send_requests (Arc::clone (&socket), params.common, msg));
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	timeout (Duration::from_millis (timeout_ms), async move { loop {
 | 
						timeout (Duration::from_millis (params.timeout_ms), async move { loop {
 | 
				
			||||||
		let (msgs, remote_addr) = match recv_msg_from (&socket).await {
 | 
							let (msgs, remote_addr) = match recv_msg_from (&socket).await {
 | 
				
			||||||
			Err (_) => continue,
 | 
								Err (_) => continue,
 | 
				
			||||||
			Ok (x) => x,
 | 
								Ok (x) => x,
 | 
				
			||||||
| 
						 | 
					@ -109,8 +105,6 @@ pub async fn find_nick <I: Iterator <Item=String>> (mut args: I) -> Result <(),
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		resp.nickname = get_peer_nickname (&nicknames, resp.mac, resp.nickname);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		if resp.nickname == needle_nick {
 | 
							if resp.nickname == needle_nick {
 | 
				
			||||||
			println! ("{}", remote_addr.ip ());
 | 
								println! ("{}", remote_addr.ip ());
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
| 
						 | 
					@ -126,10 +120,6 @@ fn configure_client <I: Iterator <Item=String>> (mut args: I)
 | 
				
			||||||
	let mut bind_addrs = vec! [];
 | 
						let mut bind_addrs = vec! [];
 | 
				
			||||||
	let mut timeout_ms = 500;
 | 
						let mut timeout_ms = 500;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	let ConfigFile {
 | 
					 | 
				
			||||||
		nicknames,
 | 
					 | 
				
			||||||
	} = load_config_file ();
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	while let Some (arg) = args.next () {
 | 
						while let Some (arg) = args.next () {
 | 
				
			||||||
		match arg.as_str () {
 | 
							match arg.as_str () {
 | 
				
			||||||
			"--bind-addr" => {
 | 
								"--bind-addr" => {
 | 
				
			||||||
| 
						 | 
					@ -155,43 +145,15 @@ fn configure_client <I: Iterator <Item=String>> (mut args: I)
 | 
				
			||||||
	Ok (ClientParams {
 | 
						Ok (ClientParams {
 | 
				
			||||||
		common: Default::default (),
 | 
							common: Default::default (),
 | 
				
			||||||
		bind_addrs,
 | 
							bind_addrs,
 | 
				
			||||||
		nicknames,
 | 
					 | 
				
			||||||
		timeout_ms,
 | 
							timeout_ms,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn load_config_file () -> ConfigFile {
 | 
					async fn make_socket (params: &ClientParams) -> Result <Arc <UdpSocket>, AppError> {
 | 
				
			||||||
	let mut nicknames: HashMap <String, String> = Default::default ();
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if let Some (proj_dirs) = find_project_dirs () {
 | 
					 | 
				
			||||||
		let mut ini = Ini::new_cs ();
 | 
					 | 
				
			||||||
		let path = proj_dirs.config_dir ().join ("client.ini");
 | 
					 | 
				
			||||||
		if ini.load (&path).is_ok () {
 | 
					 | 
				
			||||||
			let map_ref = ini.get_map_ref ();
 | 
					 | 
				
			||||||
			if let Some (x) = map_ref.get ("nicknames") {
 | 
					 | 
				
			||||||
				for (k, v) in x {
 | 
					 | 
				
			||||||
					if let Some (v) = v {
 | 
					 | 
				
			||||||
						let k = k.replace ('-', ":");
 | 
					 | 
				
			||||||
						nicknames.insert (k, v.to_string ());
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	ConfigFile {
 | 
					 | 
				
			||||||
		nicknames,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async fn make_socket (
 | 
					 | 
				
			||||||
	common_params: &app_common::Params,
 | 
					 | 
				
			||||||
	bind_addrs: Vec <Ipv4Addr>,
 | 
					 | 
				
			||||||
) -> Result <Arc <UdpSocket>, AppError> {
 | 
					 | 
				
			||||||
	let socket = UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, 0)).await?;
 | 
						let socket = UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, 0)).await?;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	for bind_addr in &bind_addrs {
 | 
						for bind_addr in ¶ms.bind_addrs {
 | 
				
			||||||
		if let Err (e) = socket.join_multicast_v4 (common_params.multicast_addr, *bind_addr) {
 | 
							if let Err (e) = socket.join_multicast_v4 (params.common.multicast_addr, *bind_addr) {
 | 
				
			||||||
			println! ("Error joining multicast group with iface {}: {:?}", bind_addr, e);
 | 
								println! ("Error joining multicast group with iface {}: {:?}", bind_addr, e);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -215,8 +177,7 @@ async fn send_requests (
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn listen_for_responses (
 | 
					async fn listen_for_responses (
 | 
				
			||||||
	socket: &UdpSocket,
 | 
						socket: &UdpSocket, 
 | 
				
			||||||
	nicknames: HashMap <String, String>,
 | 
					 | 
				
			||||||
	peers: &mut HashMap <SocketAddr, ServerResponse>
 | 
						peers: &mut HashMap <SocketAddr, ServerResponse>
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
	loop {
 | 
						loop {
 | 
				
			||||||
| 
						 | 
					@ -238,63 +199,6 @@ async fn listen_for_responses (
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		resp.nickname = get_peer_nickname (&nicknames, resp.mac, resp.nickname);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		peers.insert (remote_addr, resp);
 | 
							peers.insert (remote_addr, resp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
fn get_peer_nickname (
 | 
					 | 
				
			||||||
	nicknames: &HashMap <String, String>,
 | 
					 | 
				
			||||||
	mac: Option <[u8; 6]>,
 | 
					 | 
				
			||||||
	peer_nickname: Option <String>
 | 
					 | 
				
			||||||
) -> Option <String>
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	match peer_nickname.as_ref ().map (String::as_str) {
 | 
					 | 
				
			||||||
		None => (),
 | 
					 | 
				
			||||||
		Some ("") => (),
 | 
					 | 
				
			||||||
		_ => return peer_nickname,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if let Some (mac) = &mac {
 | 
					 | 
				
			||||||
		return nicknames.get (&format! ("{}", MacAddress::new (*mac))).cloned ()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	None
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg (test)]
 | 
					 | 
				
			||||||
mod test {
 | 
					 | 
				
			||||||
	use super::*;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	#[test]
 | 
					 | 
				
			||||||
	fn test_nicknames () {
 | 
					 | 
				
			||||||
		let mut nicks = HashMap::new ();
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		for (k, v) in [
 | 
					 | 
				
			||||||
			("01:01:01:01:01:01", "phoenix")
 | 
					 | 
				
			||||||
		] {
 | 
					 | 
				
			||||||
			nicks.insert (k.to_string (), v.to_string ());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		for (num, (mac, peer_nickname), expected) in [
 | 
					 | 
				
			||||||
			// Somehow the server returns no MAC nor nick. In this case we are helpless
 | 
					 | 
				
			||||||
			( 1, (None, None), None),
 | 
					 | 
				
			||||||
			// If the server tells us its MAC, we can look up our nickname for it
 | 
					 | 
				
			||||||
			( 2, (Some ([1, 1, 1, 1, 1, 1]), None), Some ("phoenix")),
 | 
					 | 
				
			||||||
			// Unless it's not in our nick list.
 | 
					 | 
				
			||||||
			( 3, (Some ([1, 1, 1, 1, 1, 2]), None), None),
 | 
					 | 
				
			||||||
			// If the server tells us its nickname, that always takes priority
 | 
					 | 
				
			||||||
			( 4, (None, Some ("snowflake")), Some ("snowflake")),
 | 
					 | 
				
			||||||
			( 5, (Some ([1, 1, 1, 1, 1, 1]), Some ("snowflake")), Some ("snowflake")),
 | 
					 | 
				
			||||||
			( 6, (Some ([1, 1, 1, 1, 1, 2]), Some ("snowflake")), Some ("snowflake")),
 | 
					 | 
				
			||||||
			// But blank nicknames are treated like None
 | 
					 | 
				
			||||||
			( 7, (None, Some ("")), None),
 | 
					 | 
				
			||||||
			( 8, (Some ([1, 1, 1, 1, 1, 1]), Some ("")), Some ("phoenix")),
 | 
					 | 
				
			||||||
			( 9, (Some ([1, 1, 1, 1, 1, 2]), Some ("")), None),
 | 
					 | 
				
			||||||
		] {
 | 
					 | 
				
			||||||
			let actual = get_peer_nickname (&nicks, mac, peer_nickname.map (str::to_string));
 | 
					 | 
				
			||||||
			assert_eq! (actual.as_ref ().map (String::as_str), expected, "{}", num);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										11
									
								
								src/main.rs
								
								
								
								
							| 
						 | 
					@ -28,9 +28,7 @@ async fn async_main () -> Result <(), AppError> {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	match subcommand.as_ref ().map (|x| &x[..]) {
 | 
						match subcommand.as_ref ().map (|x| &x[..]) {
 | 
				
			||||||
		None => return Err (CliArgError::MissingSubcommand.into ()),
 | 
							None => return Err (CliArgError::MissingSubcommand.into ()),
 | 
				
			||||||
		Some ("--version") => println! ("lookaround v{}", LOOKAROUND_VERSION),
 | 
					 | 
				
			||||||
		Some ("client") => client::client (args).await?,
 | 
							Some ("client") => client::client (args).await?,
 | 
				
			||||||
		Some ("config") => config (),
 | 
					 | 
				
			||||||
		Some ("find-nick") => client::find_nick (args).await?,
 | 
							Some ("find-nick") => client::find_nick (args).await?,
 | 
				
			||||||
		Some ("my-ips") => my_ips ()?,
 | 
							Some ("my-ips") => my_ips ()?,
 | 
				
			||||||
		Some ("server") => server::server (args).await?,
 | 
							Some ("server") => server::server (args).await?,
 | 
				
			||||||
| 
						 | 
					@ -40,15 +38,6 @@ async fn async_main () -> Result <(), AppError> {
 | 
				
			||||||
	Ok (())
 | 
						Ok (())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn config () {
 | 
					 | 
				
			||||||
	if let Some (proj_dirs) = ProjectDirs::from ("", "ReactorScram", "LookAround") {
 | 
					 | 
				
			||||||
		println! ("Using config dir {:?}", proj_dirs.config_dir ());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		println! ("Can't detect config dir.");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn my_ips () -> Result <(), AppError> {
 | 
					fn my_ips () -> Result <(), AppError> {
 | 
				
			||||||
	for addr in ip::get_ips ()?
 | 
						for addr in ip::get_ips ()?
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,8 +18,6 @@ pub use std::{
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use configparser::ini::Ini;
 | 
					 | 
				
			||||||
pub use directories::ProjectDirs;
 | 
					 | 
				
			||||||
pub use mac_address::{
 | 
					pub use mac_address::{
 | 
				
			||||||
	MacAddress,
 | 
						MacAddress,
 | 
				
			||||||
	get_mac_address,
 | 
						get_mac_address,
 | 
				
			||||||
| 
						 | 
					@ -36,10 +34,8 @@ pub use tokio::{
 | 
				
			||||||
pub use crate::{
 | 
					pub use crate::{
 | 
				
			||||||
	app_common::{
 | 
						app_common::{
 | 
				
			||||||
		self,
 | 
							self,
 | 
				
			||||||
		LOOKAROUND_VERSION,
 | 
					 | 
				
			||||||
		AppError,
 | 
							AppError,
 | 
				
			||||||
		CliArgError,
 | 
							CliArgError,
 | 
				
			||||||
		find_project_dirs,
 | 
					 | 
				
			||||||
		recv_msg_from,
 | 
							recv_msg_from,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	ip::get_ips,
 | 
						ip::get_ips,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,23 +39,6 @@ fn configure <I: Iterator <Item=String>> (mut args: I) -> Result <Params, AppErr
 | 
				
			||||||
	let mut bind_addrs = vec![];
 | 
						let mut bind_addrs = vec![];
 | 
				
			||||||
	let mut nickname = String::new ();
 | 
						let mut nickname = String::new ();
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if let Some (proj_dirs) = find_project_dirs () {
 | 
					 | 
				
			||||||
		let mut ini = Ini::new_cs ();
 | 
					 | 
				
			||||||
		let path = proj_dirs.config_dir ().join ("server.ini");
 | 
					 | 
				
			||||||
		if ini.load (&path).is_ok () {
 | 
					 | 
				
			||||||
			if let Some (x) = ini.get ("server", "nickname") {
 | 
					 | 
				
			||||||
				nickname = x;
 | 
					 | 
				
			||||||
				eprintln! ("Loaded nickname {:?}", nickname);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else {
 | 
					 | 
				
			||||||
			eprintln! ("Can't load ini from {:?}, didn't load default configs", path);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		eprintln! ("Can't find config dir, didn't load default configs");
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	while let Some (arg) = args.next () {
 | 
						while let Some (arg) = args.next () {
 | 
				
			||||||
		match arg.as_str () {
 | 
							match arg.as_str () {
 | 
				
			||||||
			"--bind-addr" => {
 | 
								"--bind-addr" => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue