Skip to content

Commit

Permalink
feat(tui): add last NAT status column (#1219)
Browse files Browse the repository at this point in the history
  • Loading branch information
fujiapple852 committed Jul 22, 2024
1 parent c6a1abb commit 38e7152
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 12 deletions.
4 changes: 4 additions & 0 deletions crates/trippy-tui/src/config/columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ pub enum TuiColumn {
LastIcmpPacketType,
/// The icmp packet code for the last probe for this hop.
LastIcmpPacketCode,
/// The NAT detection status for the last probe for this hop.
LastNatStatus,
}

impl TryFrom<char> for TuiColumn {
Expand Down Expand Up @@ -116,6 +118,7 @@ impl TryFrom<char> for TuiColumn {
'Q' => Ok(Self::LastSeq),
'T' => Ok(Self::LastIcmpPacketType),
'C' => Ok(Self::LastIcmpPacketCode),
'N' => Ok(Self::LastNatStatus),
c => Err(anyhow!(format!("unknown column code: {c}"))),
}
}
Expand Down Expand Up @@ -144,6 +147,7 @@ impl Display for TuiColumn {
Self::LastSeq => write!(f, "Q"),
Self::LastIcmpPacketType => write!(f, "T"),
Self::LastIcmpPacketCode => write!(f, "C"),
Self::LastNatStatus => write!(f, "N"),
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions crates/trippy-tui/src/frontend/columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ pub enum ColumnType {
LastIcmpPacketType,
/// The icmp packet code for the last probe for this hop.
LastIcmpPacketCode,
/// The NAT detection status for the last probe for this hop.
LastNatStatus,
}

impl From<ColumnType> for char {
Expand All @@ -207,6 +209,7 @@ impl From<ColumnType> for char {
ColumnType::LastSeq => 'Q',
ColumnType::LastIcmpPacketType => 'T',
ColumnType::LastIcmpPacketCode => 'C',
ColumnType::LastNatStatus => 'N',
}
}
}
Expand Down Expand Up @@ -234,6 +237,7 @@ impl From<TuiColumn> for Column {
TuiColumn::LastSeq => Self::new_shown(ColumnType::LastSeq),
TuiColumn::LastIcmpPacketType => Self::new_shown(ColumnType::LastIcmpPacketType),
TuiColumn::LastIcmpPacketCode => Self::new_shown(ColumnType::LastIcmpPacketCode),
TuiColumn::LastNatStatus => Self::new_shown(ColumnType::LastNatStatus),
}
}
}
Expand Down Expand Up @@ -261,6 +265,7 @@ impl Display for ColumnType {
Self::LastSeq => write!(f, "Seq"),
Self::LastIcmpPacketType => write!(f, "Type"),
Self::LastIcmpPacketCode => write!(f, "Code"),
Self::LastNatStatus => write!(f, "Nat"),
}
}
}
Expand Down Expand Up @@ -290,6 +295,7 @@ impl ColumnType {
Self::LastSeq => ColumnWidth::Fixed(7),
Self::LastIcmpPacketType => ColumnWidth::Fixed(7),
Self::LastIcmpPacketCode => ColumnWidth::Fixed(7),
Self::LastNatStatus => ColumnWidth::Fixed(7),
}
}
}
Expand Down Expand Up @@ -348,6 +354,7 @@ mod tests {
Column::new_hidden(ColumnType::LastSeq),
Column::new_hidden(ColumnType::LastIcmpPacketType),
Column::new_hidden(ColumnType::LastIcmpPacketCode),
Column::new_hidden(ColumnType::LastNatStatus),
])
);
}
Expand Down
66 changes: 54 additions & 12 deletions crates/trippy-tui/src/frontend/render/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use ratatui::widgets::{Block, BorderType, Borders, Cell, Row, Table};
use ratatui::Frame;
use std::net::IpAddr;
use std::rc::Rc;
use trippy_core::Hop;
use trippy_core::{Extension, Extensions, IcmpPacketType, MplsLabelStackMember, UnknownExtension};
use trippy_core::{Hop, NatStatus};
use trippy_dns::{AsInfo, DnsEntry, DnsResolver, Resolved, Resolver, Unresolved};

/// Render the table of data about the hops.
Expand Down Expand Up @@ -163,13 +163,22 @@ fn new_cell(
ColumnType::LastSeq => render_usize_cell(usize::from(hop.last_sequence())),
ColumnType::LastIcmpPacketType => render_icmp_packet_type_cell(hop.last_icmp_packet_type()),
ColumnType::LastIcmpPacketCode => render_icmp_packet_code_cell(hop.last_icmp_packet_type()),
ColumnType::LastNatStatus => render_nat_cell(hop.last_nat_status()),
}
}

