tools: Tailscale status
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user