From 59dc2cee2ed3ca5e7e8418f36db9477b20d7a991 Mon Sep 17 00:00:00 2001 From: MouMeng <2482924065@qq.com> Date: Fri, 23 Jan 2026 23:44:16 +0800 Subject: [PATCH] API: Add ListRule() for routing (#5569) https://github.com/XTLS/Xray-core/pull/5569#issuecomment-3766310407 --- app/router/command/command.go | 15 + app/router/command/command.pb.go | 589 ++++++++++++++------------ app/router/command/command.proto | 13 + app/router/command/command_grpc.pb.go | 56 ++- app/router/router.go | 17 +- features/routing/router.go | 6 + main/commands/all/api/api.go | 1 + main/commands/all/api/rules_list.go | 43 ++ 8 files changed, 457 insertions(+), 283 deletions(-) create mode 100644 main/commands/all/api/rules_list.go diff --git a/app/router/command/command.go b/app/router/command/command.go index fd9caa22..c0974553 100644 --- a/app/router/command/command.go +++ b/app/router/command/command.go @@ -60,6 +60,7 @@ func (s *routingServer) AddRule(ctx context.Context, request *AddRuleRequest) (* return nil, errors.New("unsupported router implementation") } + func (s *routingServer) RemoveRule(ctx context.Context, request *RemoveRuleRequest) (*RemoveRuleResponse, error) { if bo, ok := s.router.(routing.Router); ok { return &RemoveRuleResponse{}, bo.RemoveRule(request.RuleTag) @@ -67,6 +68,20 @@ func (s *routingServer) RemoveRule(ctx context.Context, request *RemoveRuleReque return nil, errors.New("unsupported router implementation") } +func (s *routingServer) ListRule(ctx context.Context, request *ListRuleRequest) (*ListRuleResponse, error) { + if bo, ok := s.router.(routing.Router); ok { + response := &ListRuleResponse{} + for _, v := range bo.ListRule() { + response.Rules = append(response.Rules, &ListRuleItem{ + Tag: v.GetOutboundTag(), + RuleTag: v.GetRuleTag(), + }) + } + return response, nil + } + return nil, errors.New("unsupported router implementation") +} + // NewRoutingServer creates a statistics service with statistics manager. func NewRoutingServer(router routing.Router, routingStats stats.Channel) RoutingServiceServer { return &routingServer{ diff --git a/app/router/command/command.pb.go b/app/router/command/command.pb.go index b8b1864d..30fe39cd 100644 --- a/app/router/command/command.pb.go +++ b/app/router/command/command.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.2 +// protoc-gen-go v1.36.11 +// protoc v6.33.2 // source: app/router/command/command.proto package command @@ -13,6 +13,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + unsafe "unsafe" ) const ( @@ -26,25 +27,24 @@ const ( // It conforms to the structure of xray.features.routing.Context and // xray.features.routing.Route. type RoutingContext struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - InboundTag string `protobuf:"bytes,1,opt,name=InboundTag,proto3" json:"InboundTag,omitempty"` - Network net.Network `protobuf:"varint,2,opt,name=Network,proto3,enum=xray.common.net.Network" json:"Network,omitempty"` - SourceIPs [][]byte `protobuf:"bytes,3,rep,name=SourceIPs,proto3" json:"SourceIPs,omitempty"` - TargetIPs [][]byte `protobuf:"bytes,4,rep,name=TargetIPs,proto3" json:"TargetIPs,omitempty"` - SourcePort uint32 `protobuf:"varint,5,opt,name=SourcePort,proto3" json:"SourcePort,omitempty"` - TargetPort uint32 `protobuf:"varint,6,opt,name=TargetPort,proto3" json:"TargetPort,omitempty"` - TargetDomain string `protobuf:"bytes,7,opt,name=TargetDomain,proto3" json:"TargetDomain,omitempty"` - Protocol string `protobuf:"bytes,8,opt,name=Protocol,proto3" json:"Protocol,omitempty"` - User string `protobuf:"bytes,9,opt,name=User,proto3" json:"User,omitempty"` - Attributes map[string]string `protobuf:"bytes,10,rep,name=Attributes,proto3" json:"Attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"` - OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,omitempty"` - LocalIPs [][]byte `protobuf:"bytes,13,rep,name=LocalIPs,proto3" json:"LocalIPs,omitempty"` - LocalPort uint32 `protobuf:"varint,14,opt,name=LocalPort,proto3" json:"LocalPort,omitempty"` - VlessRoute uint32 `protobuf:"varint,15,opt,name=VlessRoute,proto3" json:"VlessRoute,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + InboundTag string `protobuf:"bytes,1,opt,name=InboundTag,proto3" json:"InboundTag,omitempty"` + Network net.Network `protobuf:"varint,2,opt,name=Network,proto3,enum=xray.common.net.Network" json:"Network,omitempty"` + SourceIPs [][]byte `protobuf:"bytes,3,rep,name=SourceIPs,proto3" json:"SourceIPs,omitempty"` + TargetIPs [][]byte `protobuf:"bytes,4,rep,name=TargetIPs,proto3" json:"TargetIPs,omitempty"` + SourcePort uint32 `protobuf:"varint,5,opt,name=SourcePort,proto3" json:"SourcePort,omitempty"` + TargetPort uint32 `protobuf:"varint,6,opt,name=TargetPort,proto3" json:"TargetPort,omitempty"` + TargetDomain string `protobuf:"bytes,7,opt,name=TargetDomain,proto3" json:"TargetDomain,omitempty"` + Protocol string `protobuf:"bytes,8,opt,name=Protocol,proto3" json:"Protocol,omitempty"` + User string `protobuf:"bytes,9,opt,name=User,proto3" json:"User,omitempty"` + Attributes map[string]string `protobuf:"bytes,10,rep,name=Attributes,proto3" json:"Attributes,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"` + OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,omitempty"` + LocalIPs [][]byte `protobuf:"bytes,13,rep,name=LocalIPs,proto3" json:"LocalIPs,omitempty"` + LocalPort uint32 `protobuf:"varint,14,opt,name=LocalPort,proto3" json:"LocalPort,omitempty"` + VlessRoute uint32 `protobuf:"varint,15,opt,name=VlessRoute,proto3" json:"VlessRoute,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoutingContext) Reset() { @@ -201,11 +201,10 @@ func (x *RoutingContext) GetVlessRoute() uint32 { // // * If FieldSelectors is left empty, all fields will be returned. type SubscribeRoutingStatsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - FieldSelectors []string `protobuf:"bytes,1,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + FieldSelectors []string `protobuf:"bytes,1,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SubscribeRoutingStatsRequest) Reset() { @@ -253,13 +252,12 @@ func (x *SubscribeRoutingStatsRequest) GetFieldSelectors() []string { // * PublishResult broadcasts the routing result to routing statistics channel // if set true. type TestRouteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RoutingContext *RoutingContext `protobuf:"bytes,1,opt,name=RoutingContext,proto3" json:"RoutingContext,omitempty"` - FieldSelectors []string `protobuf:"bytes,2,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"` - PublishResult bool `protobuf:"varint,3,opt,name=PublishResult,proto3" json:"PublishResult,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + RoutingContext *RoutingContext `protobuf:"bytes,1,opt,name=RoutingContext,proto3" json:"RoutingContext,omitempty"` + FieldSelectors []string `protobuf:"bytes,2,rep,name=FieldSelectors,proto3" json:"FieldSelectors,omitempty"` + PublishResult bool `protobuf:"varint,3,opt,name=PublishResult,proto3" json:"PublishResult,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *TestRouteRequest) Reset() { @@ -314,11 +312,10 @@ func (x *TestRouteRequest) GetPublishResult() bool { } type PrincipleTargetInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Tag []string `protobuf:"bytes,1,rep,name=tag,proto3" json:"tag,omitempty"` unknownFields protoimpl.UnknownFields - - Tag []string `protobuf:"bytes,1,rep,name=tag,proto3" json:"tag,omitempty"` + sizeCache protoimpl.SizeCache } func (x *PrincipleTargetInfo) Reset() { @@ -359,11 +356,10 @@ func (x *PrincipleTargetInfo) GetTag() []string { } type OverrideInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` unknownFields protoimpl.UnknownFields - - Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` + sizeCache protoimpl.SizeCache } func (x *OverrideInfo) Reset() { @@ -404,12 +400,11 @@ func (x *OverrideInfo) GetTarget() string { } type BalancerMsg struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Override *OverrideInfo `protobuf:"bytes,5,opt,name=override,proto3" json:"override,omitempty"` - PrincipleTarget *PrincipleTargetInfo `protobuf:"bytes,6,opt,name=principle_target,json=principleTarget,proto3" json:"principle_target,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + Override *OverrideInfo `protobuf:"bytes,5,opt,name=override,proto3" json:"override,omitempty"` + PrincipleTarget *PrincipleTargetInfo `protobuf:"bytes,6,opt,name=principle_target,json=principleTarget,proto3" json:"principle_target,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *BalancerMsg) Reset() { @@ -457,11 +452,10 @@ func (x *BalancerMsg) GetPrincipleTarget() *PrincipleTargetInfo { } type GetBalancerInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` unknownFields protoimpl.UnknownFields - - Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetBalancerInfoRequest) Reset() { @@ -502,11 +496,10 @@ func (x *GetBalancerInfoRequest) GetTag() string { } type GetBalancerInfoResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Balancer *BalancerMsg `protobuf:"bytes,1,opt,name=balancer,proto3" json:"balancer,omitempty"` unknownFields protoimpl.UnknownFields - - Balancer *BalancerMsg `protobuf:"bytes,1,opt,name=balancer,proto3" json:"balancer,omitempty"` + sizeCache protoimpl.SizeCache } func (x *GetBalancerInfoResponse) Reset() { @@ -547,12 +540,11 @@ func (x *GetBalancerInfoResponse) GetBalancer() *BalancerMsg { } type OverrideBalancerTargetRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + BalancerTag string `protobuf:"bytes,1,opt,name=balancerTag,proto3" json:"balancerTag,omitempty"` + Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` unknownFields protoimpl.UnknownFields - - BalancerTag string `protobuf:"bytes,1,opt,name=balancerTag,proto3" json:"balancerTag,omitempty"` - Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"` + sizeCache protoimpl.SizeCache } func (x *OverrideBalancerTargetRequest) Reset() { @@ -600,9 +592,9 @@ func (x *OverrideBalancerTargetRequest) GetTarget() string { } type OverrideBalancerTargetResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *OverrideBalancerTargetResponse) Reset() { @@ -636,12 +628,11 @@ func (*OverrideBalancerTargetResponse) Descriptor() ([]byte, []int) { } type AddRuleRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + Config *serial.TypedMessage `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ShouldAppend bool `protobuf:"varint,2,opt,name=shouldAppend,proto3" json:"shouldAppend,omitempty"` unknownFields protoimpl.UnknownFields - - Config *serial.TypedMessage `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ShouldAppend bool `protobuf:"varint,2,opt,name=shouldAppend,proto3" json:"shouldAppend,omitempty"` + sizeCache protoimpl.SizeCache } func (x *AddRuleRequest) Reset() { @@ -689,9 +680,9 @@ func (x *AddRuleRequest) GetShouldAppend() bool { } type AddRuleResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *AddRuleResponse) Reset() { @@ -725,11 +716,10 @@ func (*AddRuleResponse) Descriptor() ([]byte, []int) { } type RemoveRuleRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + RuleTag string `protobuf:"bytes,1,opt,name=ruleTag,proto3" json:"ruleTag,omitempty"` unknownFields protoimpl.UnknownFields - - RuleTag string `protobuf:"bytes,1,opt,name=ruleTag,proto3" json:"ruleTag,omitempty"` + sizeCache protoimpl.SizeCache } func (x *RemoveRuleRequest) Reset() { @@ -770,9 +760,9 @@ func (x *RemoveRuleRequest) GetRuleTag() string { } type RemoveRuleResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RemoveRuleResponse) Reset() { @@ -805,15 +795,147 @@ func (*RemoveRuleResponse) Descriptor() ([]byte, []int) { return file_app_router_command_command_proto_rawDescGZIP(), []int{13} } -type Config struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache +type ListRuleRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRuleRequest) Reset() { + *x = ListRuleRequest{} + mi := &file_app_router_command_command_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRuleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRuleRequest) ProtoMessage() {} + +func (x *ListRuleRequest) ProtoReflect() protoreflect.Message { + mi := &file_app_router_command_command_proto_msgTypes[14] + 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 ListRuleRequest.ProtoReflect.Descriptor instead. +func (*ListRuleRequest) Descriptor() ([]byte, []int) { + return file_app_router_command_command_proto_rawDescGZIP(), []int{14} +} + +type ListRuleItem struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + RuleTag string `protobuf:"bytes,2,opt,name=ruleTag,proto3" json:"ruleTag,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRuleItem) Reset() { + *x = ListRuleItem{} + mi := &file_app_router_command_command_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRuleItem) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRuleItem) ProtoMessage() {} + +func (x *ListRuleItem) ProtoReflect() protoreflect.Message { + mi := &file_app_router_command_command_proto_msgTypes[15] + 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 ListRuleItem.ProtoReflect.Descriptor instead. +func (*ListRuleItem) Descriptor() ([]byte, []int) { + return file_app_router_command_command_proto_rawDescGZIP(), []int{15} +} + +func (x *ListRuleItem) GetTag() string { + if x != nil { + return x.Tag + } + return "" +} + +func (x *ListRuleItem) GetRuleTag() string { + if x != nil { + return x.RuleTag + } + return "" +} + +type ListRuleResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Rules []*ListRuleItem `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRuleResponse) Reset() { + *x = ListRuleResponse{} + mi := &file_app_router_command_command_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRuleResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRuleResponse) ProtoMessage() {} + +func (x *ListRuleResponse) ProtoReflect() protoreflect.Message { + mi := &file_app_router_command_command_proto_msgTypes[16] + 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 ListRuleResponse.ProtoReflect.Descriptor instead. +func (*ListRuleResponse) Descriptor() ([]byte, []int) { + return file_app_router_command_command_proto_rawDescGZIP(), []int{16} +} + +func (x *ListRuleResponse) GetRules() []*ListRuleItem { + if x != nil { + return x.Rules + } + return nil +} + +type Config struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Config) Reset() { *x = Config{} - mi := &file_app_router_command_command_proto_msgTypes[14] + mi := &file_app_router_command_command_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -825,7 +947,7 @@ func (x *Config) String() string { func (*Config) ProtoMessage() {} func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_app_router_command_command_proto_msgTypes[14] + mi := &file_app_router_command_command_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -838,187 +960,103 @@ func (x *Config) ProtoReflect() protoreflect.Message { // Deprecated: Use Config.ProtoReflect.Descriptor instead. func (*Config) Descriptor() ([]byte, []int) { - return file_app_router_command_command_proto_rawDescGZIP(), []int{14} + return file_app_router_command_command_proto_rawDescGZIP(), []int{17} } var File_app_router_command_command_proto protoreflect.FileDescriptor -var file_app_router_command_command_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x17, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x18, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf6, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75, - 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x49, - 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x32, 0x0a, 0x07, 0x4e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, - 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, - 0x1c, 0x0a, 0x09, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x09, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, - 0x09, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x50, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x09, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x50, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, - 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x55, - 0x73, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x57, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, - 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x41, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x4f, 0x75, 0x74, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x18, 0x0b, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x11, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x75, 0x74, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x49, 0x50, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, - 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, - 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, - 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65, - 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f, - 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, - 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, - 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69, - 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x27, 0x0a, - 0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xa9, - 0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x41, - 0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, - 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63, - 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65, - 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x5b, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, - 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x20, - 0x0a, 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x6e, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0c, - 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, - 0x22, 0x11, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, - 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, - 0x61, 0x67, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x32, 0xbf, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x35, - 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, - 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, - 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, - 0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, - 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, - 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, - 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, - 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8b, 0x01, - 0x0a, 0x16, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, - 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x07, 0x41, - 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, - 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x0a, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, - 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, - 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, - 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, - 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, -} +const file_app_router_command_command_proto_rawDesc = "" + + "\n" + + " app/router/command/command.proto\x12\x17xray.app.router.command\x1a\x18common/net/network.proto\x1a!common/serial/typed_message.proto\"\xf6\x04\n" + + "\x0eRoutingContext\x12\x1e\n" + + "\n" + + "InboundTag\x18\x01 \x01(\tR\n" + + "InboundTag\x122\n" + + "\aNetwork\x18\x02 \x01(\x0e2\x18.xray.common.net.NetworkR\aNetwork\x12\x1c\n" + + "\tSourceIPs\x18\x03 \x03(\fR\tSourceIPs\x12\x1c\n" + + "\tTargetIPs\x18\x04 \x03(\fR\tTargetIPs\x12\x1e\n" + + "\n" + + "SourcePort\x18\x05 \x01(\rR\n" + + "SourcePort\x12\x1e\n" + + "\n" + + "TargetPort\x18\x06 \x01(\rR\n" + + "TargetPort\x12\"\n" + + "\fTargetDomain\x18\a \x01(\tR\fTargetDomain\x12\x1a\n" + + "\bProtocol\x18\b \x01(\tR\bProtocol\x12\x12\n" + + "\x04User\x18\t \x01(\tR\x04User\x12W\n" + + "\n" + + "Attributes\x18\n" + + " \x03(\v27.xray.app.router.command.RoutingContext.AttributesEntryR\n" + + "Attributes\x12,\n" + + "\x11OutboundGroupTags\x18\v \x03(\tR\x11OutboundGroupTags\x12 \n" + + "\vOutboundTag\x18\f \x01(\tR\vOutboundTag\x12\x1a\n" + + "\bLocalIPs\x18\r \x03(\fR\bLocalIPs\x12\x1c\n" + + "\tLocalPort\x18\x0e \x01(\rR\tLocalPort\x12\x1e\n" + + "\n" + + "VlessRoute\x18\x0f \x01(\rR\n" + + "VlessRoute\x1a=\n" + + "\x0fAttributesEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"F\n" + + "\x1cSubscribeRoutingStatsRequest\x12&\n" + + "\x0eFieldSelectors\x18\x01 \x03(\tR\x0eFieldSelectors\"\xb1\x01\n" + + "\x10TestRouteRequest\x12O\n" + + "\x0eRoutingContext\x18\x01 \x01(\v2'.xray.app.router.command.RoutingContextR\x0eRoutingContext\x12&\n" + + "\x0eFieldSelectors\x18\x02 \x03(\tR\x0eFieldSelectors\x12$\n" + + "\rPublishResult\x18\x03 \x01(\bR\rPublishResult\"'\n" + + "\x13PrincipleTargetInfo\x12\x10\n" + + "\x03tag\x18\x01 \x03(\tR\x03tag\"&\n" + + "\fOverrideInfo\x12\x16\n" + + "\x06target\x18\x02 \x01(\tR\x06target\"\xa9\x01\n" + + "\vBalancerMsg\x12A\n" + + "\boverride\x18\x05 \x01(\v2%.xray.app.router.command.OverrideInfoR\boverride\x12W\n" + + "\x10principle_target\x18\x06 \x01(\v2,.xray.app.router.command.PrincipleTargetInfoR\x0fprincipleTarget\"*\n" + + "\x16GetBalancerInfoRequest\x12\x10\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\"[\n" + + "\x17GetBalancerInfoResponse\x12@\n" + + "\bbalancer\x18\x01 \x01(\v2$.xray.app.router.command.BalancerMsgR\bbalancer\"Y\n" + + "\x1dOverrideBalancerTargetRequest\x12 \n" + + "\vbalancerTag\x18\x01 \x01(\tR\vbalancerTag\x12\x16\n" + + "\x06target\x18\x02 \x01(\tR\x06target\" \n" + + "\x1eOverrideBalancerTargetResponse\"n\n" + + "\x0eAddRuleRequest\x128\n" + + "\x06config\x18\x01 \x01(\v2 .xray.common.serial.TypedMessageR\x06config\x12\"\n" + + "\fshouldAppend\x18\x02 \x01(\bR\fshouldAppend\"\x11\n" + + "\x0fAddRuleResponse\"-\n" + + "\x11RemoveRuleRequest\x12\x18\n" + + "\aruleTag\x18\x01 \x01(\tR\aruleTag\"\x14\n" + + "\x12RemoveRuleResponse\"\x11\n" + + "\x0fListRuleRequest\":\n" + + "\fListRuleItem\x12\x10\n" + + "\x03tag\x18\x01 \x01(\tR\x03tag\x12\x18\n" + + "\aruleTag\x18\x02 \x01(\tR\aruleTag\"O\n" + + "\x10ListRuleResponse\x12;\n" + + "\x05rules\x18\x01 \x03(\v2%.xray.app.router.command.ListRuleItemR\x05rules\"\b\n" + + "\x06Config2\xa2\x06\n" + + "\x0eRoutingService\x12{\n" + + "\x15SubscribeRoutingStats\x125.xray.app.router.command.SubscribeRoutingStatsRequest\x1a'.xray.app.router.command.RoutingContext\"\x000\x01\x12a\n" + + "\tTestRoute\x12).xray.app.router.command.TestRouteRequest\x1a'.xray.app.router.command.RoutingContext\"\x00\x12v\n" + + "\x0fGetBalancerInfo\x12/.xray.app.router.command.GetBalancerInfoRequest\x1a0.xray.app.router.command.GetBalancerInfoResponse\"\x00\x12\x8b\x01\n" + + "\x16OverrideBalancerTarget\x126.xray.app.router.command.OverrideBalancerTargetRequest\x1a7.xray.app.router.command.OverrideBalancerTargetResponse\"\x00\x12^\n" + + "\aAddRule\x12'.xray.app.router.command.AddRuleRequest\x1a(.xray.app.router.command.AddRuleResponse\"\x00\x12g\n" + + "\n" + + "RemoveRule\x12*.xray.app.router.command.RemoveRuleRequest\x1a+.xray.app.router.command.RemoveRuleResponse\"\x00\x12a\n" + + "\bListRule\x12(.xray.app.router.command.ListRuleRequest\x1a).xray.app.router.command.ListRuleResponse\"\x00Bg\n" + + "\x1bcom.xray.app.router.commandP\x01Z,github.com/xtls/xray-core/app/router/command\xaa\x02\x17Xray.App.Router.Commandb\x06proto3" var ( file_app_router_command_command_proto_rawDescOnce sync.Once - file_app_router_command_command_proto_rawDescData = file_app_router_command_command_proto_rawDesc + file_app_router_command_command_proto_rawDescData []byte ) func file_app_router_command_command_proto_rawDescGZIP() []byte { file_app_router_command_command_proto_rawDescOnce.Do(func() { - file_app_router_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_router_command_command_proto_rawDescData) + file_app_router_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_router_command_command_proto_rawDesc), len(file_app_router_command_command_proto_rawDesc))) }) return file_app_router_command_command_proto_rawDescData } -var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_app_router_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_app_router_command_command_proto_goTypes = []any{ (*RoutingContext)(nil), // 0: xray.app.router.command.RoutingContext (*SubscribeRoutingStatsRequest)(nil), // 1: xray.app.router.command.SubscribeRoutingStatsRequest @@ -1034,36 +1072,42 @@ var file_app_router_command_command_proto_goTypes = []any{ (*AddRuleResponse)(nil), // 11: xray.app.router.command.AddRuleResponse (*RemoveRuleRequest)(nil), // 12: xray.app.router.command.RemoveRuleRequest (*RemoveRuleResponse)(nil), // 13: xray.app.router.command.RemoveRuleResponse - (*Config)(nil), // 14: xray.app.router.command.Config - nil, // 15: xray.app.router.command.RoutingContext.AttributesEntry - (net.Network)(0), // 16: xray.common.net.Network - (*serial.TypedMessage)(nil), // 17: xray.common.serial.TypedMessage + (*ListRuleRequest)(nil), // 14: xray.app.router.command.ListRuleRequest + (*ListRuleItem)(nil), // 15: xray.app.router.command.ListRuleItem + (*ListRuleResponse)(nil), // 16: xray.app.router.command.ListRuleResponse + (*Config)(nil), // 17: xray.app.router.command.Config + nil, // 18: xray.app.router.command.RoutingContext.AttributesEntry + (net.Network)(0), // 19: xray.common.net.Network + (*serial.TypedMessage)(nil), // 20: xray.common.serial.TypedMessage } var file_app_router_command_command_proto_depIdxs = []int32{ - 16, // 0: xray.app.router.command.RoutingContext.Network:type_name -> xray.common.net.Network - 15, // 1: xray.app.router.command.RoutingContext.Attributes:type_name -> xray.app.router.command.RoutingContext.AttributesEntry + 19, // 0: xray.app.router.command.RoutingContext.Network:type_name -> xray.common.net.Network + 18, // 1: xray.app.router.command.RoutingContext.Attributes:type_name -> xray.app.router.command.RoutingContext.AttributesEntry 0, // 2: xray.app.router.command.TestRouteRequest.RoutingContext:type_name -> xray.app.router.command.RoutingContext 4, // 3: xray.app.router.command.BalancerMsg.override:type_name -> xray.app.router.command.OverrideInfo 3, // 4: xray.app.router.command.BalancerMsg.principle_target:type_name -> xray.app.router.command.PrincipleTargetInfo 5, // 5: xray.app.router.command.GetBalancerInfoResponse.balancer:type_name -> xray.app.router.command.BalancerMsg - 17, // 6: xray.app.router.command.AddRuleRequest.config:type_name -> xray.common.serial.TypedMessage - 1, // 7: xray.app.router.command.RoutingService.SubscribeRoutingStats:input_type -> xray.app.router.command.SubscribeRoutingStatsRequest - 2, // 8: xray.app.router.command.RoutingService.TestRoute:input_type -> xray.app.router.command.TestRouteRequest - 6, // 9: xray.app.router.command.RoutingService.GetBalancerInfo:input_type -> xray.app.router.command.GetBalancerInfoRequest - 8, // 10: xray.app.router.command.RoutingService.OverrideBalancerTarget:input_type -> xray.app.router.command.OverrideBalancerTargetRequest - 10, // 11: xray.app.router.command.RoutingService.AddRule:input_type -> xray.app.router.command.AddRuleRequest - 12, // 12: xray.app.router.command.RoutingService.RemoveRule:input_type -> xray.app.router.command.RemoveRuleRequest - 0, // 13: xray.app.router.command.RoutingService.SubscribeRoutingStats:output_type -> xray.app.router.command.RoutingContext - 0, // 14: xray.app.router.command.RoutingService.TestRoute:output_type -> xray.app.router.command.RoutingContext - 7, // 15: xray.app.router.command.RoutingService.GetBalancerInfo:output_type -> xray.app.router.command.GetBalancerInfoResponse - 9, // 16: xray.app.router.command.RoutingService.OverrideBalancerTarget:output_type -> xray.app.router.command.OverrideBalancerTargetResponse - 11, // 17: xray.app.router.command.RoutingService.AddRule:output_type -> xray.app.router.command.AddRuleResponse - 13, // 18: xray.app.router.command.RoutingService.RemoveRule:output_type -> xray.app.router.command.RemoveRuleResponse - 13, // [13:19] is the sub-list for method output_type - 7, // [7:13] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 20, // 6: xray.app.router.command.AddRuleRequest.config:type_name -> xray.common.serial.TypedMessage + 15, // 7: xray.app.router.command.ListRuleResponse.rules:type_name -> xray.app.router.command.ListRuleItem + 1, // 8: xray.app.router.command.RoutingService.SubscribeRoutingStats:input_type -> xray.app.router.command.SubscribeRoutingStatsRequest + 2, // 9: xray.app.router.command.RoutingService.TestRoute:input_type -> xray.app.router.command.TestRouteRequest + 6, // 10: xray.app.router.command.RoutingService.GetBalancerInfo:input_type -> xray.app.router.command.GetBalancerInfoRequest + 8, // 11: xray.app.router.command.RoutingService.OverrideBalancerTarget:input_type -> xray.app.router.command.OverrideBalancerTargetRequest + 10, // 12: xray.app.router.command.RoutingService.AddRule:input_type -> xray.app.router.command.AddRuleRequest + 12, // 13: xray.app.router.command.RoutingService.RemoveRule:input_type -> xray.app.router.command.RemoveRuleRequest + 14, // 14: xray.app.router.command.RoutingService.ListRule:input_type -> xray.app.router.command.ListRuleRequest + 0, // 15: xray.app.router.command.RoutingService.SubscribeRoutingStats:output_type -> xray.app.router.command.RoutingContext + 0, // 16: xray.app.router.command.RoutingService.TestRoute:output_type -> xray.app.router.command.RoutingContext + 7, // 17: xray.app.router.command.RoutingService.GetBalancerInfo:output_type -> xray.app.router.command.GetBalancerInfoResponse + 9, // 18: xray.app.router.command.RoutingService.OverrideBalancerTarget:output_type -> xray.app.router.command.OverrideBalancerTargetResponse + 11, // 19: xray.app.router.command.RoutingService.AddRule:output_type -> xray.app.router.command.AddRuleResponse + 13, // 20: xray.app.router.command.RoutingService.RemoveRule:output_type -> xray.app.router.command.RemoveRuleResponse + 16, // 21: xray.app.router.command.RoutingService.ListRule:output_type -> xray.app.router.command.ListRuleResponse + 15, // [15:22] is the sub-list for method output_type + 8, // [8:15] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_app_router_command_command_proto_init() } @@ -1075,9 +1119,9 @@ func file_app_router_command_command_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_app_router_command_command_proto_rawDesc, + RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_router_command_command_proto_rawDesc), len(file_app_router_command_command_proto_rawDesc)), NumEnums: 0, - NumMessages: 16, + NumMessages: 19, NumExtensions: 0, NumServices: 1, }, @@ -1086,7 +1130,6 @@ func file_app_router_command_command_proto_init() { MessageInfos: file_app_router_command_command_proto_msgTypes, }.Build() File_app_router_command_command_proto = out.File - file_app_router_command_command_proto_rawDesc = nil file_app_router_command_command_proto_goTypes = nil file_app_router_command_command_proto_depIdxs = nil } diff --git a/app/router/command/command.proto b/app/router/command/command.proto index 17aea575..22ae95b9 100644 --- a/app/router/command/command.proto +++ b/app/router/command/command.proto @@ -104,6 +104,17 @@ message RemoveRuleRequest { message RemoveRuleResponse {} +message ListRuleRequest {} + +message ListRuleItem { + string tag = 1; + string ruleTag = 2; +} + +message ListRuleResponse{ + repeated ListRuleItem rules = 1; +} + service RoutingService { rpc SubscribeRoutingStats(SubscribeRoutingStatsRequest) returns (stream RoutingContext) {} @@ -114,6 +125,8 @@ service RoutingService { rpc AddRule(AddRuleRequest) returns (AddRuleResponse) {} rpc RemoveRule(RemoveRuleRequest) returns (RemoveRuleResponse) {} + + rpc ListRule(ListRuleRequest) returns (ListRuleResponse) {} } message Config {} diff --git a/app/router/command/command_grpc.pb.go b/app/router/command/command_grpc.pb.go index 23e03c8a..f134d621 100644 --- a/app/router/command/command_grpc.pb.go +++ b/app/router/command/command_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v5.28.2 +// - protoc-gen-go-grpc v1.6.0 +// - protoc v6.33.2 // source: app/router/command/command.proto package command @@ -25,6 +25,7 @@ const ( RoutingService_OverrideBalancerTarget_FullMethodName = "/xray.app.router.command.RoutingService/OverrideBalancerTarget" RoutingService_AddRule_FullMethodName = "/xray.app.router.command.RoutingService/AddRule" RoutingService_RemoveRule_FullMethodName = "/xray.app.router.command.RoutingService/RemoveRule" + RoutingService_ListRule_FullMethodName = "/xray.app.router.command.RoutingService/ListRule" ) // RoutingServiceClient is the client API for RoutingService service. @@ -37,6 +38,7 @@ type RoutingServiceClient interface { OverrideBalancerTarget(ctx context.Context, in *OverrideBalancerTargetRequest, opts ...grpc.CallOption) (*OverrideBalancerTargetResponse, error) AddRule(ctx context.Context, in *AddRuleRequest, opts ...grpc.CallOption) (*AddRuleResponse, error) RemoveRule(ctx context.Context, in *RemoveRuleRequest, opts ...grpc.CallOption) (*RemoveRuleResponse, error) + ListRule(ctx context.Context, in *ListRuleRequest, opts ...grpc.CallOption) (*ListRuleResponse, error) } type routingServiceClient struct { @@ -116,6 +118,16 @@ func (c *routingServiceClient) RemoveRule(ctx context.Context, in *RemoveRuleReq return out, nil } +func (c *routingServiceClient) ListRule(ctx context.Context, in *ListRuleRequest, opts ...grpc.CallOption) (*ListRuleResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListRuleResponse) + err := c.cc.Invoke(ctx, RoutingService_ListRule_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // RoutingServiceServer is the server API for RoutingService service. // All implementations must embed UnimplementedRoutingServiceServer // for forward compatibility. @@ -126,6 +138,7 @@ type RoutingServiceServer interface { OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error) AddRule(context.Context, *AddRuleRequest) (*AddRuleResponse, error) RemoveRule(context.Context, *RemoveRuleRequest) (*RemoveRuleResponse, error) + ListRule(context.Context, *ListRuleRequest) (*ListRuleResponse, error) mustEmbedUnimplementedRoutingServiceServer() } @@ -137,22 +150,25 @@ type RoutingServiceServer interface { type UnimplementedRoutingServiceServer struct{} func (UnimplementedRoutingServiceServer) SubscribeRoutingStats(*SubscribeRoutingStatsRequest, grpc.ServerStreamingServer[RoutingContext]) error { - return status.Errorf(codes.Unimplemented, "method SubscribeRoutingStats not implemented") + return status.Error(codes.Unimplemented, "method SubscribeRoutingStats not implemented") } func (UnimplementedRoutingServiceServer) TestRoute(context.Context, *TestRouteRequest) (*RoutingContext, error) { - return nil, status.Errorf(codes.Unimplemented, "method TestRoute not implemented") + return nil, status.Error(codes.Unimplemented, "method TestRoute not implemented") } func (UnimplementedRoutingServiceServer) GetBalancerInfo(context.Context, *GetBalancerInfoRequest) (*GetBalancerInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBalancerInfo not implemented") + return nil, status.Error(codes.Unimplemented, "method GetBalancerInfo not implemented") } func (UnimplementedRoutingServiceServer) OverrideBalancerTarget(context.Context, *OverrideBalancerTargetRequest) (*OverrideBalancerTargetResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method OverrideBalancerTarget not implemented") + return nil, status.Error(codes.Unimplemented, "method OverrideBalancerTarget not implemented") } func (UnimplementedRoutingServiceServer) AddRule(context.Context, *AddRuleRequest) (*AddRuleResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddRule not implemented") + return nil, status.Error(codes.Unimplemented, "method AddRule not implemented") } func (UnimplementedRoutingServiceServer) RemoveRule(context.Context, *RemoveRuleRequest) (*RemoveRuleResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RemoveRule not implemented") + return nil, status.Error(codes.Unimplemented, "method RemoveRule not implemented") +} +func (UnimplementedRoutingServiceServer) ListRule(context.Context, *ListRuleRequest) (*ListRuleResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListRule not implemented") } func (UnimplementedRoutingServiceServer) mustEmbedUnimplementedRoutingServiceServer() {} func (UnimplementedRoutingServiceServer) testEmbeddedByValue() {} @@ -165,7 +181,7 @@ type UnsafeRoutingServiceServer interface { } func RegisterRoutingServiceServer(s grpc.ServiceRegistrar, srv RoutingServiceServer) { - // If the following call pancis, it indicates UnimplementedRoutingServiceServer was + // If the following call panics, it indicates UnimplementedRoutingServiceServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. @@ -276,6 +292,24 @@ func _RoutingService_RemoveRule_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _RoutingService_ListRule_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListRuleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RoutingServiceServer).ListRule(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: RoutingService_ListRule_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoutingServiceServer).ListRule(ctx, req.(*ListRuleRequest)) + } + return interceptor(ctx, in, info, handler) +} + // RoutingService_ServiceDesc is the grpc.ServiceDesc for RoutingService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -303,6 +337,10 @@ var RoutingService_ServiceDesc = grpc.ServiceDesc{ MethodName: "RemoveRule", Handler: _RoutingService_RemoveRule_Handler, }, + { + MethodName: "ListRule", + Handler: _RoutingService_ListRule_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/app/router/router.go b/app/router/router.go index 2f35b3e7..790bf8e2 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -2,7 +2,7 @@ package router import ( "context" - sync "sync" + "sync" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/errors" @@ -181,6 +181,21 @@ func (r *Router) RemoveRule(tag string) error { return errors.New("empty tag name!") } + +// ListRule implements routing.Router +func (r *Router) ListRule() []routing.Route { + r.mu.Lock() + defer r.mu.Unlock() + ruleList := make([]routing.Route, 0) + for _, rule := range r.rules { + ruleList = append(ruleList, &Route{ + outboundTag: rule.Tag, + ruleTag: rule.RuleTag, + }) + } + return ruleList +} + func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) { // SkipDNSResolve is set from DNS module. // the DOH remote server maybe a domain name, diff --git a/features/routing/router.go b/features/routing/router.go index 174d59fd..46172de7 100644 --- a/features/routing/router.go +++ b/features/routing/router.go @@ -16,6 +16,7 @@ type Router interface { PickRoute(ctx Context) (Route, error) AddRule(config *serial.TypedMessage, shouldAppend bool) error RemoveRule(tag string) error + ListRule() []Route } // Route is the routing result of Router feature. @@ -65,6 +66,11 @@ func (DefaultRouter) RemoveRule(tag string) error { return common.ErrNoClue } +// ListRule implements Router. +func (DefaultRouter) ListRule() []Route { + return nil +} + // Start implements common.Runnable. func (DefaultRouter) Start() error { return nil diff --git a/main/commands/all/api/api.go b/main/commands/all/api/api.go index cd5e97f4..85d7aa9f 100644 --- a/main/commands/all/api/api.go +++ b/main/commands/all/api/api.go @@ -29,6 +29,7 @@ var CmdAPI = &base.Command{ cmdInboundUserCount, cmdAddRules, cmdRemoveRules, + cmdListRules, cmdSourceIpBlock, cmdOnlineStats, cmdOnlineStatsIpList, diff --git a/main/commands/all/api/rules_list.go b/main/commands/all/api/rules_list.go new file mode 100644 index 00000000..6bc1c4aa --- /dev/null +++ b/main/commands/all/api/rules_list.go @@ -0,0 +1,43 @@ +package api + +import ( + routerService "github.com/xtls/xray-core/app/router/command" + "github.com/xtls/xray-core/main/commands/base" +) + +var cmdListRules = &base.Command{ + CustomFlags: true, + UsageLine: "{{.Exec}} api lsrules [--server=127.0.0.1:8080]", + Short: "List routing rules", + Long: ` +List routing rules in Xray. + +Arguments: + + -s, -server + The API server address. Default 127.0.0.1:8080 + + -t, -timeout + Timeout in seconds for calling API. Default 3 + +Example: + + {{.Exec}} {{.LongName}} --server=127.0.0.1:8080 +`, + Run: executeListRules, +} + +func executeListRules(cmd *base.Command, args []string) { + setSharedFlags(cmd) + cmd.Flag.Parse(args) + + conn, ctx, close := dialAPIServer() + defer close() + + client := routerService.NewRoutingServiceClient(conn) + resp, err := client.ListRule(ctx, &routerService.ListRuleRequest{}) + if err != nil { + base.Fatalf("failed to list rules: %s", err) + } + showJSONResponse(resp) +}