tools: Tailscale status

This commit is contained in:
世界
2026-04-09 19:34:27 +08:00
parent 47f09c96a9
commit d70bfb9bb6
10 changed files with 988 additions and 100 deletions
+22
View File
@@ -720,3 +720,25 @@ func (c *CommandClient) StartSTUNTest(server string, outboundTag string, handler
handler.OnProgress(stunTestProgressFromGRPC(event))
}
}
func (c *CommandClient) SubscribeTailscaleStatus(handler TailscaleStatusHandler) error {
client, err := c.getClientForCall()
if err != nil {
return err
}
if c.standalone {
defer c.closeConnection()
}
stream, err := client.SubscribeTailscaleStatus(context.Background(), &emptypb.Empty{})
if err != nil {
return err
}
for {
event, recvErr := stream.Recv()
if recvErr != nil {
handler.OnError(recvErr.Error())
return recvErr
}
handler.OnStatusUpdate(tailscaleStatusUpdateFromGRPC(event))
}
}
@@ -0,0 +1,132 @@
package libbox
import "github.com/sagernet/sing-box/daemon"
type TailscaleStatusUpdate struct {
endpoints []*TailscaleEndpointStatus
}
func (u *TailscaleStatusUpdate) Endpoints() TailscaleEndpointStatusIterator {
return newIterator(u.endpoints)
}
type TailscaleEndpointStatusIterator interface {
Next() *TailscaleEndpointStatus
HasNext() bool
}
type TailscaleEndpointStatus struct {
EndpointTag string
BackendState string
AuthURL string
NetworkName string
MagicDNSSuffix string
Self *TailscalePeer
userGroups []*TailscaleUserGroup
}
func (s *TailscaleEndpointStatus) UserGroups() TailscaleUserGroupIterator {
return newIterator(s.userGroups)
}
type TailscaleUserGroupIterator interface {
Next() *TailscaleUserGroup
HasNext() bool
}
type TailscaleUserGroup struct {
UserID int64
LoginName string
DisplayName string
ProfilePicURL string
peers []*TailscalePeer
}
func (g *TailscaleUserGroup) Peers() TailscalePeerIterator {
return newIterator(g.peers)
}
type TailscalePeerIterator interface {
Next() *TailscalePeer
HasNext() bool
}
type TailscalePeer struct {
HostName string
DNSName string
OS string
tailscaleIPs []string
Online bool
ExitNode bool
ExitNodeOption bool
Active bool
RxBytes int64
TxBytes int64
KeyExpiry int64
}
func (p *TailscalePeer) TailscaleIPs() StringIterator {
return newIterator(p.tailscaleIPs)
}
type TailscaleStatusHandler interface {
OnStatusUpdate(status *TailscaleStatusUpdate)
OnError(message string)
}
func tailscaleStatusUpdateFromGRPC(update *daemon.TailscaleStatusUpdate) *TailscaleStatusUpdate {
endpoints := make([]*TailscaleEndpointStatus, len(update.Endpoints))
for i, endpoint := range update.Endpoints {
endpoints[i] = tailscaleEndpointStatusFromGRPC(endpoint)
}
return &TailscaleStatusUpdate{endpoints: endpoints}
}
func tailscaleEndpointStatusFromGRPC(status *daemon.TailscaleEndpointStatus) *TailscaleEndpointStatus {
userGroups := make([]*TailscaleUserGroup, len(status.UserGroups))
for i, group := range status.UserGroups {
userGroups[i] = tailscaleUserGroupFromGRPC(group)
}
result := &TailscaleEndpointStatus{
EndpointTag: status.EndpointTag,
BackendState: status.BackendState,
AuthURL: status.AuthURL,
NetworkName: status.NetworkName,
MagicDNSSuffix: status.MagicDNSSuffix,
userGroups: userGroups,
}
if status.Self != nil {
result.Self = tailscalePeerFromGRPC(status.Self)
}
return result
}
func tailscaleUserGroupFromGRPC(group *daemon.TailscaleUserGroup) *TailscaleUserGroup {
peers := make([]*TailscalePeer, len(group.Peers))
for i, peer := range group.Peers {
peers[i] = tailscalePeerFromGRPC(peer)
}
return &TailscaleUserGroup{
UserID: group.UserID,
LoginName: group.LoginName,
DisplayName: group.DisplayName,
ProfilePicURL: group.ProfilePicURL,
peers: peers,
}
}
func tailscalePeerFromGRPC(peer *daemon.TailscalePeer) *TailscalePeer {
return &TailscalePeer{
HostName: peer.HostName,
DNSName: peer.DnsName,
OS: peer.Os,
tailscaleIPs: peer.TailscaleIPs,
Online: peer.Online,
ExitNode: peer.ExitNode,
ExitNodeOption: peer.ExitNodeOption,
Active: peer.Active,
RxBytes: peer.RxBytes,
TxBytes: peer.TxBytes,
KeyExpiry: peer.KeyExpiry,
}
}
+5 -2
View File
@@ -1,9 +1,12 @@
package libbox
import "time"
import (
"time"
"unsafe"
)
func TriggerGoPanic() {
time.AfterFunc(200*time.Millisecond, func() {
panic("debug go crash")
*(*int)(unsafe.Pointer(uintptr(0))) = 0
})
}
+5
View File
@@ -12,6 +12,7 @@ import (
"github.com/sagernet/sing-box/common/networkquality"
"github.com/sagernet/sing-box/common/stun"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/experimental/locale"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/service/oomkiller"
@@ -181,6 +182,10 @@ func FormatNATFiltering(value int32) string {
return stun.NATFiltering(value).String()
}
func FormatFQDN(fqdn string) string {
return dns.FqdnToDomain(fqdn)
}
func ProxyDisplayType(proxyType string) string {
return C.ProxyDisplayName(proxyType)
}