mirror of
https://github.com/Llewellynvdm/starship.git
synced 2024-12-26 03:27:30 +00:00
feat(localip): use reserved remote address (#4648)
Instead of the remote address of 8.8.8.8 (Google DNS) in the crate local_ipaddress use a reserved IPv4 address, that should never be assigned. Also forward the underlying error on failure. Supersedes: #4614
This commit is contained in:
parent
9484e7eb01
commit
ddd54e9b20
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -1630,12 +1630,6 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
|
||||
|
||||
[[package]]
|
||||
name = "local_ipaddress"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6a104730949fbc4c78e4fa98ed769ca0faa02e9818936b61032d2d77526afa9"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.8"
|
||||
@ -2770,7 +2764,6 @@ dependencies = [
|
||||
"guess_host_triple",
|
||||
"home",
|
||||
"indexmap",
|
||||
"local_ipaddress",
|
||||
"log",
|
||||
"mockall",
|
||||
"nix 0.26.1",
|
||||
|
@ -52,7 +52,6 @@ git-features = { version = "0.24.1", optional = true }
|
||||
# default feature restriction addresses https://github.com/starship/starship/issues/4251
|
||||
git-repository = { version = "0.29.0", default-features = false, features = ["max-performance-safe"] }
|
||||
indexmap = { version = "1.9.2", features = ["serde"] }
|
||||
local_ipaddress = "0.1.3"
|
||||
log = { version = "0.4.17", features = ["std"] }
|
||||
# nofity-rust is optional (on by default) because the crate doesn't currently build for darwin with nix
|
||||
# see: https://github.com/NixOS/nixpkgs/issues/160876
|
||||
|
@ -4,14 +4,27 @@ use crate::config::ModuleConfig;
|
||||
use crate::configs::localip::LocalipConfig;
|
||||
use crate::formatter::StringFormatter;
|
||||
|
||||
use std::io::Error;
|
||||
use std::net::UdpSocket;
|
||||
|
||||
fn get_local_ipv4() -> Result<String, Error> {
|
||||
let socket = UdpSocket::bind("0.0.0.0:0")?;
|
||||
socket.connect("192.0.2.0:80")?;
|
||||
|
||||
let addr = socket.local_addr()?;
|
||||
|
||||
Ok(addr.ip().to_string())
|
||||
}
|
||||
|
||||
/// Creates a module with the ipv4 address of the local machine.
|
||||
///
|
||||
/// The `local_ipaddress` crate is used to determine the local IP address of your machine.
|
||||
/// An accurate and fast way, especially if there are multiple IP addresses available,
|
||||
/// is to connect a UDP socket and then reading its local endpoint.
|
||||
/// The IP address is gathered from the local endpoint of an UDP socket
|
||||
/// connected to a reserved IPv4 remote address, which is an accurate and fast
|
||||
/// way, especially if there are multiple IP addresses available.
|
||||
/// There should be no actual packets send over the wire.
|
||||
///
|
||||
/// Will display the ip if all of the following criteria are met:
|
||||
/// - localip.disabled is false
|
||||
/// - `localip.disabled` is false
|
||||
/// - `localip.ssh_only` is false OR the user is currently connected as an SSH session (`$SSH_CONNECTION`)
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("localip");
|
||||
@ -28,11 +41,18 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let localip = local_ipaddress::get().unwrap_or_default();
|
||||
if localip.is_empty() {
|
||||
log::warn!("unable to determine local ipv4 address");
|
||||
let localip = match get_local_ipv4() {
|
||||
Ok(ip) => ip,
|
||||
Err(e) => {
|
||||
// ErrorKind::NetworkUnreachable is unstable
|
||||
if cfg!(target_os = "linux") && e.raw_os_error() == Some(101) {
|
||||
"NetworkUnreachable".to_string()
|
||||
} else {
|
||||
log::warn!("unable to determine local ipv4 address: {e}");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
||||
formatter
|
||||
@ -60,20 +80,23 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::modules::localip::get_local_ipv4;
|
||||
use crate::test::ModuleRenderer;
|
||||
use nu_ansi_term::{Color, Style};
|
||||
|
||||
macro_rules! get_localip {
|
||||
() => {
|
||||
if let Some(localip) = local_ipaddress::get() {
|
||||
localip
|
||||
} else {
|
||||
match get_local_ipv4() {
|
||||
Ok(ip) => ip,
|
||||
Err(e) => {
|
||||
println!(
|
||||
"localip was not tested because socket connection failed! \
|
||||
This could be caused by an unconventional network setup."
|
||||
This could be caused by an unconventional network setup. \
|
||||
Error: {e}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user