feat: show version & local node (#318)

*  feat: version

Add display version information, incompatible with lower versions

* 🎈 perf: unknown

Unknown when there is no version number displayed

*  feat: Display local nodes

Display local nodes, incompatible with lower versions
This commit is contained in:
m1m1sha
2024-09-11 15:58:13 +08:00
committed by GitHub
parent 4342be29d7
commit 6ea3adcef8
10 changed files with 110 additions and 16 deletions

View File

@@ -66,6 +66,10 @@ upload_bytes: 上传
download_bytes: 下载 download_bytes: 下载
loss_rate: 丢包率 loss_rate: 丢包率
status:
version: 内核版本
local: 本机
run_network: 运行网络 run_network: 运行网络
stop_network: 停止网络 stop_network: 停止网络
network_running: 运行中 network_running: 运行中

View File

@@ -66,6 +66,10 @@ upload_bytes: Upload
download_bytes: Download download_bytes: Download
loss_rate: Loss Rate loss_rate: Loss Rate
status:
version: Version
local: Local
run_network: Run Network run_network: Run Network
stop_network: Stop Network stop_network: Stop Network
network_running: running network_running: running

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import type { NodeInfo } from '~/types/network' import type { NodeInfo, PeerRoutePair } from '~/types/network'
const props = defineProps<{ const props = defineProps<{
instanceId?: string instanceId?: string
@@ -25,13 +25,24 @@ const curNetworkInst = computed(() => {
}) })
const peerRouteInfos = computed(() => { const peerRouteInfos = computed(() => {
if (curNetworkInst.value) if (curNetworkInst.value) {
return curNetworkInst.value.detail?.peer_route_pairs || [] const my_node_info = curNetworkInst.value.detail?.my_node_info
return [{
route: {
ipv4_addr: my_node_info?.virtual_ipv4,
hostname: my_node_info?.hostname,
version: my_node_info?.version,
},
}, ...(curNetworkInst.value.detail?.peer_route_pairs || [])]
}
return [] return []
}) })
function routeCost(info: any) { function routeCost(info: any) {
if (!info.peer)
return t('status.local')
if (info.route) { if (info.route) {
const cost = info.route.cost const cost = info.route.cost
return cost === 1 ? 'p2p' : `relay(${cost})` return cost === 1 ? 'p2p' : `relay(${cost})`
@@ -74,29 +85,33 @@ function humanFileSize(bytes: number, si = false, dp = 1) {
return `${bytes.toFixed(dp)} ${units[u]}` return `${bytes.toFixed(dp)} ${units[u]}`
} }
function latencyMs(info: any) { function latencyMs(info: PeerRoutePair) {
let lat_us_sum = statsCommon(info, 'stats.latency_us') let lat_us_sum = statsCommon(info, 'stats.latency_us')
if (lat_us_sum === undefined) if (lat_us_sum === undefined)
return '' return ''
lat_us_sum = lat_us_sum / 1000 / info.peer.conns.length lat_us_sum = lat_us_sum / 1000 / info.peer!.conns.length
return `${lat_us_sum % 1 > 0 ? Math.round(lat_us_sum) + 1 : Math.round(lat_us_sum)}ms` return `${lat_us_sum % 1 > 0 ? Math.round(lat_us_sum) + 1 : Math.round(lat_us_sum)}ms`
} }
function txBytes(info: any) { function txBytes(info: PeerRoutePair) {
const tx = statsCommon(info, 'stats.tx_bytes') const tx = statsCommon(info, 'stats.tx_bytes')
return tx ? humanFileSize(tx) : '' return tx ? humanFileSize(tx) : ''
} }
function rxBytes(info: any) { function rxBytes(info: PeerRoutePair) {
const rx = statsCommon(info, 'stats.rx_bytes') const rx = statsCommon(info, 'stats.rx_bytes')
return rx ? humanFileSize(rx) : '' return rx ? humanFileSize(rx) : ''
} }
function lossRate(info: any) { function lossRate(info: PeerRoutePair) {
const lossRate = statsCommon(info, 'loss_rate') const lossRate = statsCommon(info, 'loss_rate')
return lossRate !== undefined ? `${Math.round(lossRate * 100)}%` : '' return lossRate !== undefined ? `${Math.round(lossRate * 100)}%` : ''
} }
function version(info: PeerRoutePair) {
return info.route.version === '' ? 'unknown' : info.route.version
}
const myNodeInfo = computed(() => { const myNodeInfo = computed(() => {
if (!curNetworkInst.value) if (!curNetworkInst.value)
return {} as NodeInfo return {} as NodeInfo
@@ -374,6 +389,7 @@ function showEventLogs() {
<Column :field="txBytes" style="width: 80px;" :header="t('upload_bytes')" /> <Column :field="txBytes" style="width: 80px;" :header="t('upload_bytes')" />
<Column :field="rxBytes" style="width: 80px;" :header="t('download_bytes')" /> <Column :field="rxBytes" style="width: 80px;" :header="t('download_bytes')" />
<Column :field="lossRate" style="width: 100px;" :header="t('loss_rate')" /> <Column :field="lossRate" style="width: 100px;" :header="t('loss_rate')" />
<Column :field="version" style="width: 100px;" :header="t('status.version')" />
</DataTable> </DataTable>
</template> </template>
</Card> </Card>

View File

@@ -87,6 +87,8 @@ export interface NetworkInstanceRunningInfo {
export interface NodeInfo { export interface NodeInfo {
virtual_ipv4: string virtual_ipv4: string
hostname: string
version: string
ips: { ips: {
public_ipv4: string public_ipv4: string
interface_ipv4s: string[] interface_ipv4s: string[]
@@ -125,6 +127,7 @@ export interface Route {
hostname: string hostname: string
stun_info?: StunInfo stun_info?: StunInfo
inst_id: string inst_id: string
version: string
} }
export interface PeerInfo { export interface PeerInfo {

View File

@@ -76,6 +76,7 @@ message Route {
string hostname = 6; string hostname = 6;
StunInfo stun_info = 7; StunInfo stun_info = 7;
string inst_id = 8; string inst_id = 8;
string version = 9;
} }
message NodeInfo { message NodeInfo {
@@ -87,6 +88,7 @@ message NodeInfo {
string inst_id = 6; string inst_id = 6;
repeated string listeners = 7; repeated string listeners = 7;
string config = 8; string config = 8;
string version = 9;
} }
message ShowNodeInfoRequest {} message ShowNodeInfoRequest {}

View File

@@ -197,6 +197,7 @@ impl CommandHandler {
tunnel_proto: String, tunnel_proto: String,
nat_type: String, nat_type: String,
id: String, id: String,
version: String,
} }
impl From<PeerRoutePair> for PeerTableItem { impl From<PeerRoutePair> for PeerTableItem {
@@ -212,6 +213,33 @@ impl CommandHandler {
tunnel_proto: p.get_conn_protos().unwrap_or(vec![]).join(",").to_string(), tunnel_proto: p.get_conn_protos().unwrap_or(vec![]).join(",").to_string(),
nat_type: p.get_udp_nat_type(), nat_type: p.get_udp_nat_type(),
id: p.route.peer_id.to_string(), id: p.route.peer_id.to_string(),
version: if p.route.version.is_empty() {
"unknown".to_string()
} else {
p.route.version.to_string()
},
}
}
}
impl From<NodeInfo> for PeerTableItem {
fn from(p: NodeInfo) -> Self {
PeerTableItem {
ipv4: p.ipv4_addr.clone(),
hostname: p.hostname.clone(),
cost: "Local".to_string(),
lat_ms: "-".to_string(),
loss_rate: "-".to_string(),
rx_bytes: "-".to_string(),
tx_bytes: "-".to_string(),
tunnel_proto: "-".to_string(),
nat_type: if let Some(info) = p.stun_info {
info.udp_nat_type().as_str_name().to_string()
} else {
"Unknown".to_string()
},
id: p.peer_id.to_string(),
version: p.version,
} }
} }
} }
@@ -223,6 +251,15 @@ impl CommandHandler {
return Ok(()); return Ok(());
} }
let mut client = self.get_peer_manager_client().await?;
let node_info = client
.show_node_info(ShowNodeInfoRequest::default())
.await?
.into_inner()
.node_info
.ok_or(anyhow::anyhow!("node info not found"))?;
items.push(node_info.into());
for p in peer_routes { for p in peer_routes {
items.push(p.into()); items.push(p.into());
} }
@@ -293,9 +330,28 @@ impl CommandHandler {
next_hop_hostname: String, next_hop_hostname: String,
next_hop_lat: f64, next_hop_lat: f64,
cost: i32, cost: i32,
version: String,
} }
let mut items: Vec<RouteTableItem> = vec![]; let mut items: Vec<RouteTableItem> = vec![];
let mut client = self.get_peer_manager_client().await?;
let node_info = client
.show_node_info(ShowNodeInfoRequest::default())
.await?
.into_inner()
.node_info
.ok_or(anyhow::anyhow!("node info not found"))?;
items.push(RouteTableItem {
ipv4: node_info.ipv4_addr.clone(),
hostname: node_info.hostname.clone(),
proxy_cidrs: node_info.proxy_cidrs.join(", "),
next_hop_ipv4: "-".to_string(),
next_hop_hostname: "Local".to_string(),
next_hop_lat: 0.0,
cost: 0,
version: node_info.version.clone(),
});
let peer_routes = self.list_peer_route_pair().await?; let peer_routes = self.list_peer_route_pair().await?;
for p in peer_routes.iter() { for p in peer_routes.iter() {
let Some(next_hop_pair) = peer_routes let Some(next_hop_pair) = peer_routes
@@ -314,6 +370,11 @@ impl CommandHandler {
next_hop_hostname: "".to_string(), next_hop_hostname: "".to_string(),
next_hop_lat: next_hop_pair.get_latency_ms().unwrap_or(0.0), next_hop_lat: next_hop_pair.get_latency_ms().unwrap_or(0.0),
cost: p.route.cost, cost: p.route.cost,
version: if p.route.version.is_empty() {
"unknown".to_string()
} else {
p.route.version.to_string()
},
}); });
} else { } else {
items.push(RouteTableItem { items.push(RouteTableItem {
@@ -324,6 +385,11 @@ impl CommandHandler {
next_hop_hostname: next_hop_pair.route.hostname.clone(), next_hop_hostname: next_hop_pair.route.hostname.clone(),
next_hop_lat: next_hop_pair.get_latency_ms().unwrap_or(0.0), next_hop_lat: next_hop_pair.get_latency_ms().unwrap_or(0.0),
cost: p.route.cost, cost: p.route.cost,
version: if p.route.version.is_empty() {
"unknown".to_string()
} else {
p.route.version.to_string()
},
}); });
} }
} }

View File

@@ -24,6 +24,8 @@ use tokio::task::JoinSet;
#[derive(Default, Clone, Debug, Serialize, Deserialize)] #[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct MyNodeInfo { pub struct MyNodeInfo {
pub virtual_ipv4: String, pub virtual_ipv4: String,
pub hostname: String,
pub version: String,
pub ips: GetIpListResponse, pub ips: GetIpListResponse,
pub stun_info: StunInfo, pub stun_info: StunInfo,
pub listeners: Vec<String>, pub listeners: Vec<String>,
@@ -137,6 +139,8 @@ impl EasyTierLauncher {
.get_ipv4() .get_ipv4()
.map(|x| x.to_string()) .map(|x| x.to_string())
.unwrap_or_default(), .unwrap_or_default(),
hostname: global_ctx_c.get_hostname(),
version: env!("CARGO_PKG_VERSION").to_string(),
ips: global_ctx_c.get_ip_collector().collect_ip_addrs().await, ips: global_ctx_c.get_ip_collector().collect_ip_addrs().await,
stun_info: global_ctx_c.get_stun_info_collector().get_stun_info(), stun_info: global_ctx_c.get_stun_info_collector().get_stun_info(),
listeners: global_ctx_c listeners: global_ctx_c

View File

@@ -30,14 +30,7 @@ use crate::{
PeerId, PeerId,
}, },
rpc::{HandshakeRequest, PeerConnInfo, PeerConnStats, TunnelInfo}, rpc::{HandshakeRequest, PeerConnInfo, PeerConnStats, TunnelInfo},
tunnel::packet_def::PacketType, tunnel::{filter::{StatsRecorderTunnelFilter, TunnelFilter, TunnelWithFilter}, mpsc::{MpscTunnel, MpscTunnelSender}, packet_def::{PacketType, ZCPacket}, stats::{Throughput, WindowLatency}, Tunnel, TunnelError, ZCPacketStream},
tunnel::{
filter::{StatsRecorderTunnelFilter, TunnelFilter, TunnelWithFilter},
mpsc::{MpscTunnel, MpscTunnelSender},
packet_def::ZCPacket,
stats::{Throughput, WindowLatency},
Tunnel, TunnelError, ZCPacketStream,
},
}; };
use super::{peer_conn_ping::PeerConnPinger, PacketRecvChan}; use super::{peer_conn_ping::PeerConnPinger, PacketRecvChan};

View File

@@ -771,6 +771,7 @@ impl PeerManager {
.map(|x| x.to_string()) .map(|x| x.to_string())
.collect(), .collect(),
config: self.global_ctx.config.dump(), config: self.global_ctx.config.dump(),
version: env!("CARGO_PKG_VERSION").to_string(),
} }
} }
} }

View File

@@ -163,6 +163,7 @@ impl Into<crate::rpc::Route> for RoutePeerInfo {
Some(stun_info) Some(stun_info)
}, },
inst_id: self.inst_id.to_string(), inst_id: self.inst_id.to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
} }
} }
} }