mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-11 17:47:20 +10:00
tools: Tailscale status
This commit is contained in:
@@ -2,8 +2,18 @@ package adapter
|
|||||||
|
|
||||||
import "context"
|
import "context"
|
||||||
|
|
||||||
type TailscaleStatusProvider interface {
|
type TailscaleEndpoint interface {
|
||||||
SubscribeTailscaleStatus(ctx context.Context, fn func(*TailscaleEndpointStatus)) error
|
SubscribeTailscaleStatus(ctx context.Context, fn func(*TailscaleEndpointStatus)) error
|
||||||
|
StartTailscalePing(ctx context.Context, peerIP string, fn func(*TailscalePingResult)) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type TailscalePingResult struct {
|
||||||
|
LatencyMs float64
|
||||||
|
IsDirect bool
|
||||||
|
Endpoint string
|
||||||
|
DERPRegionID int32
|
||||||
|
DERPRegionCode string
|
||||||
|
Error string
|
||||||
}
|
}
|
||||||
|
|
||||||
type TailscaleEndpointStatus struct {
|
type TailscaleEndpointStatus struct {
|
||||||
@@ -12,7 +22,14 @@ type TailscaleEndpointStatus struct {
|
|||||||
NetworkName string
|
NetworkName string
|
||||||
MagicDNSSuffix string
|
MagicDNSSuffix string
|
||||||
Self *TailscalePeer
|
Self *TailscalePeer
|
||||||
Users map[int64]*TailscaleUser
|
UserGroups []*TailscaleUserGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
type TailscaleUserGroup struct {
|
||||||
|
UserID int64
|
||||||
|
LoginName string
|
||||||
|
DisplayName string
|
||||||
|
ProfilePicURL string
|
||||||
Peers []*TailscalePeer
|
Peers []*TailscalePeer
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,10 +47,3 @@ type TailscalePeer struct {
|
|||||||
UserID int64
|
UserID int64
|
||||||
KeyExpiry int64
|
KeyExpiry int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type TailscaleUser struct {
|
|
||||||
ID int64
|
|
||||||
LoginName string
|
|
||||||
DisplayName string
|
|
||||||
ProfilePicURL string
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1085,31 +1085,6 @@ func (s *StartedService) GetStartedAt(ctx context.Context, empty *emptypb.Empty)
|
|||||||
return &StartedAt{StartedAt: s.startedAt.UnixMilli()}, nil
|
return &StartedAt{StartedAt: s.startedAt.UnixMilli()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StartedService) ListOutbounds(ctx context.Context, _ *emptypb.Empty) (*OutboundList, error) {
|
|
||||||
s.serviceAccess.RLock()
|
|
||||||
if s.serviceStatus.Status != ServiceStatus_STARTED {
|
|
||||||
s.serviceAccess.RUnlock()
|
|
||||||
return nil, os.ErrInvalid
|
|
||||||
}
|
|
||||||
boxService := s.instance
|
|
||||||
s.serviceAccess.RUnlock()
|
|
||||||
historyStorage := boxService.urlTestHistoryStorage
|
|
||||||
outbounds := boxService.instance.Outbound().Outbounds()
|
|
||||||
var list OutboundList
|
|
||||||
for _, ob := range outbounds {
|
|
||||||
item := &GroupItem{
|
|
||||||
Tag: ob.Tag(),
|
|
||||||
Type: ob.Type(),
|
|
||||||
}
|
|
||||||
if history := historyStorage.LoadURLTestHistory(adapter.OutboundTag(ob)); history != nil {
|
|
||||||
item.UrlTestTime = history.Time.Unix()
|
|
||||||
item.UrlTestDelay = int32(history.Delay)
|
|
||||||
}
|
|
||||||
list.Outbounds = append(list.Outbounds, item)
|
|
||||||
}
|
|
||||||
return &list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StartedService) SubscribeOutbounds(_ *emptypb.Empty, server grpc.ServerStreamingServer[OutboundList]) error {
|
func (s *StartedService) SubscribeOutbounds(_ *emptypb.Empty, server grpc.ServerStreamingServer[OutboundList]) error {
|
||||||
err := s.waitForStarted(server.Context())
|
err := s.waitForStarted(server.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1129,9 +1104,8 @@ func (s *StartedService) SubscribeOutbounds(_ *emptypb.Empty, server grpc.Server
|
|||||||
boxService := s.instance
|
boxService := s.instance
|
||||||
s.serviceAccess.RUnlock()
|
s.serviceAccess.RUnlock()
|
||||||
historyStorage := boxService.urlTestHistoryStorage
|
historyStorage := boxService.urlTestHistoryStorage
|
||||||
outbounds := boxService.instance.Outbound().Outbounds()
|
|
||||||
var list OutboundList
|
var list OutboundList
|
||||||
for _, ob := range outbounds {
|
for _, ob := range boxService.instance.Outbound().Outbounds() {
|
||||||
item := &GroupItem{
|
item := &GroupItem{
|
||||||
Tag: ob.Tag(),
|
Tag: ob.Tag(),
|
||||||
Type: ob.Type(),
|
Type: ob.Type(),
|
||||||
@@ -1142,6 +1116,17 @@ func (s *StartedService) SubscribeOutbounds(_ *emptypb.Empty, server grpc.Server
|
|||||||
}
|
}
|
||||||
list.Outbounds = append(list.Outbounds, item)
|
list.Outbounds = append(list.Outbounds, item)
|
||||||
}
|
}
|
||||||
|
for _, ep := range boxService.instance.Endpoint().Endpoints() {
|
||||||
|
item := &GroupItem{
|
||||||
|
Tag: ep.Tag(),
|
||||||
|
Type: ep.Type(),
|
||||||
|
}
|
||||||
|
if history := historyStorage.LoadURLTestHistory(adapter.OutboundTag(ep)); history != nil {
|
||||||
|
item.UrlTestTime = history.Time.Unix()
|
||||||
|
item.UrlTestDelay = int32(history.Delay)
|
||||||
|
}
|
||||||
|
list.Outbounds = append(list.Outbounds, item)
|
||||||
|
}
|
||||||
err = server.Send(&list)
|
err = server.Send(&list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1308,14 +1293,14 @@ func (s *StartedService) SubscribeTailscaleStatus(
|
|||||||
|
|
||||||
type tailscaleEndpoint struct {
|
type tailscaleEndpoint struct {
|
||||||
tag string
|
tag string
|
||||||
provider adapter.TailscaleStatusProvider
|
provider adapter.TailscaleEndpoint
|
||||||
}
|
}
|
||||||
var endpoints []tailscaleEndpoint
|
var endpoints []tailscaleEndpoint
|
||||||
for _, endpoint := range endpointManager.Endpoints() {
|
for _, endpoint := range endpointManager.Endpoints() {
|
||||||
if endpoint.Type() != C.TypeTailscale {
|
if endpoint.Type() != C.TypeTailscale {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
provider, loaded := endpoint.(adapter.TailscaleStatusProvider)
|
provider, loaded := endpoint.(adapter.TailscaleEndpoint)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1339,7 +1324,7 @@ func (s *StartedService) SubscribeTailscaleStatus(
|
|||||||
var waitGroup sync.WaitGroup
|
var waitGroup sync.WaitGroup
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
waitGroup.Add(1)
|
waitGroup.Add(1)
|
||||||
go func(tag string, provider adapter.TailscaleStatusProvider) {
|
go func(tag string, provider adapter.TailscaleEndpoint) {
|
||||||
defer waitGroup.Done()
|
defer waitGroup.Done()
|
||||||
_ = provider.SubscribeTailscaleStatus(ctx, func(endpointStatus *adapter.TailscaleEndpointStatus) {
|
_ = provider.SubscribeTailscaleStatus(ctx, func(endpointStatus *adapter.TailscaleEndpointStatus) {
|
||||||
select {
|
select {
|
||||||
@@ -1355,12 +1340,16 @@ func (s *StartedService) SubscribeTailscaleStatus(
|
|||||||
close(updates)
|
close(updates)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
var tags []string
|
||||||
statuses := make(map[string]*adapter.TailscaleEndpointStatus, len(endpoints))
|
statuses := make(map[string]*adapter.TailscaleEndpointStatus, len(endpoints))
|
||||||
for update := range updates {
|
for update := range updates {
|
||||||
|
if _, exists := statuses[update.tag]; !exists {
|
||||||
|
tags = append(tags, update.tag)
|
||||||
|
}
|
||||||
statuses[update.tag] = update.status
|
statuses[update.tag] = update.status
|
||||||
protoEndpoints := make([]*TailscaleEndpointStatus, 0, len(statuses))
|
protoEndpoints := make([]*TailscaleEndpointStatus, 0, len(statuses))
|
||||||
for tag, endpointStatus := range statuses {
|
for _, tag := range tags {
|
||||||
protoEndpoints = append(protoEndpoints, tailscaleEndpointStatusToProto(tag, endpointStatus))
|
protoEndpoints = append(protoEndpoints, tailscaleEndpointStatusToProto(tag, statuses[tag]))
|
||||||
}
|
}
|
||||||
sendErr := server.Send(&TailscaleStatusUpdate{
|
sendErr := server.Send(&TailscaleStatusUpdate{
|
||||||
Endpoints: protoEndpoints,
|
Endpoints: protoEndpoints,
|
||||||
@@ -1373,27 +1362,19 @@ func (s *StartedService) SubscribeTailscaleStatus(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func tailscaleEndpointStatusToProto(tag string, s *adapter.TailscaleEndpointStatus) *TailscaleEndpointStatus {
|
func tailscaleEndpointStatusToProto(tag string, s *adapter.TailscaleEndpointStatus) *TailscaleEndpointStatus {
|
||||||
userGroupMap := make(map[int64]*TailscaleUserGroup)
|
userGroups := make([]*TailscaleUserGroup, len(s.UserGroups))
|
||||||
for userID, user := range s.Users {
|
for i, group := range s.UserGroups {
|
||||||
userGroupMap[userID] = &TailscaleUserGroup{
|
peers := make([]*TailscalePeer, len(group.Peers))
|
||||||
UserID: userID,
|
for j, peer := range group.Peers {
|
||||||
LoginName: user.LoginName,
|
peers[j] = tailscalePeerToProto(peer)
|
||||||
DisplayName: user.DisplayName,
|
|
||||||
ProfilePicURL: user.ProfilePicURL,
|
|
||||||
}
|
}
|
||||||
|
userGroups[i] = &TailscaleUserGroup{
|
||||||
|
UserID: group.UserID,
|
||||||
|
LoginName: group.LoginName,
|
||||||
|
DisplayName: group.DisplayName,
|
||||||
|
ProfilePicURL: group.ProfilePicURL,
|
||||||
|
Peers: peers,
|
||||||
}
|
}
|
||||||
for _, peer := range s.Peers {
|
|
||||||
protoPeer := tailscalePeerToProto(peer)
|
|
||||||
group, loaded := userGroupMap[peer.UserID]
|
|
||||||
if !loaded {
|
|
||||||
group = &TailscaleUserGroup{UserID: peer.UserID}
|
|
||||||
userGroupMap[peer.UserID] = group
|
|
||||||
}
|
|
||||||
group.Peers = append(group.Peers, protoPeer)
|
|
||||||
}
|
|
||||||
userGroups := make([]*TailscaleUserGroup, 0, len(userGroupMap))
|
|
||||||
for _, group := range userGroupMap {
|
|
||||||
userGroups = append(userGroups, group)
|
|
||||||
}
|
}
|
||||||
result := &TailscaleEndpointStatus{
|
result := &TailscaleEndpointStatus{
|
||||||
EndpointTag: tag,
|
EndpointTag: tag,
|
||||||
@@ -1425,6 +1406,65 @@ func tailscalePeerToProto(peer *adapter.TailscalePeer) *TailscalePeer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *StartedService) StartTailscalePing(
|
||||||
|
request *TailscalePingRequest,
|
||||||
|
server grpc.ServerStreamingServer[TailscalePingResponse],
|
||||||
|
) error {
|
||||||
|
err := s.waitForStarted(server.Context())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.serviceAccess.RLock()
|
||||||
|
boxService := s.instance
|
||||||
|
s.serviceAccess.RUnlock()
|
||||||
|
|
||||||
|
endpointManager := service.FromContext[adapter.EndpointManager](boxService.ctx)
|
||||||
|
if endpointManager == nil {
|
||||||
|
return status.Error(codes.FailedPrecondition, "endpoint manager not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
var provider adapter.TailscaleEndpoint
|
||||||
|
if request.EndpointTag != "" {
|
||||||
|
endpoint, loaded := endpointManager.Get(request.EndpointTag)
|
||||||
|
if !loaded {
|
||||||
|
return status.Error(codes.NotFound, "endpoint not found: "+request.EndpointTag)
|
||||||
|
}
|
||||||
|
if endpoint.Type() != C.TypeTailscale {
|
||||||
|
return status.Error(codes.InvalidArgument, "endpoint is not Tailscale: "+request.EndpointTag)
|
||||||
|
}
|
||||||
|
pingProvider, loaded := endpoint.(adapter.TailscaleEndpoint)
|
||||||
|
if !loaded {
|
||||||
|
return status.Error(codes.FailedPrecondition, "endpoint does not support ping")
|
||||||
|
}
|
||||||
|
provider = pingProvider
|
||||||
|
} else {
|
||||||
|
for _, endpoint := range endpointManager.Endpoints() {
|
||||||
|
if endpoint.Type() != C.TypeTailscale {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pingProvider, loaded := endpoint.(adapter.TailscaleEndpoint)
|
||||||
|
if loaded {
|
||||||
|
provider = pingProvider
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if provider == nil {
|
||||||
|
return status.Error(codes.NotFound, "no Tailscale endpoint found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider.StartTailscalePing(server.Context(), request.PeerIP, func(result *adapter.TailscalePingResult) {
|
||||||
|
_ = server.Send(&TailscalePingResponse{
|
||||||
|
LatencyMs: result.LatencyMs,
|
||||||
|
IsDirect: result.IsDirect,
|
||||||
|
Endpoint: result.Endpoint,
|
||||||
|
DerpRegionID: result.DERPRegionID,
|
||||||
|
DerpRegionCode: result.DERPRegionCode,
|
||||||
|
Error: result.Error,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (s *StartedService) mustEmbedUnimplementedStartedServiceServer() {
|
func (s *StartedService) mustEmbedUnimplementedStartedServiceServer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2584,6 +2584,142 @@ func (x *TailscalePeer) GetKeyExpiry() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TailscalePingRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
EndpointTag string `protobuf:"bytes,1,opt,name=endpointTag,proto3" json:"endpointTag,omitempty"`
|
||||||
|
PeerIP string `protobuf:"bytes,2,opt,name=peerIP,proto3" json:"peerIP,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingRequest) Reset() {
|
||||||
|
*x = TailscalePingRequest{}
|
||||||
|
mi := &file_daemon_started_service_proto_msgTypes[35]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TailscalePingRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *TailscalePingRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_started_service_proto_msgTypes[35]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use TailscalePingRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*TailscalePingRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_started_service_proto_rawDescGZIP(), []int{35}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingRequest) GetEndpointTag() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.EndpointTag
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingRequest) GetPeerIP() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.PeerIP
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type TailscalePingResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
LatencyMs float64 `protobuf:"fixed64,1,opt,name=latencyMs,proto3" json:"latencyMs,omitempty"`
|
||||||
|
IsDirect bool `protobuf:"varint,2,opt,name=isDirect,proto3" json:"isDirect,omitempty"`
|
||||||
|
Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"`
|
||||||
|
DerpRegionID int32 `protobuf:"varint,4,opt,name=derpRegionID,proto3" json:"derpRegionID,omitempty"`
|
||||||
|
DerpRegionCode string `protobuf:"bytes,5,opt,name=derpRegionCode,proto3" json:"derpRegionCode,omitempty"`
|
||||||
|
Error string `protobuf:"bytes,6,opt,name=error,proto3" json:"error,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) Reset() {
|
||||||
|
*x = TailscalePingResponse{}
|
||||||
|
mi := &file_daemon_started_service_proto_msgTypes[36]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TailscalePingResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_daemon_started_service_proto_msgTypes[36]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use TailscalePingResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*TailscalePingResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_daemon_started_service_proto_rawDescGZIP(), []int{36}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) GetLatencyMs() float64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.LatencyMs
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) GetIsDirect() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.IsDirect
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) GetEndpoint() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Endpoint
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) GetDerpRegionID() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DerpRegionID
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) GetDerpRegionCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DerpRegionCode
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TailscalePingResponse) GetError() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Error
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type Log_Message struct {
|
type Log_Message struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Level LogLevel `protobuf:"varint,1,opt,name=level,proto3,enum=daemon.LogLevel" json:"level,omitempty"`
|
Level LogLevel `protobuf:"varint,1,opt,name=level,proto3,enum=daemon.LogLevel" json:"level,omitempty"`
|
||||||
@@ -2594,7 +2730,7 @@ type Log_Message struct {
|
|||||||
|
|
||||||
func (x *Log_Message) Reset() {
|
func (x *Log_Message) Reset() {
|
||||||
*x = Log_Message{}
|
*x = Log_Message{}
|
||||||
mi := &file_daemon_started_service_proto_msgTypes[35]
|
mi := &file_daemon_started_service_proto_msgTypes[37]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -2606,7 +2742,7 @@ func (x *Log_Message) String() string {
|
|||||||
func (*Log_Message) ProtoMessage() {}
|
func (*Log_Message) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Log_Message) ProtoReflect() protoreflect.Message {
|
func (x *Log_Message) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_daemon_started_service_proto_msgTypes[35]
|
mi := &file_daemon_started_service_proto_msgTypes[37]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -2839,7 +2975,17 @@ const file_daemon_started_service_proto_rawDesc = "" +
|
|||||||
"\arxBytes\x18\t \x01(\x03R\arxBytes\x12\x18\n" +
|
"\arxBytes\x18\t \x01(\x03R\arxBytes\x12\x18\n" +
|
||||||
"\atxBytes\x18\n" +
|
"\atxBytes\x18\n" +
|
||||||
" \x01(\x03R\atxBytes\x12\x1c\n" +
|
" \x01(\x03R\atxBytes\x12\x1c\n" +
|
||||||
"\tkeyExpiry\x18\v \x01(\x03R\tkeyExpiry*U\n" +
|
"\tkeyExpiry\x18\v \x01(\x03R\tkeyExpiry\"P\n" +
|
||||||
|
"\x14TailscalePingRequest\x12 \n" +
|
||||||
|
"\vendpointTag\x18\x01 \x01(\tR\vendpointTag\x12\x16\n" +
|
||||||
|
"\x06peerIP\x18\x02 \x01(\tR\x06peerIP\"\xcf\x01\n" +
|
||||||
|
"\x15TailscalePingResponse\x12\x1c\n" +
|
||||||
|
"\tlatencyMs\x18\x01 \x01(\x01R\tlatencyMs\x12\x1a\n" +
|
||||||
|
"\bisDirect\x18\x02 \x01(\bR\bisDirect\x12\x1a\n" +
|
||||||
|
"\bendpoint\x18\x03 \x01(\tR\bendpoint\x12\"\n" +
|
||||||
|
"\fderpRegionID\x18\x04 \x01(\x05R\fderpRegionID\x12&\n" +
|
||||||
|
"\x0ederpRegionCode\x18\x05 \x01(\tR\x0ederpRegionCode\x12\x14\n" +
|
||||||
|
"\x05error\x18\x06 \x01(\tR\x05error*U\n" +
|
||||||
"\bLogLevel\x12\t\n" +
|
"\bLogLevel\x12\t\n" +
|
||||||
"\x05PANIC\x10\x00\x12\t\n" +
|
"\x05PANIC\x10\x00\x12\t\n" +
|
||||||
"\x05FATAL\x10\x01\x12\t\n" +
|
"\x05FATAL\x10\x01\x12\t\n" +
|
||||||
@@ -2851,7 +2997,7 @@ const file_daemon_started_service_proto_rawDesc = "" +
|
|||||||
"\x13ConnectionEventType\x12\x18\n" +
|
"\x13ConnectionEventType\x12\x18\n" +
|
||||||
"\x14CONNECTION_EVENT_NEW\x10\x00\x12\x1b\n" +
|
"\x14CONNECTION_EVENT_NEW\x10\x00\x12\x1b\n" +
|
||||||
"\x17CONNECTION_EVENT_UPDATE\x10\x01\x12\x1b\n" +
|
"\x17CONNECTION_EVENT_UPDATE\x10\x01\x12\x1b\n" +
|
||||||
"\x17CONNECTION_EVENT_CLOSED\x10\x022\x83\x10\n" +
|
"\x17CONNECTION_EVENT_CLOSED\x10\x022\x99\x10\n" +
|
||||||
"\x0eStartedService\x12=\n" +
|
"\x0eStartedService\x12=\n" +
|
||||||
"\vStopService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12?\n" +
|
"\vStopService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12?\n" +
|
||||||
"\rReloadService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12K\n" +
|
"\rReloadService\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\x12K\n" +
|
||||||
@@ -2875,12 +3021,12 @@ const file_daemon_started_service_proto_rawDesc = "" +
|
|||||||
"\x0fCloseConnection\x12\x1e.daemon.CloseConnectionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12G\n" +
|
"\x0fCloseConnection\x12\x1e.daemon.CloseConnectionRequest\x1a\x16.google.protobuf.Empty\"\x00\x12G\n" +
|
||||||
"\x13CloseAllConnections\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00\x12M\n" +
|
"\x13CloseAllConnections\x12\x16.google.protobuf.Empty\x1a\x16.google.protobuf.Empty\"\x00\x12M\n" +
|
||||||
"\x15GetDeprecatedWarnings\x12\x16.google.protobuf.Empty\x1a\x1a.daemon.DeprecatedWarnings\"\x00\x12;\n" +
|
"\x15GetDeprecatedWarnings\x12\x16.google.protobuf.Empty\x1a\x1a.daemon.DeprecatedWarnings\"\x00\x12;\n" +
|
||||||
"\fGetStartedAt\x12\x16.google.protobuf.Empty\x1a\x11.daemon.StartedAt\"\x00\x12?\n" +
|
"\fGetStartedAt\x12\x16.google.protobuf.Empty\x1a\x11.daemon.StartedAt\"\x00\x12F\n" +
|
||||||
"\rListOutbounds\x12\x16.google.protobuf.Empty\x1a\x14.daemon.OutboundList\"\x00\x12F\n" +
|
|
||||||
"\x12SubscribeOutbounds\x12\x16.google.protobuf.Empty\x1a\x14.daemon.OutboundList\"\x000\x01\x12d\n" +
|
"\x12SubscribeOutbounds\x12\x16.google.protobuf.Empty\x1a\x14.daemon.OutboundList\"\x000\x01\x12d\n" +
|
||||||
"\x17StartNetworkQualityTest\x12!.daemon.NetworkQualityTestRequest\x1a\".daemon.NetworkQualityTestProgress\"\x000\x01\x12F\n" +
|
"\x17StartNetworkQualityTest\x12!.daemon.NetworkQualityTestRequest\x1a\".daemon.NetworkQualityTestProgress\"\x000\x01\x12F\n" +
|
||||||
"\rStartSTUNTest\x12\x17.daemon.STUNTestRequest\x1a\x18.daemon.STUNTestProgress\"\x000\x01\x12U\n" +
|
"\rStartSTUNTest\x12\x17.daemon.STUNTestRequest\x1a\x18.daemon.STUNTestProgress\"\x000\x01\x12U\n" +
|
||||||
"\x18SubscribeTailscaleStatus\x12\x16.google.protobuf.Empty\x1a\x1d.daemon.TailscaleStatusUpdate\"\x000\x01B%Z#github.com/sagernet/sing-box/daemonb\x06proto3"
|
"\x18SubscribeTailscaleStatus\x12\x16.google.protobuf.Empty\x1a\x1d.daemon.TailscaleStatusUpdate\"\x000\x01\x12U\n" +
|
||||||
|
"\x12StartTailscalePing\x12\x1c.daemon.TailscalePingRequest\x1a\x1d.daemon.TailscalePingResponse\"\x000\x01B%Z#github.com/sagernet/sing-box/daemonb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_daemon_started_service_proto_rawDescOnce sync.Once
|
file_daemon_started_service_proto_rawDescOnce sync.Once
|
||||||
@@ -2896,7 +3042,7 @@ func file_daemon_started_service_proto_rawDescGZIP() []byte {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
file_daemon_started_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
|
file_daemon_started_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
|
||||||
file_daemon_started_service_proto_msgTypes = make([]protoimpl.MessageInfo, 36)
|
file_daemon_started_service_proto_msgTypes = make([]protoimpl.MessageInfo, 38)
|
||||||
file_daemon_started_service_proto_goTypes = []any{
|
file_daemon_started_service_proto_goTypes = []any{
|
||||||
(LogLevel)(0), // 0: daemon.LogLevel
|
(LogLevel)(0), // 0: daemon.LogLevel
|
||||||
(ConnectionEventType)(0), // 1: daemon.ConnectionEventType
|
(ConnectionEventType)(0), // 1: daemon.ConnectionEventType
|
||||||
@@ -2937,14 +3083,16 @@ var (
|
|||||||
(*TailscaleEndpointStatus)(nil), // 36: daemon.TailscaleEndpointStatus
|
(*TailscaleEndpointStatus)(nil), // 36: daemon.TailscaleEndpointStatus
|
||||||
(*TailscaleUserGroup)(nil), // 37: daemon.TailscaleUserGroup
|
(*TailscaleUserGroup)(nil), // 37: daemon.TailscaleUserGroup
|
||||||
(*TailscalePeer)(nil), // 38: daemon.TailscalePeer
|
(*TailscalePeer)(nil), // 38: daemon.TailscalePeer
|
||||||
(*Log_Message)(nil), // 39: daemon.Log.Message
|
(*TailscalePingRequest)(nil), // 39: daemon.TailscalePingRequest
|
||||||
(*emptypb.Empty)(nil), // 40: google.protobuf.Empty
|
(*TailscalePingResponse)(nil), // 40: daemon.TailscalePingResponse
|
||||||
|
(*Log_Message)(nil), // 41: daemon.Log.Message
|
||||||
|
(*emptypb.Empty)(nil), // 42: google.protobuf.Empty
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var file_daemon_started_service_proto_depIdxs = []int32{
|
var file_daemon_started_service_proto_depIdxs = []int32{
|
||||||
2, // 0: daemon.ServiceStatus.status:type_name -> daemon.ServiceStatus.Type
|
2, // 0: daemon.ServiceStatus.status:type_name -> daemon.ServiceStatus.Type
|
||||||
39, // 1: daemon.Log.messages:type_name -> daemon.Log.Message
|
41, // 1: daemon.Log.messages:type_name -> daemon.Log.Message
|
||||||
0, // 2: daemon.DefaultLogLevel.level:type_name -> daemon.LogLevel
|
0, // 2: daemon.DefaultLogLevel.level:type_name -> daemon.LogLevel
|
||||||
11, // 3: daemon.Groups.group:type_name -> daemon.Group
|
11, // 3: daemon.Groups.group:type_name -> daemon.Group
|
||||||
12, // 4: daemon.Group.items:type_name -> daemon.GroupItem
|
12, // 4: daemon.Group.items:type_name -> daemon.GroupItem
|
||||||
@@ -2960,62 +3108,62 @@ var file_daemon_started_service_proto_depIdxs = []int32{
|
|||||||
37, // 14: daemon.TailscaleEndpointStatus.userGroups:type_name -> daemon.TailscaleUserGroup
|
37, // 14: daemon.TailscaleEndpointStatus.userGroups:type_name -> daemon.TailscaleUserGroup
|
||||||
38, // 15: daemon.TailscaleUserGroup.peers:type_name -> daemon.TailscalePeer
|
38, // 15: daemon.TailscaleUserGroup.peers:type_name -> daemon.TailscalePeer
|
||||||
0, // 16: daemon.Log.Message.level:type_name -> daemon.LogLevel
|
0, // 16: daemon.Log.Message.level:type_name -> daemon.LogLevel
|
||||||
40, // 17: daemon.StartedService.StopService:input_type -> google.protobuf.Empty
|
42, // 17: daemon.StartedService.StopService:input_type -> google.protobuf.Empty
|
||||||
40, // 18: daemon.StartedService.ReloadService:input_type -> google.protobuf.Empty
|
42, // 18: daemon.StartedService.ReloadService:input_type -> google.protobuf.Empty
|
||||||
40, // 19: daemon.StartedService.SubscribeServiceStatus:input_type -> google.protobuf.Empty
|
42, // 19: daemon.StartedService.SubscribeServiceStatus:input_type -> google.protobuf.Empty
|
||||||
40, // 20: daemon.StartedService.SubscribeLog:input_type -> google.protobuf.Empty
|
42, // 20: daemon.StartedService.SubscribeLog:input_type -> google.protobuf.Empty
|
||||||
40, // 21: daemon.StartedService.GetDefaultLogLevel:input_type -> google.protobuf.Empty
|
42, // 21: daemon.StartedService.GetDefaultLogLevel:input_type -> google.protobuf.Empty
|
||||||
40, // 22: daemon.StartedService.ClearLogs:input_type -> google.protobuf.Empty
|
42, // 22: daemon.StartedService.ClearLogs:input_type -> google.protobuf.Empty
|
||||||
6, // 23: daemon.StartedService.SubscribeStatus:input_type -> daemon.SubscribeStatusRequest
|
6, // 23: daemon.StartedService.SubscribeStatus:input_type -> daemon.SubscribeStatusRequest
|
||||||
40, // 24: daemon.StartedService.SubscribeGroups:input_type -> google.protobuf.Empty
|
42, // 24: daemon.StartedService.SubscribeGroups:input_type -> google.protobuf.Empty
|
||||||
40, // 25: daemon.StartedService.GetClashModeStatus:input_type -> google.protobuf.Empty
|
42, // 25: daemon.StartedService.GetClashModeStatus:input_type -> google.protobuf.Empty
|
||||||
40, // 26: daemon.StartedService.SubscribeClashMode:input_type -> google.protobuf.Empty
|
42, // 26: daemon.StartedService.SubscribeClashMode:input_type -> google.protobuf.Empty
|
||||||
16, // 27: daemon.StartedService.SetClashMode:input_type -> daemon.ClashMode
|
16, // 27: daemon.StartedService.SetClashMode:input_type -> daemon.ClashMode
|
||||||
13, // 28: daemon.StartedService.URLTest:input_type -> daemon.URLTestRequest
|
13, // 28: daemon.StartedService.URLTest:input_type -> daemon.URLTestRequest
|
||||||
14, // 29: daemon.StartedService.SelectOutbound:input_type -> daemon.SelectOutboundRequest
|
14, // 29: daemon.StartedService.SelectOutbound:input_type -> daemon.SelectOutboundRequest
|
||||||
15, // 30: daemon.StartedService.SetGroupExpand:input_type -> daemon.SetGroupExpandRequest
|
15, // 30: daemon.StartedService.SetGroupExpand:input_type -> daemon.SetGroupExpandRequest
|
||||||
40, // 31: daemon.StartedService.GetSystemProxyStatus:input_type -> google.protobuf.Empty
|
42, // 31: daemon.StartedService.GetSystemProxyStatus:input_type -> google.protobuf.Empty
|
||||||
19, // 32: daemon.StartedService.SetSystemProxyEnabled:input_type -> daemon.SetSystemProxyEnabledRequest
|
19, // 32: daemon.StartedService.SetSystemProxyEnabled:input_type -> daemon.SetSystemProxyEnabledRequest
|
||||||
20, // 33: daemon.StartedService.TriggerDebugCrash:input_type -> daemon.DebugCrashRequest
|
20, // 33: daemon.StartedService.TriggerDebugCrash:input_type -> daemon.DebugCrashRequest
|
||||||
40, // 34: daemon.StartedService.TriggerOOMReport:input_type -> google.protobuf.Empty
|
42, // 34: daemon.StartedService.TriggerOOMReport:input_type -> google.protobuf.Empty
|
||||||
21, // 35: daemon.StartedService.SubscribeConnections:input_type -> daemon.SubscribeConnectionsRequest
|
21, // 35: daemon.StartedService.SubscribeConnections:input_type -> daemon.SubscribeConnectionsRequest
|
||||||
26, // 36: daemon.StartedService.CloseConnection:input_type -> daemon.CloseConnectionRequest
|
26, // 36: daemon.StartedService.CloseConnection:input_type -> daemon.CloseConnectionRequest
|
||||||
40, // 37: daemon.StartedService.CloseAllConnections:input_type -> google.protobuf.Empty
|
42, // 37: daemon.StartedService.CloseAllConnections:input_type -> google.protobuf.Empty
|
||||||
40, // 38: daemon.StartedService.GetDeprecatedWarnings:input_type -> google.protobuf.Empty
|
42, // 38: daemon.StartedService.GetDeprecatedWarnings:input_type -> google.protobuf.Empty
|
||||||
40, // 39: daemon.StartedService.GetStartedAt:input_type -> google.protobuf.Empty
|
42, // 39: daemon.StartedService.GetStartedAt:input_type -> google.protobuf.Empty
|
||||||
40, // 40: daemon.StartedService.ListOutbounds:input_type -> google.protobuf.Empty
|
42, // 40: daemon.StartedService.SubscribeOutbounds:input_type -> google.protobuf.Empty
|
||||||
40, // 41: daemon.StartedService.SubscribeOutbounds:input_type -> google.protobuf.Empty
|
31, // 41: daemon.StartedService.StartNetworkQualityTest:input_type -> daemon.NetworkQualityTestRequest
|
||||||
31, // 42: daemon.StartedService.StartNetworkQualityTest:input_type -> daemon.NetworkQualityTestRequest
|
33, // 42: daemon.StartedService.StartSTUNTest:input_type -> daemon.STUNTestRequest
|
||||||
33, // 43: daemon.StartedService.StartSTUNTest:input_type -> daemon.STUNTestRequest
|
42, // 43: daemon.StartedService.SubscribeTailscaleStatus:input_type -> google.protobuf.Empty
|
||||||
40, // 44: daemon.StartedService.SubscribeTailscaleStatus:input_type -> google.protobuf.Empty
|
39, // 44: daemon.StartedService.StartTailscalePing:input_type -> daemon.TailscalePingRequest
|
||||||
40, // 45: daemon.StartedService.StopService:output_type -> google.protobuf.Empty
|
42, // 45: daemon.StartedService.StopService:output_type -> google.protobuf.Empty
|
||||||
40, // 46: daemon.StartedService.ReloadService:output_type -> google.protobuf.Empty
|
42, // 46: daemon.StartedService.ReloadService:output_type -> google.protobuf.Empty
|
||||||
4, // 47: daemon.StartedService.SubscribeServiceStatus:output_type -> daemon.ServiceStatus
|
4, // 47: daemon.StartedService.SubscribeServiceStatus:output_type -> daemon.ServiceStatus
|
||||||
7, // 48: daemon.StartedService.SubscribeLog:output_type -> daemon.Log
|
7, // 48: daemon.StartedService.SubscribeLog:output_type -> daemon.Log
|
||||||
8, // 49: daemon.StartedService.GetDefaultLogLevel:output_type -> daemon.DefaultLogLevel
|
8, // 49: daemon.StartedService.GetDefaultLogLevel:output_type -> daemon.DefaultLogLevel
|
||||||
40, // 50: daemon.StartedService.ClearLogs:output_type -> google.protobuf.Empty
|
42, // 50: daemon.StartedService.ClearLogs:output_type -> google.protobuf.Empty
|
||||||
9, // 51: daemon.StartedService.SubscribeStatus:output_type -> daemon.Status
|
9, // 51: daemon.StartedService.SubscribeStatus:output_type -> daemon.Status
|
||||||
10, // 52: daemon.StartedService.SubscribeGroups:output_type -> daemon.Groups
|
10, // 52: daemon.StartedService.SubscribeGroups:output_type -> daemon.Groups
|
||||||
17, // 53: daemon.StartedService.GetClashModeStatus:output_type -> daemon.ClashModeStatus
|
17, // 53: daemon.StartedService.GetClashModeStatus:output_type -> daemon.ClashModeStatus
|
||||||
16, // 54: daemon.StartedService.SubscribeClashMode:output_type -> daemon.ClashMode
|
16, // 54: daemon.StartedService.SubscribeClashMode:output_type -> daemon.ClashMode
|
||||||
40, // 55: daemon.StartedService.SetClashMode:output_type -> google.protobuf.Empty
|
42, // 55: daemon.StartedService.SetClashMode:output_type -> google.protobuf.Empty
|
||||||
40, // 56: daemon.StartedService.URLTest:output_type -> google.protobuf.Empty
|
42, // 56: daemon.StartedService.URLTest:output_type -> google.protobuf.Empty
|
||||||
40, // 57: daemon.StartedService.SelectOutbound:output_type -> google.protobuf.Empty
|
42, // 57: daemon.StartedService.SelectOutbound:output_type -> google.protobuf.Empty
|
||||||
40, // 58: daemon.StartedService.SetGroupExpand:output_type -> google.protobuf.Empty
|
42, // 58: daemon.StartedService.SetGroupExpand:output_type -> google.protobuf.Empty
|
||||||
18, // 59: daemon.StartedService.GetSystemProxyStatus:output_type -> daemon.SystemProxyStatus
|
18, // 59: daemon.StartedService.GetSystemProxyStatus:output_type -> daemon.SystemProxyStatus
|
||||||
40, // 60: daemon.StartedService.SetSystemProxyEnabled:output_type -> google.protobuf.Empty
|
42, // 60: daemon.StartedService.SetSystemProxyEnabled:output_type -> google.protobuf.Empty
|
||||||
40, // 61: daemon.StartedService.TriggerDebugCrash:output_type -> google.protobuf.Empty
|
42, // 61: daemon.StartedService.TriggerDebugCrash:output_type -> google.protobuf.Empty
|
||||||
40, // 62: daemon.StartedService.TriggerOOMReport:output_type -> google.protobuf.Empty
|
42, // 62: daemon.StartedService.TriggerOOMReport:output_type -> google.protobuf.Empty
|
||||||
23, // 63: daemon.StartedService.SubscribeConnections:output_type -> daemon.ConnectionEvents
|
23, // 63: daemon.StartedService.SubscribeConnections:output_type -> daemon.ConnectionEvents
|
||||||
40, // 64: daemon.StartedService.CloseConnection:output_type -> google.protobuf.Empty
|
42, // 64: daemon.StartedService.CloseConnection:output_type -> google.protobuf.Empty
|
||||||
40, // 65: daemon.StartedService.CloseAllConnections:output_type -> google.protobuf.Empty
|
42, // 65: daemon.StartedService.CloseAllConnections:output_type -> google.protobuf.Empty
|
||||||
27, // 66: daemon.StartedService.GetDeprecatedWarnings:output_type -> daemon.DeprecatedWarnings
|
27, // 66: daemon.StartedService.GetDeprecatedWarnings:output_type -> daemon.DeprecatedWarnings
|
||||||
29, // 67: daemon.StartedService.GetStartedAt:output_type -> daemon.StartedAt
|
29, // 67: daemon.StartedService.GetStartedAt:output_type -> daemon.StartedAt
|
||||||
30, // 68: daemon.StartedService.ListOutbounds:output_type -> daemon.OutboundList
|
30, // 68: daemon.StartedService.SubscribeOutbounds:output_type -> daemon.OutboundList
|
||||||
30, // 69: daemon.StartedService.SubscribeOutbounds:output_type -> daemon.OutboundList
|
32, // 69: daemon.StartedService.StartNetworkQualityTest:output_type -> daemon.NetworkQualityTestProgress
|
||||||
32, // 70: daemon.StartedService.StartNetworkQualityTest:output_type -> daemon.NetworkQualityTestProgress
|
34, // 70: daemon.StartedService.StartSTUNTest:output_type -> daemon.STUNTestProgress
|
||||||
34, // 71: daemon.StartedService.StartSTUNTest:output_type -> daemon.STUNTestProgress
|
35, // 71: daemon.StartedService.SubscribeTailscaleStatus:output_type -> daemon.TailscaleStatusUpdate
|
||||||
35, // 72: daemon.StartedService.SubscribeTailscaleStatus:output_type -> daemon.TailscaleStatusUpdate
|
40, // 72: daemon.StartedService.StartTailscalePing:output_type -> daemon.TailscalePingResponse
|
||||||
45, // [45:73] is the sub-list for method output_type
|
45, // [45:73] is the sub-list for method output_type
|
||||||
17, // [17:45] is the sub-list for method input_type
|
17, // [17:45] is the sub-list for method input_type
|
||||||
17, // [17:17] is the sub-list for extension type_name
|
17, // [17:17] is the sub-list for extension type_name
|
||||||
@@ -3034,7 +3182,7 @@ func file_daemon_started_service_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_daemon_started_service_proto_rawDesc), len(file_daemon_started_service_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_daemon_started_service_proto_rawDesc), len(file_daemon_started_service_proto_rawDesc)),
|
||||||
NumEnums: 4,
|
NumEnums: 4,
|
||||||
NumMessages: 36,
|
NumMessages: 38,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ service StartedService {
|
|||||||
rpc GetDeprecatedWarnings(google.protobuf.Empty) returns(DeprecatedWarnings) {}
|
rpc GetDeprecatedWarnings(google.protobuf.Empty) returns(DeprecatedWarnings) {}
|
||||||
rpc GetStartedAt(google.protobuf.Empty) returns(StartedAt) {}
|
rpc GetStartedAt(google.protobuf.Empty) returns(StartedAt) {}
|
||||||
|
|
||||||
rpc ListOutbounds(google.protobuf.Empty) returns (OutboundList) {}
|
|
||||||
rpc SubscribeOutbounds(google.protobuf.Empty) returns (stream OutboundList) {}
|
rpc SubscribeOutbounds(google.protobuf.Empty) returns (stream OutboundList) {}
|
||||||
rpc StartNetworkQualityTest(NetworkQualityTestRequest) returns (stream NetworkQualityTestProgress) {}
|
rpc StartNetworkQualityTest(NetworkQualityTestRequest) returns (stream NetworkQualityTestProgress) {}
|
||||||
rpc StartSTUNTest(STUNTestRequest) returns (stream STUNTestProgress) {}
|
rpc StartSTUNTest(STUNTestRequest) returns (stream STUNTestProgress) {}
|
||||||
rpc SubscribeTailscaleStatus(google.protobuf.Empty) returns (stream TailscaleStatusUpdate) {}
|
rpc SubscribeTailscaleStatus(google.protobuf.Empty) returns (stream TailscaleStatusUpdate) {}
|
||||||
|
rpc StartTailscalePing(TailscalePingRequest) returns (stream TailscalePingResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message ServiceStatus {
|
message ServiceStatus {
|
||||||
@@ -315,3 +315,17 @@ message TailscalePeer {
|
|||||||
int64 txBytes = 10;
|
int64 txBytes = 10;
|
||||||
int64 keyExpiry = 11;
|
int64 keyExpiry = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message TailscalePingRequest {
|
||||||
|
string endpointTag = 1;
|
||||||
|
string peerIP = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TailscalePingResponse {
|
||||||
|
double latencyMs = 1;
|
||||||
|
bool isDirect = 2;
|
||||||
|
string endpoint = 3;
|
||||||
|
int32 derpRegionID = 4;
|
||||||
|
string derpRegionCode = 5;
|
||||||
|
string error = 6;
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ const (
|
|||||||
StartedService_CloseAllConnections_FullMethodName = "/daemon.StartedService/CloseAllConnections"
|
StartedService_CloseAllConnections_FullMethodName = "/daemon.StartedService/CloseAllConnections"
|
||||||
StartedService_GetDeprecatedWarnings_FullMethodName = "/daemon.StartedService/GetDeprecatedWarnings"
|
StartedService_GetDeprecatedWarnings_FullMethodName = "/daemon.StartedService/GetDeprecatedWarnings"
|
||||||
StartedService_GetStartedAt_FullMethodName = "/daemon.StartedService/GetStartedAt"
|
StartedService_GetStartedAt_FullMethodName = "/daemon.StartedService/GetStartedAt"
|
||||||
StartedService_ListOutbounds_FullMethodName = "/daemon.StartedService/ListOutbounds"
|
|
||||||
StartedService_SubscribeOutbounds_FullMethodName = "/daemon.StartedService/SubscribeOutbounds"
|
StartedService_SubscribeOutbounds_FullMethodName = "/daemon.StartedService/SubscribeOutbounds"
|
||||||
StartedService_StartNetworkQualityTest_FullMethodName = "/daemon.StartedService/StartNetworkQualityTest"
|
StartedService_StartNetworkQualityTest_FullMethodName = "/daemon.StartedService/StartNetworkQualityTest"
|
||||||
StartedService_StartSTUNTest_FullMethodName = "/daemon.StartedService/StartSTUNTest"
|
StartedService_StartSTUNTest_FullMethodName = "/daemon.StartedService/StartSTUNTest"
|
||||||
StartedService_SubscribeTailscaleStatus_FullMethodName = "/daemon.StartedService/SubscribeTailscaleStatus"
|
StartedService_SubscribeTailscaleStatus_FullMethodName = "/daemon.StartedService/SubscribeTailscaleStatus"
|
||||||
|
StartedService_StartTailscalePing_FullMethodName = "/daemon.StartedService/StartTailscalePing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartedServiceClient is the client API for StartedService service.
|
// StartedServiceClient is the client API for StartedService service.
|
||||||
@@ -72,11 +72,11 @@ type StartedServiceClient interface {
|
|||||||
CloseAllConnections(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
CloseAllConnections(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||||
GetDeprecatedWarnings(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*DeprecatedWarnings, error)
|
GetDeprecatedWarnings(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*DeprecatedWarnings, error)
|
||||||
GetStartedAt(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StartedAt, error)
|
GetStartedAt(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StartedAt, error)
|
||||||
ListOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*OutboundList, error)
|
|
||||||
SubscribeOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OutboundList], error)
|
SubscribeOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OutboundList], error)
|
||||||
StartNetworkQualityTest(ctx context.Context, in *NetworkQualityTestRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[NetworkQualityTestProgress], error)
|
StartNetworkQualityTest(ctx context.Context, in *NetworkQualityTestRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[NetworkQualityTestProgress], error)
|
||||||
StartSTUNTest(ctx context.Context, in *STUNTestRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[STUNTestProgress], error)
|
StartSTUNTest(ctx context.Context, in *STUNTestRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[STUNTestProgress], error)
|
||||||
SubscribeTailscaleStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[TailscaleStatusUpdate], error)
|
SubscribeTailscaleStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[TailscaleStatusUpdate], error)
|
||||||
|
StartTailscalePing(ctx context.Context, in *TailscalePingRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[TailscalePingResponse], error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type startedServiceClient struct {
|
type startedServiceClient struct {
|
||||||
@@ -371,16 +371,6 @@ func (c *startedServiceClient) GetStartedAt(ctx context.Context, in *emptypb.Emp
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *startedServiceClient) ListOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*OutboundList, error) {
|
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
|
||||||
out := new(OutboundList)
|
|
||||||
err := c.cc.Invoke(ctx, StartedService_ListOutbounds_FullMethodName, in, out, cOpts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *startedServiceClient) SubscribeOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OutboundList], error) {
|
func (c *startedServiceClient) SubscribeOutbounds(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (grpc.ServerStreamingClient[OutboundList], error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
stream, err := c.cc.NewStream(ctx, &StartedService_ServiceDesc.Streams[6], StartedService_SubscribeOutbounds_FullMethodName, cOpts...)
|
stream, err := c.cc.NewStream(ctx, &StartedService_ServiceDesc.Streams[6], StartedService_SubscribeOutbounds_FullMethodName, cOpts...)
|
||||||
@@ -457,6 +447,25 @@ func (c *startedServiceClient) SubscribeTailscaleStatus(ctx context.Context, in
|
|||||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
type StartedService_SubscribeTailscaleStatusClient = grpc.ServerStreamingClient[TailscaleStatusUpdate]
|
type StartedService_SubscribeTailscaleStatusClient = grpc.ServerStreamingClient[TailscaleStatusUpdate]
|
||||||
|
|
||||||
|
func (c *startedServiceClient) StartTailscalePing(ctx context.Context, in *TailscalePingRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[TailscalePingResponse], error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
stream, err := c.cc.NewStream(ctx, &StartedService_ServiceDesc.Streams[10], StartedService_StartTailscalePing_FullMethodName, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
x := &grpc.GenericClientStream[TailscalePingRequest, TailscalePingResponse]{ClientStream: stream}
|
||||||
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := x.ClientStream.CloseSend(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
|
type StartedService_StartTailscalePingClient = grpc.ServerStreamingClient[TailscalePingResponse]
|
||||||
|
|
||||||
// StartedServiceServer is the server API for StartedService service.
|
// StartedServiceServer is the server API for StartedService service.
|
||||||
// All implementations must embed UnimplementedStartedServiceServer
|
// All implementations must embed UnimplementedStartedServiceServer
|
||||||
// for forward compatibility.
|
// for forward compatibility.
|
||||||
@@ -484,11 +493,11 @@ type StartedServiceServer interface {
|
|||||||
CloseAllConnections(context.Context, *emptypb.Empty) (*emptypb.Empty, error)
|
CloseAllConnections(context.Context, *emptypb.Empty) (*emptypb.Empty, error)
|
||||||
GetDeprecatedWarnings(context.Context, *emptypb.Empty) (*DeprecatedWarnings, error)
|
GetDeprecatedWarnings(context.Context, *emptypb.Empty) (*DeprecatedWarnings, error)
|
||||||
GetStartedAt(context.Context, *emptypb.Empty) (*StartedAt, error)
|
GetStartedAt(context.Context, *emptypb.Empty) (*StartedAt, error)
|
||||||
ListOutbounds(context.Context, *emptypb.Empty) (*OutboundList, error)
|
|
||||||
SubscribeOutbounds(*emptypb.Empty, grpc.ServerStreamingServer[OutboundList]) error
|
SubscribeOutbounds(*emptypb.Empty, grpc.ServerStreamingServer[OutboundList]) error
|
||||||
StartNetworkQualityTest(*NetworkQualityTestRequest, grpc.ServerStreamingServer[NetworkQualityTestProgress]) error
|
StartNetworkQualityTest(*NetworkQualityTestRequest, grpc.ServerStreamingServer[NetworkQualityTestProgress]) error
|
||||||
StartSTUNTest(*STUNTestRequest, grpc.ServerStreamingServer[STUNTestProgress]) error
|
StartSTUNTest(*STUNTestRequest, grpc.ServerStreamingServer[STUNTestProgress]) error
|
||||||
SubscribeTailscaleStatus(*emptypb.Empty, grpc.ServerStreamingServer[TailscaleStatusUpdate]) error
|
SubscribeTailscaleStatus(*emptypb.Empty, grpc.ServerStreamingServer[TailscaleStatusUpdate]) error
|
||||||
|
StartTailscalePing(*TailscalePingRequest, grpc.ServerStreamingServer[TailscalePingResponse]) error
|
||||||
mustEmbedUnimplementedStartedServiceServer()
|
mustEmbedUnimplementedStartedServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,10 +600,6 @@ func (UnimplementedStartedServiceServer) GetStartedAt(context.Context, *emptypb.
|
|||||||
return nil, status.Error(codes.Unimplemented, "method GetStartedAt not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetStartedAt not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UnimplementedStartedServiceServer) ListOutbounds(context.Context, *emptypb.Empty) (*OutboundList, error) {
|
|
||||||
return nil, status.Error(codes.Unimplemented, "method ListOutbounds not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (UnimplementedStartedServiceServer) SubscribeOutbounds(*emptypb.Empty, grpc.ServerStreamingServer[OutboundList]) error {
|
func (UnimplementedStartedServiceServer) SubscribeOutbounds(*emptypb.Empty, grpc.ServerStreamingServer[OutboundList]) error {
|
||||||
return status.Error(codes.Unimplemented, "method SubscribeOutbounds not implemented")
|
return status.Error(codes.Unimplemented, "method SubscribeOutbounds not implemented")
|
||||||
}
|
}
|
||||||
@@ -610,6 +615,10 @@ func (UnimplementedStartedServiceServer) StartSTUNTest(*STUNTestRequest, grpc.Se
|
|||||||
func (UnimplementedStartedServiceServer) SubscribeTailscaleStatus(*emptypb.Empty, grpc.ServerStreamingServer[TailscaleStatusUpdate]) error {
|
func (UnimplementedStartedServiceServer) SubscribeTailscaleStatus(*emptypb.Empty, grpc.ServerStreamingServer[TailscaleStatusUpdate]) error {
|
||||||
return status.Error(codes.Unimplemented, "method SubscribeTailscaleStatus not implemented")
|
return status.Error(codes.Unimplemented, "method SubscribeTailscaleStatus not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (UnimplementedStartedServiceServer) StartTailscalePing(*TailscalePingRequest, grpc.ServerStreamingServer[TailscalePingResponse]) error {
|
||||||
|
return status.Error(codes.Unimplemented, "method StartTailscalePing not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedStartedServiceServer) mustEmbedUnimplementedStartedServiceServer() {}
|
func (UnimplementedStartedServiceServer) mustEmbedUnimplementedStartedServiceServer() {}
|
||||||
func (UnimplementedStartedServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedStartedServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
@@ -1003,24 +1012,6 @@ func _StartedService_GetStartedAt_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _StartedService_ListOutbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(emptypb.Empty)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(StartedServiceServer).ListOutbounds(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: StartedService_ListOutbounds_FullMethodName,
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(StartedServiceServer).ListOutbounds(ctx, req.(*emptypb.Empty))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _StartedService_SubscribeOutbounds_Handler(srv interface{}, stream grpc.ServerStream) error {
|
func _StartedService_SubscribeOutbounds_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
m := new(emptypb.Empty)
|
m := new(emptypb.Empty)
|
||||||
if err := stream.RecvMsg(m); err != nil {
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
@@ -1065,6 +1056,17 @@ func _StartedService_SubscribeTailscaleStatus_Handler(srv interface{}, stream gr
|
|||||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
type StartedService_SubscribeTailscaleStatusServer = grpc.ServerStreamingServer[TailscaleStatusUpdate]
|
type StartedService_SubscribeTailscaleStatusServer = grpc.ServerStreamingServer[TailscaleStatusUpdate]
|
||||||
|
|
||||||
|
func _StartedService_StartTailscalePing_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
|
m := new(TailscalePingRequest)
|
||||||
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return srv.(StartedServiceServer).StartTailscalePing(m, &grpc.GenericServerStream[TailscalePingRequest, TailscalePingResponse]{ServerStream: stream})
|
||||||
|
}
|
||||||
|
|
||||||
|
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||||
|
type StartedService_StartTailscalePingServer = grpc.ServerStreamingServer[TailscalePingResponse]
|
||||||
|
|
||||||
// StartedService_ServiceDesc is the grpc.ServiceDesc for StartedService service.
|
// StartedService_ServiceDesc is the grpc.ServiceDesc for StartedService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@@ -1140,10 +1142,6 @@ var StartedService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "GetStartedAt",
|
MethodName: "GetStartedAt",
|
||||||
Handler: _StartedService_GetStartedAt_Handler,
|
Handler: _StartedService_GetStartedAt_Handler,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MethodName: "ListOutbounds",
|
|
||||||
Handler: _StartedService_ListOutbounds_Handler,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{
|
Streams: []grpc.StreamDesc{
|
||||||
{
|
{
|
||||||
@@ -1196,6 +1194,11 @@ var StartedService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
Handler: _StartedService_SubscribeTailscaleStatus_Handler,
|
Handler: _StartedService_SubscribeTailscaleStatus_Handler,
|
||||||
ServerStreams: true,
|
ServerStreams: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
StreamName: "StartTailscalePing",
|
||||||
|
Handler: _StartedService_StartTailscalePing_Handler,
|
||||||
|
ServerStreams: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Metadata: "daemon/started_service.proto",
|
Metadata: "daemon/started_service.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ import (
|
|||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -626,16 +628,6 @@ func (c *CommandClient) SetGroupExpand(groupTag string, isExpand bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandClient) ListOutbounds() (OutboundGroupItemIterator, error) {
|
|
||||||
return callWithResult(c, func(client daemon.StartedServiceClient) (OutboundGroupItemIterator, error) {
|
|
||||||
list, err := client.ListOutbounds(context.Background(), &emptypb.Empty{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return outboundGroupItemListFromGRPC(list), nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CommandClient) StartNetworkQualityTest(configURL string, outboundTag string, serial bool, maxRuntimeSeconds int32, http3 bool, handler NetworkQualityTestHandler) error {
|
func (c *CommandClient) StartNetworkQualityTest(configURL string, outboundTag string, serial bool, maxRuntimeSeconds int32, http3 bool, handler NetworkQualityTestHandler) error {
|
||||||
client, err := c.getClientForCall()
|
client, err := c.getClientForCall()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -736,9 +728,37 @@ func (c *CommandClient) SubscribeTailscaleStatus(handler TailscaleStatusHandler)
|
|||||||
for {
|
for {
|
||||||
event, recvErr := stream.Recv()
|
event, recvErr := stream.Recv()
|
||||||
if recvErr != nil {
|
if recvErr != nil {
|
||||||
|
if status.Code(recvErr) == codes.NotFound {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
handler.OnError(recvErr.Error())
|
handler.OnError(recvErr.Error())
|
||||||
return recvErr
|
return recvErr
|
||||||
}
|
}
|
||||||
handler.OnStatusUpdate(tailscaleStatusUpdateFromGRPC(event))
|
handler.OnStatusUpdate(tailscaleStatusUpdateFromGRPC(event))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CommandClient) StartTailscalePing(endpointTag string, peerIP string, handler TailscalePingHandler) error {
|
||||||
|
client, err := c.getClientForCall()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.standalone {
|
||||||
|
defer c.closeConnection()
|
||||||
|
}
|
||||||
|
stream, err := client.StartTailscalePing(context.Background(), &daemon.TailscalePingRequest{
|
||||||
|
EndpointTag: endpointTag,
|
||||||
|
PeerIP: peerIP,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
event, recvErr := stream.Recv()
|
||||||
|
if recvErr != nil {
|
||||||
|
handler.OnError(recvErr.Error())
|
||||||
|
return recvErr
|
||||||
|
}
|
||||||
|
handler.OnPingResult(tailscalePingResultFromGRPC(event))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
28
experimental/libbox/command_types_tailscale_ping.go
Normal file
28
experimental/libbox/command_types_tailscale_ping.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import "github.com/sagernet/sing-box/daemon"
|
||||||
|
|
||||||
|
type TailscalePingResult struct {
|
||||||
|
LatencyMs float64
|
||||||
|
IsDirect bool
|
||||||
|
Endpoint string
|
||||||
|
DERPRegionID int32
|
||||||
|
DERPRegionCode string
|
||||||
|
Error string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TailscalePingHandler interface {
|
||||||
|
OnPingResult(result *TailscalePingResult)
|
||||||
|
OnError(message string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tailscalePingResultFromGRPC(response *daemon.TailscalePingResponse) *TailscalePingResult {
|
||||||
|
return &TailscalePingResult{
|
||||||
|
LatencyMs: response.LatencyMs,
|
||||||
|
IsDirect: response.IsDirect,
|
||||||
|
Endpoint: response.Endpoint,
|
||||||
|
DERPRegionID: response.DerpRegionID,
|
||||||
|
DERPRegionCode: response.DerpRegionCode,
|
||||||
|
Error: response.Error,
|
||||||
|
}
|
||||||
|
}
|
||||||
16
protocol/tailscale/hostinfo_tvos.go
Normal file
16
protocol/tailscale/hostinfo_tvos.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//go:build with_gvisor && tvos
|
||||||
|
|
||||||
|
package tailscale
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
|
||||||
|
"github.com/sagernet/tailscale/types/lazy"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname isAppleTV github.com/sagernet/tailscale/version.isAppleTV
|
||||||
|
var isAppleTV lazy.SyncValue[bool]
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
isAppleTV.Set(true)
|
||||||
|
}
|
||||||
55
protocol/tailscale/ping.go
Normal file
55
protocol/tailscale/ping.go
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
//go:build with_gvisor
|
||||||
|
|
||||||
|
package tailscale
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/tailscale/ipn/ipnstate"
|
||||||
|
"github.com/sagernet/tailscale/tailcfg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t *Endpoint) StartTailscalePing(ctx context.Context, peerIP string, fn func(*adapter.TailscalePingResult)) error {
|
||||||
|
ip, err := netip.ParseAddr(peerIP)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
localClient, err := t.server.LocalClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ticker := time.NewTicker(time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
result, pingErr := localClient.Ping(ctx, ip, tailcfg.PingDisco)
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
if pingErr != nil {
|
||||||
|
fn(&adapter.TailscalePingResult{
|
||||||
|
Error: pingErr.Error(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
fn(convertPingResult(result))
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-ticker.C:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertPingResult(result *ipnstate.PingResult) *adapter.TailscalePingResult {
|
||||||
|
return &adapter.TailscalePingResult{
|
||||||
|
LatencyMs: result.LatencySeconds * 1000,
|
||||||
|
IsDirect: result.Endpoint != "",
|
||||||
|
Endpoint: result.Endpoint,
|
||||||
|
DERPRegionID: int32(result.DERPRegionID),
|
||||||
|
DERPRegionCode: result.DERPRegionCode,
|
||||||
|
Error: result.Err,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,14 +4,14 @@ package tailscale
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/tailscale/ipn"
|
"github.com/sagernet/tailscale/ipn"
|
||||||
"github.com/sagernet/tailscale/ipn/ipnstate"
|
"github.com/sagernet/tailscale/ipn/ipnstate"
|
||||||
"github.com/sagernet/tailscale/tailcfg"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ adapter.TailscaleStatusProvider = (*Endpoint)(nil)
|
var _ adapter.TailscaleEndpoint = (*Endpoint)(nil)
|
||||||
|
|
||||||
func (t *Endpoint) SubscribeTailscaleStatus(ctx context.Context, fn func(*adapter.TailscaleEndpointStatus)) error {
|
func (t *Endpoint) SubscribeTailscaleStatus(ctx context.Context, fn func(*adapter.TailscaleEndpointStatus)) error {
|
||||||
localBackend := t.server.ExportLocalBackend()
|
localBackend := t.server.ExportLocalBackend()
|
||||||
@@ -46,13 +46,35 @@ func convertTailscaleStatus(status *ipnstate.Status) *adapter.TailscaleEndpointS
|
|||||||
if status.Self != nil {
|
if status.Self != nil {
|
||||||
result.Self = convertTailscalePeer(status.Self)
|
result.Self = convertTailscalePeer(status.Self)
|
||||||
}
|
}
|
||||||
result.Users = make(map[int64]*adapter.TailscaleUser, len(status.User))
|
groupIndex := make(map[int64]*adapter.TailscaleUserGroup)
|
||||||
for userID, profile := range status.User {
|
for _, peerKey := range status.Peers() {
|
||||||
result.Users[int64(userID)] = convertTailscaleUser(userID, profile)
|
peer := status.Peer[peerKey]
|
||||||
|
userID := int64(peer.UserID)
|
||||||
|
group, loaded := groupIndex[userID]
|
||||||
|
if !loaded {
|
||||||
|
group = &adapter.TailscaleUserGroup{
|
||||||
|
UserID: userID,
|
||||||
}
|
}
|
||||||
result.Peers = make([]*adapter.TailscalePeer, 0, len(status.Peer))
|
if profile, hasProfile := status.User[peer.UserID]; hasProfile {
|
||||||
for _, peer := range status.Peer {
|
group.LoginName = profile.LoginName
|
||||||
result.Peers = append(result.Peers, convertTailscalePeer(peer))
|
group.DisplayName = profile.DisplayName
|
||||||
|
group.ProfilePicURL = profile.ProfilePicURL
|
||||||
|
}
|
||||||
|
groupIndex[userID] = group
|
||||||
|
result.UserGroups = append(result.UserGroups, group)
|
||||||
|
}
|
||||||
|
group.Peers = append(group.Peers, convertTailscalePeer(peer))
|
||||||
|
}
|
||||||
|
for _, group := range result.UserGroups {
|
||||||
|
slices.SortStableFunc(group.Peers, func(a, b *adapter.TailscalePeer) int {
|
||||||
|
if a.Online != b.Online {
|
||||||
|
if a.Online {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -81,12 +103,3 @@ func convertTailscalePeer(peer *ipnstate.PeerStatus) *adapter.TailscalePeer {
|
|||||||
KeyExpiry: keyExpiry,
|
KeyExpiry: keyExpiry,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertTailscaleUser(id tailcfg.UserID, profile tailcfg.UserProfile) *adapter.TailscaleUser {
|
|
||||||
return &adapter.TailscaleUser{
|
|
||||||
ID: int64(id),
|
|
||||||
LoginName: profile.LoginName,
|
|
||||||
DisplayName: profile.DisplayName,
|
|
||||||
ProfilePicURL: profile.ProfilePicURL,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user