cleaned up and added install subcommand
parent
5aeb4c8d7a
commit
0286d854d6
|
@ -2,6 +2,12 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.97"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -20,6 +26,21 @@ version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "camino"
|
||||||
|
version = "1.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -88,11 +109,14 @@ dependencies = [
|
||||||
name = "lookaround"
|
name = "lookaround"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"camino",
|
||||||
"configparser",
|
"configparser",
|
||||||
"directories",
|
"directories",
|
||||||
"mac_address",
|
"mac_address",
|
||||||
"nix",
|
"nix",
|
||||||
"rand",
|
"rand",
|
||||||
|
"sys-info",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
@ -249,6 +273,12 @@ dependencies = [
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.82"
|
version = "1.0.82"
|
||||||
|
@ -260,6 +290,16 @@ dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sys-info"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.30"
|
version = "1.0.30"
|
||||||
|
|
|
@ -12,11 +12,14 @@ repository = "https://six-five-six-four.com/git/reactor/lookaround"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.97"
|
||||||
|
camino = "1.1.9"
|
||||||
configparser = "3.0.0"
|
configparser = "3.0.0"
|
||||||
directories = "5.0.0"
|
directories = "5.0.0"
|
||||||
mac_address = "1.1.8"
|
mac_address = "1.1.8"
|
||||||
nix = "0.29.0"
|
nix = "0.29.0"
|
||||||
rand = "0.8.4"
|
rand = "0.8.4"
|
||||||
|
sys-info = "0.9.1"
|
||||||
thiserror = "1.0.30"
|
thiserror = "1.0.30"
|
||||||
tokio = { version = "1.14.0", features = ["fs", "net", "rt", "time"] }
|
tokio = { version = "1.14.0", features = ["fs", "net", "rt", "time"] }
|
||||||
|
|
||||||
|
|
39
README.md
39
README.md
|
@ -28,51 +28,38 @@ Make sure Cargo is installed from [RustUp.](https://rustup.rs/)
|
||||||
cargo install lookaround
|
cargo install lookaround
|
||||||
|
|
||||||
# Find your config directory
|
# Find your config directory
|
||||||
# Prints something like `Using config dir "/home/user/.config/lookaround"`
|
# e.g. `$HOME/.config/lookaround`
|
||||||
lookaround config
|
lookaround config
|
||||||
```
|
```
|
||||||
|
|
||||||
Create the files `client.ini` and/or `server.ini` in that directory
|
Use `$HOME/.config/lookaround/client.ini` as a hosts file if it's more convenient
|
||||||
(e.g. /home/user/.config/lookaround/server.ini)
|
for your client to be the source of truth for nicknames.
|
||||||
|
|
||||||
```ini
|
```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]
|
[nicknames]
|
||||||
11-11-11-11-11-11 = laptop
|
11-11-11-11-11-11 = bob-laptop
|
||||||
22-22-22-22-22-22 = desktop
|
22-22-22-22-22-22 = alice-desktop
|
||||||
```
|
```
|
||||||
|
|
||||||
|
LookAround will use the system's hostname as its server nickname.
|
||||||
|
If you have a generic hostname like `ubuntu`, override this in `$HOME/.config/lookaround/server.ini`:
|
||||||
|
|
||||||
```ini
|
```ini
|
||||||
# Long-lived servers can have their nickname configured in server.ini
|
|
||||||
[server]
|
[server]
|
||||||
nickname = my-computer
|
nickname = alice-desktop
|
||||||
```
|
```
|
||||||
|
|
||||||
## Auto-Start (Linux)
|
## Auto-Start (Linux)
|
||||||
|
|
||||||
Put this systemd unit in `~/.config/systemd/user/lookaround.service`:
|
Run `lookaround install` or `lookaround install $NICKNAME` if you want to set a nickname.
|
||||||
|
|
||||||
```ini
|
This will create `$HOME/.config/lookaround/server.ini` and `$HOME/.config/systemd/user/lookaround.service`, and start the systemd user service.
|
||||||
[Unit]
|
|
||||||
Description=LookAround
|
|
||||||
|
|
||||||
[Service]
|
To check that it's running
|
||||||
ExecStart=/home/user/.cargo/bin/lookaround server
|
|
||||||
Restart=always
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
```
|
|
||||||
|
|
||||||
Then start the service, check that it's running okay, and enable it for
|
|
||||||
auto-start:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
systemctl --user start lookaround
|
|
||||||
systemctl --user status lookaround
|
systemctl --user status lookaround
|
||||||
systemctl --user enable lookaround
|
lookaround client
|
||||||
```
|
```
|
||||||
|
|
||||||
## Auto-Start (Windows)
|
## Auto-Start (Windows)
|
||||||
|
|
|
@ -9,6 +9,10 @@ pub fn try_config_dir() -> Option<PathBuf> {
|
||||||
Some(try_project_dir()?.config_local_dir().into())
|
Some(try_project_dir()?.config_local_dir().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_server_config_path() -> Option<PathBuf> {
|
||||||
|
Some(try_config_dir()?.join("server.ini"))
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum AppError {
|
pub enum AppError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
|
@ -1,7 +1,83 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use anyhow::{Context as _, Result, anyhow, ensure};
|
||||||
|
use std::{io::Write as _, process::Command};
|
||||||
|
|
||||||
pub(crate) fn main() -> Result<(), AppError> {
|
pub(crate) fn main(nickname: Option<&str>) -> Result<()> {
|
||||||
let path = app_common::try_config_dir().unwrap().join("server.ini");
|
if let Some(nickname) = nickname {
|
||||||
|
let path = app_common::try_server_config_path().context("can't find config dir")?;
|
||||||
|
let text = format!(
|
||||||
|
"[server]
|
||||||
|
nickname = {nickname}
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
write_new(&path, &text).context("Didn't install LookAround server.ini")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_autostart()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
fn setup_autostart() -> Result<()> {
|
||||||
|
anyhow::bail!("LookAround autostart is only implemented for systemd + GNU/Linux");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn setup_autostart() -> Result<()> {
|
||||||
|
let dirs = directories::BaseDirs::new().context("Could not find home dir")?;
|
||||||
|
let home = dirs.config_local_dir();
|
||||||
|
let path = home.join("systemd").join("user").join("lookaround.service");
|
||||||
|
|
||||||
|
let exe_path =
|
||||||
|
Utf8PathBuf::from_path_buf(std::env::current_exe().context("Can't get current_exe")?)
|
||||||
|
.map_err(|_| anyhow!("current_exe isn't valid UTF-8"))?;
|
||||||
|
let text = format!(
|
||||||
|
"[Unit]
|
||||||
|
Description=LookAround
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart={exe_path} server
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
write_new(&path, &text).context("Didn't install systemd service unit")?;
|
||||||
|
|
||||||
|
ensure!(
|
||||||
|
Command::new("systemctl")
|
||||||
|
.args(["--user", "start", "lookaround"])
|
||||||
|
.status()?
|
||||||
|
.success(),
|
||||||
|
"starting service failed"
|
||||||
|
);
|
||||||
|
ensure!(
|
||||||
|
Command::new("systemctl")
|
||||||
|
.args(["--user", "enable", "lookaround"])
|
||||||
|
.status()?
|
||||||
|
.success(),
|
||||||
|
"enabling service failed"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_new(path: &Path, content: &str) -> Result<()> {
|
||||||
|
use std::fs;
|
||||||
|
fs::create_dir_all(
|
||||||
|
path.parent()
|
||||||
|
.context("Impossible, path should always have a parent")?,
|
||||||
|
)?;
|
||||||
|
match fs::File::create_new(path) {
|
||||||
|
Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {
|
||||||
|
eprintln!("File already exists, won't overwrite: `{path:?}`")
|
||||||
|
}
|
||||||
|
Err(err) => Err(err)?,
|
||||||
|
Ok(mut f) => f.write_all(content.as_bytes())?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use anyhow::{Result, bail};
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
|
||||||
pub mod app_common;
|
pub mod app_common;
|
||||||
|
@ -9,7 +10,7 @@ mod prelude;
|
||||||
mod server;
|
mod server;
|
||||||
pub mod tlv;
|
pub mod tlv;
|
||||||
|
|
||||||
fn main() -> Result<(), AppError> {
|
fn main() -> Result<()> {
|
||||||
let rt = tokio::runtime::Builder::new_current_thread()
|
let rt = tokio::runtime::Builder::new_current_thread()
|
||||||
.enable_io()
|
.enable_io()
|
||||||
.enable_time()
|
.enable_time()
|
||||||
|
@ -20,7 +21,7 @@ fn main() -> Result<(), AppError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn async_main() -> Result<(), AppError> {
|
async fn async_main() -> Result<()> {
|
||||||
let mut args = env::args();
|
let mut args = env::args();
|
||||||
|
|
||||||
let _exe_name = args.next();
|
let _exe_name = args.next();
|
||||||
|
@ -32,19 +33,21 @@ async fn async_main() -> Result<(), AppError> {
|
||||||
match subcommand.as_ref() {
|
match subcommand.as_ref() {
|
||||||
"--version" => {
|
"--version" => {
|
||||||
println!("lookaround v{}", env!("CARGO_PKG_VERSION"));
|
println!("lookaround v{}", env!("CARGO_PKG_VERSION"));
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"client" => client::client(args).await,
|
"client" => client::client(args).await?,
|
||||||
"config" => {
|
"config" => {
|
||||||
config();
|
config();
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
"find-nick" => client::find_nick(args).await,
|
"find-nick" => client::find_nick(args).await?,
|
||||||
"install" => install::main(),
|
"install" => {
|
||||||
"my-ips" => my_ips(),
|
let nickname = args.next();
|
||||||
"server" => server::server(args).await,
|
install::main(nickname.as_deref())?
|
||||||
x => Err(CliArgError::UnknownSubcommand(x.to_string()).into()),
|
}
|
||||||
|
"my-ips" => my_ips()?,
|
||||||
|
"server" => server::server(args).await?,
|
||||||
|
x => bail!("Unknown subcommand `{x}`"),
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn config() {
|
fn config() {
|
||||||
|
|
|
@ -3,12 +3,13 @@ pub use std::{
|
||||||
env,
|
env,
|
||||||
io::{Cursor, Write},
|
io::{Cursor, Write},
|
||||||
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
||||||
path::PathBuf,
|
path::{Path, PathBuf},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub use camino::Utf8PathBuf;
|
||||||
pub use configparser::ini::Ini;
|
pub use configparser::ini::Ini;
|
||||||
pub use mac_address::{MacAddress, get_mac_address};
|
pub use mac_address::{MacAddress, get_mac_address};
|
||||||
pub use rand::RngCore;
|
pub use rand::RngCore;
|
||||||
|
|
|
@ -42,10 +42,9 @@ pub async fn server<I: Iterator<Item = String>>(args: I) -> Result<(), AppError>
|
||||||
fn configure<I: Iterator<Item = String>>(mut args: I) -> Result<Params, AppError> {
|
fn configure<I: Iterator<Item = String>>(mut args: I) -> Result<Params, AppError> {
|
||||||
let common = app_common::Params::default();
|
let common = app_common::Params::default();
|
||||||
let mut bind_addrs = vec![];
|
let mut bind_addrs = vec![];
|
||||||
let mut nickname = String::new();
|
let mut nickname = sys_info::hostname().unwrap_or_default();
|
||||||
|
|
||||||
if let Some(dir) = app_common::try_config_dir() {
|
if let Some(path) = app_common::try_server_config_path() {
|
||||||
let path = dir.join("server.ini");
|
|
||||||
let mut ini = Ini::new_cs();
|
let mut ini = Ini::new_cs();
|
||||||
if ini.load(&path).is_ok() {
|
if ini.load(&path).is_ok() {
|
||||||
if let Some(x) = ini.get("server", "nickname") {
|
if let Some(x) = ini.get("server", "nickname") {
|
||||||
|
|
Loading…
Reference in New Issue