fn render_usize_cell(value: usize) -> Cell<'static> {
Cell::from(format!("{value}"))
}

fn render_nat_cell(value: NatStatus) -> Cell<'static> {
Cell::from(match value {
NatStatus::NotApplicable => "n/a",
NatStatus::NotDetected => "No",
NatStatus::Detected => "Yes",
})
}

fn render_loss_pct_cell(hop: &Hop) -> Cell<'static> {
Cell::from(format!("{:.1}%", hop.loss_pct()))
}
Expand Down Expand Up @@ -336,13 +345,20 @@ fn format_address(
} else {
None
};
let nat = match hop.last_nat_status() {
NatStatus::Detected => Some("NAT"),
_ => None,
};
let mut address = addr_fmt;
if let Some(geo) = geo_fmt.as_deref() {
address.push_str(&format!(" [{geo}]"));
}
if let Some(exp) = exp_fmt {
address.push_str(&format!(" [{exp}]"));
}
if let Some(nat) = nat {
address.push_str(&format!(" [{nat}]"));
}
if let Some(freq) = freq_fmt {
address.push_str(&format!(" [{freq}]"));
}
Expand Down Expand Up @@ -521,9 +537,10 @@ fn format_details(
dns.lazy_reverse_lookup(*addr)
};
let ext = hop.extensions();
let nat = hop.last_nat_status();
match dns_entry {
DnsEntry::Pending(addr) => {
fmt_details_line(addr, index, count, None, None, geoip, ext, config)
fmt_details_line(addr, index, count, None, None, geoip, ext, nat, config)
}
DnsEntry::Resolved(Resolved::WithAsInfo(addr, hosts, asinfo)) => fmt_details_line(
addr,
Expand All @@ -533,6 +550,7 @@ fn format_details(
Some(asinfo),
geoip,
ext,
nat,
config,
),
DnsEntry::NotFound(Unresolved::WithAsInfo(addr, asinfo)) => fmt_details_line(
Expand All @@ -543,14 +561,31 @@ fn format_details(
Some(asinfo),
geoip,
ext,
nat,
config,
),
DnsEntry::Resolved(Resolved::Normal(addr, hosts)) => fmt_details_line(
addr,
index,
count,
Some(hosts),
None,
geoip,
ext,
nat,
config,
),
DnsEntry::NotFound(Unresolved::Normal(addr)) => fmt_details_line(
addr,
index,
count,
Some(vec![]),
None,
geoip,
ext,
nat,
config,
),
DnsEntry::Resolved(Resolved::Normal(addr, hosts)) => {
fmt_details_line(addr, index, count, Some(hosts), None, geoip, ext, config)
}
DnsEntry::NotFound(Unresolved::Normal(addr)) => {
fmt_details_line(addr, index, count, Some(vec![]), None, geoip, ext, config)
}
DnsEntry::Failed(ip) => {
format!("Failed: {ip}")
}
Expand Down Expand Up @@ -582,9 +617,10 @@ fn fmt_details_line(
asinfo: Option<AsInfo>,
geoip: Option<Rc<GeoIpCity>>,
extensions: Option<&Extensions>,
nat: NatStatus,
config: &TuiConfig,
) -> String {
let as_formatted = match (config.lookup_as_info, asinfo) {
let as_fmt = match (config.lookup_as_info, asinfo) {
(false, _) => "AS Name: <not enabled>\nAS Info: <not enabled>".to_string(),
(true, None) => "AS Name: <awaited>\nAS Info: <awaited>".to_string(),
(true, Some(info)) if info.asn.is_empty() => {
Expand All @@ -604,7 +640,7 @@ fn fmt_details_line(
} else {
"Host: <awaited>".to_string()
};
let geoip_formatted = if let Some(geo) = geoip {
let geoip_fmt = if let Some(geo) = geoip {
let (lat, long, radius) = geo.coordinates().unwrap_or_default();
format!(
"Geo: {}\nPos: {}, {} (~{}km)",
Expand All @@ -616,10 +652,16 @@ fn fmt_details_line(
} else {
"Geo: <not found>\nPos: <not found>".to_string()
};
let ext_formatted = if let Some(extensions) = extensions {
let ext_fmt = if let Some(extensions) = extensions {
format!("Ext: [{}]", format_extensions_all(extensions))
} else {
"Ext: <none>".to_string()
};
format!("{addr} [{index} of {count}]\n{hosts_rendered}\n{as_formatted}\n{geoip_formatted}\n{ext_formatted}")
let nat_fmt = match nat {
NatStatus::Detected => " [NAT]",
_ => "",
};
format!(
"{addr}{nat_fmt} [{index} of {count}]\n{hosts_rendered}\n{as_fmt}\n{geoip_fmt}\n{ext_fmt}"
)
}

0 comments on commit 38e7152

Please sign in to comment.