mirror of
https://mirror.suhoan.cn/https://github.com/EasyTier/EasyTier.git
synced 2025-12-12 20:57:26 +08:00
✨ 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:
@@ -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: 运行中
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user