diff --git a/app/proxyman/command/command.go b/app/proxyman/command/command.go index 4554f32b..3c7824d2 100644 --- a/app/proxyman/command/command.go +++ b/app/proxyman/command/command.go @@ -5,6 +5,7 @@ import ( "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/errors" + "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/features/inbound" "github.com/xtls/xray-core/features/outbound" @@ -98,6 +99,46 @@ func (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundR return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler) } +func (s *handlerServer) GetInboundUsers(ctx context.Context, request *GetInboundUserRequest) (*GetInboundUserResponse, error) { + handler, err := s.ihm.GetHandler(ctx, request.Tag) + if err != nil { + return nil, errors.New("failed to get handler: ", request.Tag).Base(err) + } + p, err := getInbound(handler) + if err != nil { + return nil, err + } + um, ok := p.(proxy.UserManager) + if !ok { + return nil, errors.New("proxy is not a UserManager") + } + if len(request.Email) > 0 { + return &GetInboundUserResponse{Users: []*protocol.User{protocol.ToProtoUser(um.GetUser(ctx, request.Email))}}, nil + } + var result = make([]*protocol.User, 0, 100) + users := um.GetUsers(ctx) + for _, u := range users { + result = append(result, protocol.ToProtoUser(u)) + } + return &GetInboundUserResponse{Users: result}, nil +} + +func (s *handlerServer) GetInboundUsersCount(ctx context.Context, request *GetInboundUserRequest) (*GetInboundUsersCountResponse, error) { + handler, err := s.ihm.GetHandler(ctx, request.Tag) + if err != nil { + return nil, errors.New("failed to get handler: ", request.Tag).Base(err) + } + p, err := getInbound(handler) + if err != nil { + return nil, err + } + um, ok := p.(proxy.UserManager) + if !ok { + return nil, errors.New("proxy is not a UserManager") + } + return &GetInboundUsersCountResponse{Count: um.GetUsersCount(ctx)}, nil +} + func (s *handlerServer) AddOutbound(ctx context.Context, request *AddOutboundRequest) (*AddOutboundResponse, error) { if err := core.AddOutboundHandler(s.s, request.Outbound); err != nil { return nil, err diff --git a/app/proxyman/command/command.pb.go b/app/proxyman/command/command.pb.go index 32a29cc6..a98da103 100644 --- a/app/proxyman/command/command.pb.go +++ b/app/proxyman/command/command.pb.go @@ -364,6 +364,149 @@ func (*AlterInboundResponse) Descriptor() ([]byte, []int) { return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{7} } +type GetInboundUserRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` +} + +func (x *GetInboundUserRequest) Reset() { + *x = GetInboundUserRequest{} + mi := &file_app_proxyman_command_command_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetInboundUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetInboundUserRequest) ProtoMessage() {} + +func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_app_proxyman_command_command_proto_msgTypes[8] + 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 GetInboundUserRequest.ProtoReflect.Descriptor instead. +func (*GetInboundUserRequest) Descriptor() ([]byte, []int) { + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{8} +} + +func (x *GetInboundUserRequest) GetTag() string { + if x != nil { + return x.Tag + } + return "" +} + +func (x *GetInboundUserRequest) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +type GetInboundUserResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` +} + +func (x *GetInboundUserResponse) Reset() { + *x = GetInboundUserResponse{} + mi := &file_app_proxyman_command_command_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetInboundUserResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetInboundUserResponse) ProtoMessage() {} + +func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message { + mi := &file_app_proxyman_command_command_proto_msgTypes[9] + 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 GetInboundUserResponse.ProtoReflect.Descriptor instead. +func (*GetInboundUserResponse) Descriptor() ([]byte, []int) { + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{9} +} + +func (x *GetInboundUserResponse) GetUsers() []*protocol.User { + if x != nil { + return x.Users + } + return nil +} + +type GetInboundUsersCountResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` +} + +func (x *GetInboundUsersCountResponse) Reset() { + *x = GetInboundUsersCountResponse{} + mi := &file_app_proxyman_command_command_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetInboundUsersCountResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetInboundUsersCountResponse) ProtoMessage() {} + +func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message { + mi := &file_app_proxyman_command_command_proto_msgTypes[10] + 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 GetInboundUsersCountResponse.ProtoReflect.Descriptor instead. +func (*GetInboundUsersCountResponse) Descriptor() ([]byte, []int) { + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{10} +} + +func (x *GetInboundUsersCountResponse) GetCount() int64 { + if x != nil { + return x.Count + } + return 0 +} + type AddOutboundRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -374,7 +517,7 @@ type AddOutboundRequest struct { func (x *AddOutboundRequest) Reset() { *x = AddOutboundRequest{} - mi := &file_app_proxyman_command_command_proto_msgTypes[8] + mi := &file_app_proxyman_command_command_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -386,7 +529,7 @@ func (x *AddOutboundRequest) String() string { func (*AddOutboundRequest) ProtoMessage() {} func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_command_command_proto_msgTypes[8] + mi := &file_app_proxyman_command_command_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -399,7 +542,7 @@ func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddOutboundRequest.ProtoReflect.Descriptor instead. func (*AddOutboundRequest) Descriptor() ([]byte, []int) { - return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{8} + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{11} } func (x *AddOutboundRequest) GetOutbound() *core.OutboundHandlerConfig { @@ -417,7 +560,7 @@ type AddOutboundResponse struct { func (x *AddOutboundResponse) Reset() { *x = AddOutboundResponse{} - mi := &file_app_proxyman_command_command_proto_msgTypes[9] + mi := &file_app_proxyman_command_command_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -429,7 +572,7 @@ func (x *AddOutboundResponse) String() string { func (*AddOutboundResponse) ProtoMessage() {} func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_command_command_proto_msgTypes[9] + mi := &file_app_proxyman_command_command_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -442,7 +585,7 @@ func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddOutboundResponse.ProtoReflect.Descriptor instead. func (*AddOutboundResponse) Descriptor() ([]byte, []int) { - return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{9} + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{12} } type RemoveOutboundRequest struct { @@ -455,7 +598,7 @@ type RemoveOutboundRequest struct { func (x *RemoveOutboundRequest) Reset() { *x = RemoveOutboundRequest{} - mi := &file_app_proxyman_command_command_proto_msgTypes[10] + mi := &file_app_proxyman_command_command_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -467,7 +610,7 @@ func (x *RemoveOutboundRequest) String() string { func (*RemoveOutboundRequest) ProtoMessage() {} func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_command_command_proto_msgTypes[10] + mi := &file_app_proxyman_command_command_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -480,7 +623,7 @@ func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveOutboundRequest.ProtoReflect.Descriptor instead. func (*RemoveOutboundRequest) Descriptor() ([]byte, []int) { - return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{10} + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{13} } func (x *RemoveOutboundRequest) GetTag() string { @@ -498,7 +641,7 @@ type RemoveOutboundResponse struct { func (x *RemoveOutboundResponse) Reset() { *x = RemoveOutboundResponse{} - mi := &file_app_proxyman_command_command_proto_msgTypes[11] + mi := &file_app_proxyman_command_command_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -510,7 +653,7 @@ func (x *RemoveOutboundResponse) String() string { func (*RemoveOutboundResponse) ProtoMessage() {} func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_command_command_proto_msgTypes[11] + mi := &file_app_proxyman_command_command_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -523,7 +666,7 @@ func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveOutboundResponse.ProtoReflect.Descriptor instead. func (*RemoveOutboundResponse) Descriptor() ([]byte, []int) { - return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{11} + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{14} } type AlterOutboundRequest struct { @@ -537,7 +680,7 @@ type AlterOutboundRequest struct { func (x *AlterOutboundRequest) Reset() { *x = AlterOutboundRequest{} - mi := &file_app_proxyman_command_command_proto_msgTypes[12] + mi := &file_app_proxyman_command_command_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -549,7 +692,7 @@ func (x *AlterOutboundRequest) String() string { func (*AlterOutboundRequest) ProtoMessage() {} func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_command_command_proto_msgTypes[12] + mi := &file_app_proxyman_command_command_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -562,7 +705,7 @@ func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AlterOutboundRequest.ProtoReflect.Descriptor instead. func (*AlterOutboundRequest) Descriptor() ([]byte, []int) { - return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{12} + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{15} } func (x *AlterOutboundRequest) GetTag() string { @@ -587,7 +730,7 @@ type AlterOutboundResponse struct { func (x *AlterOutboundResponse) Reset() { *x = AlterOutboundResponse{} - mi := &file_app_proxyman_command_command_proto_msgTypes[13] + mi := &file_app_proxyman_command_command_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -599,7 +742,7 @@ func (x *AlterOutboundResponse) String() string { func (*AlterOutboundResponse) ProtoMessage() {} func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_command_command_proto_msgTypes[13] + mi := &file_app_proxyman_command_command_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -612,7 +755,7 @@ func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AlterOutboundResponse.ProtoReflect.Descriptor instead. func (*AlterOutboundResponse) Descriptor() ([]byte, []int) { - return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{13} + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{16} } type Config struct { @@ -623,7 +766,7 @@ type Config struct { func (x *Config) Reset() { *x = Config{} - mi := &file_app_proxyman_command_command_proto_msgTypes[14] + mi := &file_app_proxyman_command_command_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -635,7 +778,7 @@ func (x *Config) String() string { func (*Config) ProtoMessage() {} func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_app_proxyman_command_command_proto_msgTypes[14] + mi := &file_app_proxyman_command_command_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -648,7 +791,7 @@ func (x *Config) ProtoReflect() protoreflect.Message { // Deprecated: Use Config.ProtoReflect.Descriptor instead. func (*Config) Descriptor() ([]byte, []int) { - return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{14} + return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{17} } var File_app_proxyman_command_command_proto protoreflect.FileDescriptor @@ -688,79 +831,107 @@ var file_app_proxyman_command_command_proto_rawDesc = []byte{ 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, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x0a, 0x12, - 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x22, 0x15, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x15, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 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, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x14, - 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 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, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 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, 0x09, 0x6f, 0x70, 0x65, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x15, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 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, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a, + 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, + 0x52, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, + 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x15, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 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, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xc5, 0x05, 0x0a, 0x0e, 0x48, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x0a, - 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x78, 0x72, 0x61, - 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, - 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, - 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, + 0x68, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 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, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 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, 0x09, + 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74, + 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xc5, 0x07, 0x0a, + 0x0e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x6b, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, + 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, - 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, - 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e, + 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, + 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, + 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x12, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, + 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, + 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, + 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x78, 0x72, 0x61, + 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x83, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, + 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, + 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, + 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6e, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x2e, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, + 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x77, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, + 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, + 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, + 0x0a, 0x0d, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, - 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x6e, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x12, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, - 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, - 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x77, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x41, - 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e, 0x78, - 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, - 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, - 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, - 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, + 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, + 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -775,51 +946,59 @@ func file_app_proxyman_command_command_proto_rawDescGZIP() []byte { return file_app_proxyman_command_command_proto_rawDescData } -var file_app_proxyman_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_app_proxyman_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_app_proxyman_command_command_proto_goTypes = []any{ - (*AddUserOperation)(nil), // 0: xray.app.proxyman.command.AddUserOperation - (*RemoveUserOperation)(nil), // 1: xray.app.proxyman.command.RemoveUserOperation - (*AddInboundRequest)(nil), // 2: xray.app.proxyman.command.AddInboundRequest - (*AddInboundResponse)(nil), // 3: xray.app.proxyman.command.AddInboundResponse - (*RemoveInboundRequest)(nil), // 4: xray.app.proxyman.command.RemoveInboundRequest - (*RemoveInboundResponse)(nil), // 5: xray.app.proxyman.command.RemoveInboundResponse - (*AlterInboundRequest)(nil), // 6: xray.app.proxyman.command.AlterInboundRequest - (*AlterInboundResponse)(nil), // 7: xray.app.proxyman.command.AlterInboundResponse - (*AddOutboundRequest)(nil), // 8: xray.app.proxyman.command.AddOutboundRequest - (*AddOutboundResponse)(nil), // 9: xray.app.proxyman.command.AddOutboundResponse - (*RemoveOutboundRequest)(nil), // 10: xray.app.proxyman.command.RemoveOutboundRequest - (*RemoveOutboundResponse)(nil), // 11: xray.app.proxyman.command.RemoveOutboundResponse - (*AlterOutboundRequest)(nil), // 12: xray.app.proxyman.command.AlterOutboundRequest - (*AlterOutboundResponse)(nil), // 13: xray.app.proxyman.command.AlterOutboundResponse - (*Config)(nil), // 14: xray.app.proxyman.command.Config - (*protocol.User)(nil), // 15: xray.common.protocol.User - (*core.InboundHandlerConfig)(nil), // 16: xray.core.InboundHandlerConfig - (*serial.TypedMessage)(nil), // 17: xray.common.serial.TypedMessage - (*core.OutboundHandlerConfig)(nil), // 18: xray.core.OutboundHandlerConfig + (*AddUserOperation)(nil), // 0: xray.app.proxyman.command.AddUserOperation + (*RemoveUserOperation)(nil), // 1: xray.app.proxyman.command.RemoveUserOperation + (*AddInboundRequest)(nil), // 2: xray.app.proxyman.command.AddInboundRequest + (*AddInboundResponse)(nil), // 3: xray.app.proxyman.command.AddInboundResponse + (*RemoveInboundRequest)(nil), // 4: xray.app.proxyman.command.RemoveInboundRequest + (*RemoveInboundResponse)(nil), // 5: xray.app.proxyman.command.RemoveInboundResponse + (*AlterInboundRequest)(nil), // 6: xray.app.proxyman.command.AlterInboundRequest + (*AlterInboundResponse)(nil), // 7: xray.app.proxyman.command.AlterInboundResponse + (*GetInboundUserRequest)(nil), // 8: xray.app.proxyman.command.GetInboundUserRequest + (*GetInboundUserResponse)(nil), // 9: xray.app.proxyman.command.GetInboundUserResponse + (*GetInboundUsersCountResponse)(nil), // 10: xray.app.proxyman.command.GetInboundUsersCountResponse + (*AddOutboundRequest)(nil), // 11: xray.app.proxyman.command.AddOutboundRequest + (*AddOutboundResponse)(nil), // 12: xray.app.proxyman.command.AddOutboundResponse + (*RemoveOutboundRequest)(nil), // 13: xray.app.proxyman.command.RemoveOutboundRequest + (*RemoveOutboundResponse)(nil), // 14: xray.app.proxyman.command.RemoveOutboundResponse + (*AlterOutboundRequest)(nil), // 15: xray.app.proxyman.command.AlterOutboundRequest + (*AlterOutboundResponse)(nil), // 16: xray.app.proxyman.command.AlterOutboundResponse + (*Config)(nil), // 17: xray.app.proxyman.command.Config + (*protocol.User)(nil), // 18: xray.common.protocol.User + (*core.InboundHandlerConfig)(nil), // 19: xray.core.InboundHandlerConfig + (*serial.TypedMessage)(nil), // 20: xray.common.serial.TypedMessage + (*core.OutboundHandlerConfig)(nil), // 21: xray.core.OutboundHandlerConfig } var file_app_proxyman_command_command_proto_depIdxs = []int32{ - 15, // 0: xray.app.proxyman.command.AddUserOperation.user:type_name -> xray.common.protocol.User - 16, // 1: xray.app.proxyman.command.AddInboundRequest.inbound:type_name -> xray.core.InboundHandlerConfig - 17, // 2: xray.app.proxyman.command.AlterInboundRequest.operation:type_name -> xray.common.serial.TypedMessage - 18, // 3: xray.app.proxyman.command.AddOutboundRequest.outbound:type_name -> xray.core.OutboundHandlerConfig - 17, // 4: xray.app.proxyman.command.AlterOutboundRequest.operation:type_name -> xray.common.serial.TypedMessage - 2, // 5: xray.app.proxyman.command.HandlerService.AddInbound:input_type -> xray.app.proxyman.command.AddInboundRequest - 4, // 6: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest - 6, // 7: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest - 8, // 8: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest - 10, // 9: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest - 12, // 10: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest - 3, // 11: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse - 5, // 12: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse - 7, // 13: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse - 9, // 14: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse - 11, // 15: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse - 13, // 16: xray.app.proxyman.command.HandlerService.AlterOutbound:output_type -> xray.app.proxyman.command.AlterOutboundResponse - 11, // [11:17] is the sub-list for method output_type - 5, // [5:11] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 18, // 0: xray.app.proxyman.command.AddUserOperation.user:type_name -> xray.common.protocol.User + 19, // 1: xray.app.proxyman.command.AddInboundRequest.inbound:type_name -> xray.core.InboundHandlerConfig + 20, // 2: xray.app.proxyman.command.AlterInboundRequest.operation:type_name -> xray.common.serial.TypedMessage + 18, // 3: xray.app.proxyman.command.GetInboundUserResponse.users:type_name -> xray.common.protocol.User + 21, // 4: xray.app.proxyman.command.AddOutboundRequest.outbound:type_name -> xray.core.OutboundHandlerConfig + 20, // 5: xray.app.proxyman.command.AlterOutboundRequest.operation:type_name -> xray.common.serial.TypedMessage + 2, // 6: xray.app.proxyman.command.HandlerService.AddInbound:input_type -> xray.app.proxyman.command.AddInboundRequest + 4, // 7: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest + 6, // 8: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest + 8, // 9: xray.app.proxyman.command.HandlerService.GetInboundUsers:input_type -> xray.app.proxyman.command.GetInboundUserRequest + 8, // 10: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:input_type -> xray.app.proxyman.command.GetInboundUserRequest + 11, // 11: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest + 13, // 12: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest + 15, // 13: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest + 3, // 14: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse + 5, // 15: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse + 7, // 16: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse + 9, // 17: xray.app.proxyman.command.HandlerService.GetInboundUsers:output_type -> xray.app.proxyman.command.GetInboundUserResponse + 10, // 18: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:output_type -> xray.app.proxyman.command.GetInboundUsersCountResponse + 12, // 19: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse + 14, // 20: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse + 16, // 21: xray.app.proxyman.command.HandlerService.AlterOutbound:output_type -> xray.app.proxyman.command.AlterOutboundResponse + 14, // [14:22] is the sub-list for method output_type + 6, // [6:14] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_app_proxyman_command_command_proto_init() } @@ -833,7 +1012,7 @@ func file_app_proxyman_command_command_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_app_proxyman_command_command_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 18, NumExtensions: 0, NumServices: 1, }, diff --git a/app/proxyman/command/command.proto b/app/proxyman/command/command.proto index 5a09bd88..9a2d0142 100644 --- a/app/proxyman/command/command.proto +++ b/app/proxyman/command/command.proto @@ -37,6 +37,19 @@ message AlterInboundRequest { message AlterInboundResponse {} +message GetInboundUserRequest { + string tag = 1; + string email = 2; +} + +message GetInboundUserResponse { + repeated xray.common.protocol.User users = 1; +} + +message GetInboundUsersCountResponse { + int64 count = 1; +} + message AddOutboundRequest { core.OutboundHandlerConfig outbound = 1; } @@ -63,6 +76,10 @@ service HandlerService { rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {} + rpc GetInboundUsers(GetInboundUserRequest) returns (GetInboundUserResponse) {} + + rpc GetInboundUsersCount(GetInboundUserRequest) returns (GetInboundUsersCountResponse) {} + rpc AddOutbound(AddOutboundRequest) returns (AddOutboundResponse) {} rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {} diff --git a/app/proxyman/command/command_grpc.pb.go b/app/proxyman/command/command_grpc.pb.go index 4f12836b..7abbae8e 100644 --- a/app/proxyman/command/command_grpc.pb.go +++ b/app/proxyman/command/command_grpc.pb.go @@ -19,12 +19,14 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound" - HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound" - HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound" - HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound" - HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound" - HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound" + HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound" + HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound" + HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound" + HandlerService_GetInboundUsers_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsers" + HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsersCount" + HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound" + HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound" + HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound" ) // HandlerServiceClient is the client API for HandlerService service. @@ -34,6 +36,8 @@ type HandlerServiceClient interface { AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error) RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error) AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error) + GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error) + GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error) AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error) @@ -77,6 +81,26 @@ func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboun return out, nil } +func (c *handlerServiceClient) GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetInboundUserResponse) + err := c.cc.Invoke(ctx, HandlerService_GetInboundUsers_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *handlerServiceClient) GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetInboundUsersCountResponse) + err := c.cc.Invoke(ctx, HandlerService_GetInboundUsersCount_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddOutboundResponse) @@ -114,6 +138,8 @@ type HandlerServiceServer interface { AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error) RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) + GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error) + GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error) AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error) RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) @@ -136,6 +162,12 @@ func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context, *RemoveI func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AlterInbound not implemented") } +func (UnimplementedHandlerServiceServer) GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsers not implemented") +} +func (UnimplementedHandlerServiceServer) GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsersCount not implemented") +} func (UnimplementedHandlerServiceServer) AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AddOutbound not implemented") } @@ -220,6 +252,42 @@ func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _HandlerService_GetInboundUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetInboundUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HandlerServiceServer).GetInboundUsers(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: HandlerService_GetInboundUsers_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).GetInboundUsers(ctx, req.(*GetInboundUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _HandlerService_GetInboundUsersCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetInboundUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HandlerServiceServer).GetInboundUsersCount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: HandlerService_GetInboundUsersCount_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HandlerServiceServer).GetInboundUsersCount(ctx, req.(*GetInboundUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _HandlerService_AddOutbound_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(AddOutboundRequest) if err := dec(in); err != nil { @@ -293,6 +361,14 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{ MethodName: "AlterInbound", Handler: _HandlerService_AlterInbound_Handler, }, + { + MethodName: "GetInboundUsers", + Handler: _HandlerService_GetInboundUsers_Handler, + }, + { + MethodName: "GetInboundUsersCount", + Handler: _HandlerService_GetInboundUsersCount_Handler, + }, { MethodName: "AddOutbound", Handler: _HandlerService_AddOutbound_Handler, diff --git a/common/protocol/account.go b/common/protocol/account.go index 7793974a..75568817 100644 --- a/common/protocol/account.go +++ b/common/protocol/account.go @@ -1,8 +1,11 @@ package protocol +import "google.golang.org/protobuf/proto" + // Account is a user identity used for authentication. type Account interface { Equals(Account) bool + ToProto() proto.Message } // AsAccount is an object can be converted into account. diff --git a/common/protocol/user.go b/common/protocol/user.go index d6e3a131..2986eb19 100644 --- a/common/protocol/user.go +++ b/common/protocol/user.go @@ -1,6 +1,9 @@ package protocol -import "github.com/xtls/xray-core/common/errors" +import ( + "github.com/xtls/xray-core/common/errors" + "github.com/xtls/xray-core/common/serial" +) func (u *User) GetTypedAccount() (Account, error) { if u.GetAccount() == nil { @@ -32,6 +35,17 @@ func (u *User) ToMemoryUser() (*MemoryUser, error) { }, nil } +func ToProtoUser(mu *MemoryUser) *User { + if mu == nil { + return nil + } + return &User{ + Account: serial.ToTypedMessage(mu.Account.ToProto()), + Email: mu.Email, + Level: mu.Level, + } +} + // MemoryUser is a parsed form of User, to reduce number of parsing of Account proto. type MemoryUser struct { // Account is the parsed account of the protocol. diff --git a/core/proto.go b/core/proto.go index b85d99d8..030365cc 100644 --- a/core/proto.go +++ b/core/proto.go @@ -1,5 +1,5 @@ package core -//go:generate go install -v google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.2 -//go:generate go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.5.1 +//go:generate go install -v google.golang.org/protobuf/cmd/protoc-gen-go@latest +//go:generate go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest //go:generate go run ../infra/vprotogen/main.go -pwd ./.. diff --git a/infra/conf/shadowsocks.go b/infra/conf/shadowsocks.go index 1bd6462c..f12040a6 100644 --- a/infra/conf/shadowsocks.go +++ b/infra/conf/shadowsocks.go @@ -126,9 +126,13 @@ func buildShadowsocks2022(v *ShadowsocksServerConfig) (proto.Message, error) { if user.Cipher != "" { return nil, errors.New("shadowsocks 2022 (multi-user): users must have empty method") } - config.Users = append(config.Users, &shadowsocks_2022.User{ - Key: user.Password, - Email: user.Email, + account := &shadowsocks_2022.Account{ + Key: user.Password, + } + config.Users = append(config.Users, &protocol.User{ + Email: user.Email, + Level: uint32(user.Level), + Account: serial.ToTypedMessage(account), }) } return config, nil diff --git a/main/commands/all/api/api.go b/main/commands/all/api/api.go index ea43d107..5e21884b 100644 --- a/main/commands/all/api/api.go +++ b/main/commands/all/api/api.go @@ -21,6 +21,8 @@ var CmdAPI = &base.Command{ cmdAddOutbounds, cmdRemoveInbounds, cmdRemoveOutbounds, + cmdInboundUser, + cmdInboundUserCount, cmdAddRules, cmdRemoveRules, cmdSourceIpBlock, diff --git a/main/commands/all/api/inbound_user.go b/main/commands/all/api/inbound_user.go new file mode 100644 index 00000000..6ffa4ebb --- /dev/null +++ b/main/commands/all/api/inbound_user.go @@ -0,0 +1,50 @@ +package api + +import ( + handlerService "github.com/xtls/xray-core/app/proxyman/command" + "github.com/xtls/xray-core/main/commands/base" +) + +var cmdInboundUser = &base.Command{ + CustomFlags: true, + UsageLine: "{{.Exec}} api inbounduser [--server=127.0.0.1:8080] -tag=tag [-email=email]", + Short: "Get Inbound User", + Long: ` +Get User info from an inbound. +Arguments: + -s, -server + The API server address. Default 127.0.0.1:8080 + -t, -timeout + Timeout seconds to call API. Default 3 + -tag + Inbound tag + -email + User email. If email is not given, will get all users +Example: + {{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name" -email="xray@love.com" +`, + Run: executeInboundUser, +} + +func executeInboundUser(cmd *base.Command, args []string) { + setSharedFlags(cmd) + var tag string + var email string + cmd.Flag.StringVar(&tag, "tag", "", "") + cmd.Flag.StringVar(&email, "email", "", "") + cmd.Flag.Parse(args) + + conn, ctx, close := dialAPIServer() + defer close() + + client := handlerService.NewHandlerServiceClient(conn) + r := &handlerService.GetInboundUserRequest{ + Tag: tag, + Email: email, + } + resp, err := client.GetInboundUsers(ctx, r) + if err != nil { + base.Fatalf("failed to get inbound user: %s", err) + } + showJSONResponse(resp) +} diff --git a/main/commands/all/api/inbound_user_count.go b/main/commands/all/api/inbound_user_count.go new file mode 100644 index 00000000..18cab7e8 --- /dev/null +++ b/main/commands/all/api/inbound_user_count.go @@ -0,0 +1,45 @@ +package api + +import ( + handlerService "github.com/xtls/xray-core/app/proxyman/command" + "github.com/xtls/xray-core/main/commands/base" +) + +var cmdInboundUserCount = &base.Command{ + CustomFlags: true, + UsageLine: "{{.Exec}} api inboundusercount [--server=127.0.0.1:8080] -tag=tag", + Short: "Get Inbound User Count", + Long: ` +Get User count from an inbound. +Arguments: + -s, -server + The API server address. Default 127.0.0.1:8080 + -t, -timeout + Timeout seconds to call API. Default 3 + -tag + Inbound tag +Example: + {{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name" +`, + Run: executeInboundUserCount, +} + +func executeInboundUserCount(cmd *base.Command, args []string) { + setSharedFlags(cmd) + var tag string + cmd.Flag.StringVar(&tag, "tag", "", "") + cmd.Flag.Parse(args) + + conn, ctx, close := dialAPIServer() + defer close() + + client := handlerService.NewHandlerServiceClient(conn) + r := &handlerService.GetInboundUserRequest{ + Tag: tag, + } + resp, err := client.GetInboundUsersCount(ctx, r) + if err != nil { + base.Fatalf("failed to get inbound user count: %s", err) + } + showJSONResponse(resp) +} diff --git a/proxy/http/config.go b/proxy/http/config.go index 00ce0795..a41bb010 100644 --- a/proxy/http/config.go +++ b/proxy/http/config.go @@ -1,6 +1,8 @@ package http import ( + "google.golang.org/protobuf/proto" + "github.com/xtls/xray-core/common/protocol" ) @@ -11,6 +13,10 @@ func (a *Account) Equals(another protocol.Account) bool { return false } +func (a *Account) ToProto() proto.Message { + return a +} + func (a *Account) AsAccount() (protocol.Account, error) { return a, nil } diff --git a/proxy/proxy.go b/proxy/proxy.go index b507cc39..868c8dfc 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -78,6 +78,15 @@ type UserManager interface { // RemoveUser removes a user by email. RemoveUser(context.Context, string) error + + // Get user by email. + GetUser(context.Context, string) *protocol.MemoryUser + + // Get all users. + GetUsers(context.Context) []*protocol.MemoryUser + + // Get users count. + GetUsersCount(context.Context) int64 } type GetInbound interface { diff --git a/proxy/shadowsocks/config.go b/proxy/shadowsocks/config.go index 396e59be..e2d812ab 100644 --- a/proxy/shadowsocks/config.go +++ b/proxy/shadowsocks/config.go @@ -6,6 +6,7 @@ import ( "crypto/cipher" "crypto/md5" "crypto/sha1" + "google.golang.org/protobuf/proto" "io" "github.com/xtls/xray-core/common" @@ -20,8 +21,10 @@ import ( // MemoryAccount is an account type converted from Account. type MemoryAccount struct { - Cipher Cipher - Key []byte + Cipher Cipher + CipherType CipherType + Key []byte + Password string replayFilter antireplay.GeneralizedReplayFilter } @@ -36,6 +39,14 @@ func (a *MemoryAccount) Equals(another protocol.Account) bool { return false } +func (a *MemoryAccount) ToProto() proto.Message { + return &Account{ + CipherType: a.CipherType, + Password: a.Password, + IvCheck: a.replayFilter != nil, + } +} + func (a *MemoryAccount) CheckIV(iv []byte) error { if a.replayFilter == nil { return nil @@ -107,7 +118,9 @@ func (a *Account) AsAccount() (protocol.Account, error) { } return &MemoryAccount{ Cipher: Cipher, + CipherType: a.CipherType, Key: passwordToCipherKey([]byte(a.Password), Cipher.KeySize()), + Password: a.Password, replayFilter: func() antireplay.GeneralizedReplayFilter { if a.IvCheck { return antireplay.NewBloomRing() diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index e6135a45..356868e4 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -63,6 +63,21 @@ func (s *Server) RemoveUser(ctx context.Context, e string) error { return s.validator.Del(e) } +// GetUser implements proxy.UserManager.GetUser(). +func (s *Server) GetUser(ctx context.Context, email string) *protocol.MemoryUser { + return s.validator.GetByEmail(email) +} + +// GetUsers implements proxy.UserManager.GetUsers(). +func (s *Server) GetUsers(ctx context.Context) []*protocol.MemoryUser { + return s.validator.GetAll() +} + +// GetUsersCount implements proxy.UserManager.GetUsersCount(). +func (s *Server) GetUsersCount(context.Context) int64 { + return s.validator.GetCount() +} + func (s *Server) Network() []net.Network { list := s.config.Network if len(list) == 0 { diff --git a/proxy/shadowsocks/validator.go b/proxy/shadowsocks/validator.go index ae92a8dc..84e59dc1 100644 --- a/proxy/shadowsocks/validator.go +++ b/proxy/shadowsocks/validator.go @@ -74,6 +74,40 @@ func (v *Validator) Del(email string) error { return nil } +// GetByEmail Get a Shadowsocks user with a non-empty Email. +func (v *Validator) GetByEmail(email string) *protocol.MemoryUser { + if email == "" { + return nil + } + + v.Lock() + defer v.Unlock() + + email = strings.ToLower(email) + for _, u := range v.users { + if strings.EqualFold(u.Email, email) { + return u + } + } + return nil +} + +// GetAll get all users +func (v *Validator) GetAll() []*protocol.MemoryUser { + v.Lock() + defer v.Unlock() + dst := make([]*protocol.MemoryUser, len(v.users)) + copy(dst, v.users) + return dst +} + +// GetCount get users count +func (v *Validator) GetCount() int64 { + v.Lock() + defer v.Unlock() + return int64(len(v.users)) +} + // Get a Shadowsocks user. func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol.MemoryUser, aead cipher.AEAD, ret []byte, ivLen int32, err error) { v.RLock() diff --git a/proxy/shadowsocks_2022/config.go b/proxy/shadowsocks_2022/config.go index 8a66406c..3678cd58 100644 --- a/proxy/shadowsocks_2022/config.go +++ b/proxy/shadowsocks_2022/config.go @@ -1,22 +1,20 @@ package shadowsocks_2022 import ( + "google.golang.org/protobuf/proto" + "github.com/xtls/xray-core/common/protocol" ) // MemoryAccount is an account type converted from Account. type MemoryAccount struct { Key string - Email string - Level int32 } // AsAccount implements protocol.AsAccount. -func (u *User) AsAccount() (protocol.Account, error) { +func (u *Account) AsAccount() (protocol.Account, error) { return &MemoryAccount{ Key: u.GetKey(), - Email: u.GetEmail(), - Level: u.GetLevel(), }, nil } @@ -27,3 +25,9 @@ func (a *MemoryAccount) Equals(another protocol.Account) bool { } return false } + +func (a *MemoryAccount) ToProto() proto.Message { + return &Account{ + Key: a.Key, + } +} diff --git a/proxy/shadowsocks_2022/config.pb.go b/proxy/shadowsocks_2022/config.pb.go index b47438ea..f2f78ad6 100644 --- a/proxy/shadowsocks_2022/config.pb.go +++ b/proxy/shadowsocks_2022/config.pb.go @@ -8,6 +8,7 @@ package shadowsocks_2022 import ( net "github.com/xtls/xray-core/common/net" + protocol "github.com/xtls/xray-core/common/protocol" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -103,10 +104,10 @@ type MultiUserServerConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` - Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` - Users []*User `protobuf:"bytes,3,rep,name=users,proto3" json:"users,omitempty"` - Network []net.Network `protobuf:"varint,4,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"` + Method string `protobuf:"bytes,1,opt,name=method,proto3" json:"method,omitempty"` + Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` + Users []*protocol.User `protobuf:"bytes,3,rep,name=users,proto3" json:"users,omitempty"` + Network []net.Network `protobuf:"varint,4,rep,packed,name=network,proto3,enum=xray.common.net.Network" json:"network,omitempty"` } func (x *MultiUserServerConfig) Reset() { @@ -153,7 +154,7 @@ func (x *MultiUserServerConfig) GetKey() string { return "" } -func (x *MultiUserServerConfig) GetUsers() []*User { +func (x *MultiUserServerConfig) GetUsers() []*protocol.User { if x != nil { return x.Users } @@ -313,30 +314,28 @@ func (x *RelayServerConfig) GetNetwork() []net.Network { return nil } -type User struct { +type Account struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` - Level int32 `protobuf:"varint,3,opt,name=level,proto3" json:"level,omitempty"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` } -func (x *User) Reset() { - *x = User{} +func (x *Account) Reset() { + *x = Account{} mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *User) String() string { +func (x *Account) String() string { return protoimpl.X.MessageStringOf(x) } -func (*User) ProtoMessage() {} +func (*Account) ProtoMessage() {} -func (x *User) ProtoReflect() protoreflect.Message { +func (x *Account) ProtoReflect() protoreflect.Message { mi := &file_proxy_shadowsocks_2022_config_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -348,32 +347,18 @@ func (x *User) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use User.ProtoReflect.Descriptor instead. -func (*User) Descriptor() ([]byte, []int) { +// Deprecated: Use Account.ProtoReflect.Descriptor instead. +func (*Account) Descriptor() ([]byte, []int) { return file_proxy_shadowsocks_2022_config_proto_rawDescGZIP(), []int{4} } -func (x *User) GetKey() string { +func (x *Account) GetKey() string { if x != nil { return x.Key } return "" } -func (x *User) GetEmail() string { - if x != nil { - return x.Email - } - return "" -} - -func (x *User) GetLevel() int32 { - if x != nil { - return x.Level - } - return 0 -} - type ClientConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -469,76 +454,74 @@ var file_proxy_shadowsocks_2022_config_proto_rawDesc = []byte{ 0x32, 0x32, 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, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0x98, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, + 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, 0x03, 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, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0xa7, 0x01, + 0x0a, 0x15, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x32, 0x0a, - 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x05, 0x20, 0x03, 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, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x22, 0xae, 0x01, 0x0a, 0x15, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x55, 0x73, 0x65, 0x72, 0x53, + 0x79, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, + 0x65, 0x72, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x04, + 0x20, 0x03, 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, + 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x9b, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x61, + 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x35, + 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, + 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, + 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xc4, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x37, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, - 0x32, 0x32, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x32, - 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x04, 0x20, 0x03, 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, 0x6e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x22, 0x9b, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x35, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, - 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, - 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, - 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, - 0x76, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x22, 0xc4, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x51, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, - 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x5f, - 0x32, 0x30, 0x32, 0x32, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x04, - 0x20, 0x03, 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, - 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x44, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0xd6, 0x01, - 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, - 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0c, 0x75, 0x64, 0x70, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, - 0x74, 0x63, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x64, 0x70, 0x4f, 0x76, - 0x65, 0x72, 0x54, 0x63, 0x70, 0x12, 0x2f, 0x0a, 0x14, 0x75, 0x64, 0x70, 0x5f, 0x6f, 0x76, 0x65, - 0x72, 0x5f, 0x74, 0x63, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x11, 0x75, 0x64, 0x70, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x63, 0x70, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x51, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, - 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0x50, 0x01, 0x5a, 0x30, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, - 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0xaa, 0x02, 0x1a, - 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, - 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x32, 0x30, 0x32, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x44, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x18, 0x04, 0x20, 0x03, 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, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22, 0x1b, 0x0a, 0x07, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0xd6, 0x01, 0x0a, 0x0c, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, + 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x20, 0x0a, 0x0c, 0x75, 0x64, 0x70, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x63, 0x70, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x64, 0x70, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x63, + 0x70, 0x12, 0x2f, 0x0a, 0x14, 0x75, 0x64, 0x70, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x63, + 0x70, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x11, 0x75, 0x64, 0x70, 0x4f, 0x76, 0x65, 0x72, 0x54, 0x63, 0x70, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x42, 0x72, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, + 0x5f, 0x32, 0x30, 0x32, 0x32, 0x50, 0x01, 0x5a, 0x30, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, + 0x6f, 0x63, 0x6b, 0x73, 0x5f, 0x32, 0x30, 0x32, 0x32, 0xaa, 0x02, 0x1a, 0x58, 0x72, 0x61, 0x79, + 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, + 0x6b, 0x73, 0x32, 0x30, 0x32, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -559,19 +542,20 @@ var file_proxy_shadowsocks_2022_config_proto_goTypes = []any{ (*MultiUserServerConfig)(nil), // 1: xray.proxy.shadowsocks_2022.MultiUserServerConfig (*RelayDestination)(nil), // 2: xray.proxy.shadowsocks_2022.RelayDestination (*RelayServerConfig)(nil), // 3: xray.proxy.shadowsocks_2022.RelayServerConfig - (*User)(nil), // 4: xray.proxy.shadowsocks_2022.User + (*Account)(nil), // 4: xray.proxy.shadowsocks_2022.Account (*ClientConfig)(nil), // 5: xray.proxy.shadowsocks_2022.ClientConfig (net.Network)(0), // 6: xray.common.net.Network - (*net.IPOrDomain)(nil), // 7: xray.common.net.IPOrDomain + (*protocol.User)(nil), // 7: xray.common.protocol.User + (*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain } var file_proxy_shadowsocks_2022_config_proto_depIdxs = []int32{ 6, // 0: xray.proxy.shadowsocks_2022.ServerConfig.network:type_name -> xray.common.net.Network - 4, // 1: xray.proxy.shadowsocks_2022.MultiUserServerConfig.users:type_name -> xray.proxy.shadowsocks_2022.User + 7, // 1: xray.proxy.shadowsocks_2022.MultiUserServerConfig.users:type_name -> xray.common.protocol.User 6, // 2: xray.proxy.shadowsocks_2022.MultiUserServerConfig.network:type_name -> xray.common.net.Network - 7, // 3: xray.proxy.shadowsocks_2022.RelayDestination.address:type_name -> xray.common.net.IPOrDomain + 8, // 3: xray.proxy.shadowsocks_2022.RelayDestination.address:type_name -> xray.common.net.IPOrDomain 2, // 4: xray.proxy.shadowsocks_2022.RelayServerConfig.destinations:type_name -> xray.proxy.shadowsocks_2022.RelayDestination 6, // 5: xray.proxy.shadowsocks_2022.RelayServerConfig.network:type_name -> xray.common.net.Network - 7, // 6: xray.proxy.shadowsocks_2022.ClientConfig.address:type_name -> xray.common.net.IPOrDomain + 8, // 6: xray.proxy.shadowsocks_2022.ClientConfig.address:type_name -> xray.common.net.IPOrDomain 7, // [7:7] is the sub-list for method output_type 7, // [7:7] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name diff --git a/proxy/shadowsocks_2022/config.proto b/proxy/shadowsocks_2022/config.proto index 60540991..14006648 100644 --- a/proxy/shadowsocks_2022/config.proto +++ b/proxy/shadowsocks_2022/config.proto @@ -8,6 +8,7 @@ option java_multiple_files = true; import "common/net/network.proto"; import "common/net/address.proto"; +import "common/protocol/user.proto"; message ServerConfig { string method = 1; @@ -20,7 +21,7 @@ message ServerConfig { message MultiUserServerConfig { string method = 1; string key = 2; - repeated User users = 3; + repeated xray.common.protocol.User users = 3; repeated xray.common.net.Network network = 4; } @@ -39,10 +40,8 @@ message RelayServerConfig { repeated xray.common.net.Network network = 4; } -message User { +message Account { string key = 1; - string email = 2; - int32 level = 3; } message ClientConfig { diff --git a/proxy/shadowsocks_2022/inbound_multi.go b/proxy/shadowsocks_2022/inbound_multi.go index 8cb2d65e..20b85139 100644 --- a/proxy/shadowsocks_2022/inbound_multi.go +++ b/proxy/shadowsocks_2022/inbound_multi.go @@ -37,7 +37,7 @@ func init() { type MultiUserInbound struct { sync.Mutex networks []net.Network - users []*User + users []*protocol.MemoryUser service *shadowaead_2022.MultiService[int] } @@ -49,9 +49,22 @@ func NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiU net.Network_UDP, } } + memUsers := []*protocol.MemoryUser{} + for i, user := range config.Users { + if user.Email == "" { + u := uuid.New() + user.Email = "unnamed-user-" + strconv.Itoa(i) + "-" + u.String() + } + u, err := user.ToMemoryUser() + if err != nil { + return nil, errors.New("failed to get shadowsocks user").Base(err).AtError() + } + memUsers = append(memUsers, u) + } + inbound := &MultiUserInbound{ networks: networks, - users: config.Users, + users: memUsers, } if config.Key == "" { return nil, errors.New("missing key") @@ -64,16 +77,9 @@ func NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiU if err != nil { return nil, errors.New("create service").Base(err) } - - for i, user := range config.Users { - if user.Email == "" { - u := uuid.New() - user.Email = "unnamed-user-" + strconv.Itoa(i) + "-" + u.String() - } - } err = service.UpdateUsersWithPasswords( - C.MapIndexed(config.Users, func(index int, it *User) int { return index }), - C.Map(config.Users, func(it *User) string { return it.Key }), + C.MapIndexed(memUsers, func(index int, it *protocol.MemoryUser) int { return index }), + C.Map(memUsers, func(it *protocol.MemoryUser) string { return it.Account.(*MemoryAccount).Key }), ) if err != nil { return nil, errors.New("create service").Base(err) @@ -88,25 +94,20 @@ func (i *MultiUserInbound) AddUser(ctx context.Context, u *protocol.MemoryUser) i.Lock() defer i.Unlock() - account := u.Account.(*MemoryAccount) - if account.Email != "" { + if u.Email != "" { for idx := range i.users { - if i.users[idx].Email == account.Email { - return errors.New("User ", account.Email, " already exists.") + if i.users[idx].Email == u.Email { + return errors.New("User ", u.Email, " already exists.") } } } - i.users = append(i.users, &User{ - Key: account.Key, - Email: account.Email, - Level: account.Level, - }) + i.users = append(i.users, u) // sync to multi service // Considering implements shadowsocks2022 in xray-core may have better performance. i.service.UpdateUsersWithPasswords( - C.MapIndexed(i.users, func(index int, it *User) int { return index }), - C.Map(i.users, func(it *User) string { return it.Key }), + C.MapIndexed(i.users, func(index int, it *protocol.MemoryUser) int { return index }), + C.Map(i.users, func(it *protocol.MemoryUser) string { return it.Account.(*MemoryAccount).Key }), ) return nil @@ -142,13 +143,46 @@ func (i *MultiUserInbound) RemoveUser(ctx context.Context, email string) error { // sync to multi service // Considering implements shadowsocks2022 in xray-core may have better performance. i.service.UpdateUsersWithPasswords( - C.MapIndexed(i.users, func(index int, it *User) int { return index }), - C.Map(i.users, func(it *User) string { return it.Key }), + C.MapIndexed(i.users, func(index int, it *protocol.MemoryUser) int { return index }), + C.Map(i.users, func(it *protocol.MemoryUser) string { return it.Account.(*MemoryAccount).Key }), ) return nil } +// GetUser implements proxy.UserManager.GetUser(). +func (i *MultiUserInbound) GetUser(ctx context.Context, email string) *protocol.MemoryUser { + if email == "" { + return nil + } + + i.Lock() + defer i.Unlock() + + for _, u := range i.users { + if strings.EqualFold(u.Email, email) { + return u + } + } + return nil +} + +// GetUsers implements proxy.UserManager.GetUsers(). +func (i *MultiUserInbound) GetUsers(ctx context.Context) []*protocol.MemoryUser { + i.Lock() + defer i.Unlock() + dst := make([]*protocol.MemoryUser, len(i.users)) + copy(dst, i.users) + return dst +} + +// GetUsersCount implements proxy.UserManager.GetUsersCount(). +func (i *MultiUserInbound) GetUsersCount(context.Context) int64 { + i.Lock() + defer i.Unlock() + return int64(len(i.users)) +} + func (i *MultiUserInbound) Network() []net.Network { return i.networks } @@ -194,10 +228,7 @@ func (i *MultiUserInbound) NewConnection(ctx context.Context, conn net.Conn, met inbound := session.InboundFromContext(ctx) userInt, _ := A.UserFromContext[int](ctx) user := i.users[userInt] - inbound.User = &protocol.MemoryUser{ - Email: user.Email, - Level: uint32(user.Level), - } + inbound.User = user ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ From: metadata.Source, To: metadata.Destination, @@ -222,10 +253,7 @@ func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.Packe inbound := session.InboundFromContext(ctx) userInt, _ := A.UserFromContext[int](ctx) user := i.users[userInt] - inbound.User = &protocol.MemoryUser{ - Email: user.Email, - Level: uint32(user.Level), - } + inbound.User = user ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ From: metadata.Source, To: metadata.Destination, diff --git a/proxy/socks/config.go b/proxy/socks/config.go index 3b162abe..e8aa328a 100644 --- a/proxy/socks/config.go +++ b/proxy/socks/config.go @@ -1,6 +1,10 @@ package socks -import "github.com/xtls/xray-core/common/protocol" +import ( + "google.golang.org/protobuf/proto" + + "github.com/xtls/xray-core/common/protocol" +) func (a *Account) Equals(another protocol.Account) bool { if account, ok := another.(*Account); ok { @@ -9,6 +13,10 @@ func (a *Account) Equals(another protocol.Account) bool { return false } +func (a *Account) ToProto() proto.Message { + return a +} + func (a *Account) AsAccount() (protocol.Account, error) { return a, nil } diff --git a/proxy/trojan/config.go b/proxy/trojan/config.go index a02dfe98..b7591996 100644 --- a/proxy/trojan/config.go +++ b/proxy/trojan/config.go @@ -3,7 +3,8 @@ package trojan import ( "crypto/sha256" "encoding/hex" - fmt "fmt" + "fmt" + "google.golang.org/protobuf/proto" "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/protocol" @@ -33,6 +34,12 @@ func (a *MemoryAccount) Equals(another protocol.Account) bool { return false } +func (a *MemoryAccount) ToProto() proto.Message { + return &Account{ + Password: a.Password, + } +} + func hexSha224(password string) []byte { buf := make([]byte, 56) hash := sha256.New224() diff --git a/proxy/trojan/server.go b/proxy/trojan/server.go index 6110eec0..20ac1fd1 100644 --- a/proxy/trojan/server.go +++ b/proxy/trojan/server.go @@ -125,6 +125,21 @@ func (s *Server) RemoveUser(ctx context.Context, e string) error { return s.validator.Del(e) } +// GetUser implements proxy.UserManager.GetUser(). +func (s *Server) GetUser(ctx context.Context, email string) *protocol.MemoryUser { + return s.validator.GetByEmail(email) +} + +// GetUsers implements proxy.UserManager.GetUsers(). +func (s *Server) GetUsers(ctx context.Context) []*protocol.MemoryUser { + return s.validator.GetAll() +} + +// GetUsersCount implements proxy.UserManager.GetUsersCount(). +func (s *Server) GetUsersCount(context.Context) int64 { + return s.validator.GetCount() +} + // Network implements proxy.Inbound.Network(). func (s *Server) Network() []net.Network { return []net.Network{net.Network_TCP, net.Network_UNIX} diff --git a/proxy/trojan/validator.go b/proxy/trojan/validator.go index 4ffe41a1..fb3499fa 100644 --- a/proxy/trojan/validator.go +++ b/proxy/trojan/validator.go @@ -50,3 +50,33 @@ func (v *Validator) Get(hash string) *protocol.MemoryUser { } return nil } + + +// Get a trojan user with hashed key, nil if user doesn't exist. +func (v *Validator) GetByEmail(email string) *protocol.MemoryUser { + u, _ := v.email.Load(email) + if u != nil { + return u.(*protocol.MemoryUser) + } + return nil +} + +// Get all users +func (v *Validator) GetAll() []*protocol.MemoryUser { + var u = make([]*protocol.MemoryUser, 0, 100) + v.email.Range(func(key, value interface{}) bool { + u = append(u, value.(*protocol.MemoryUser)) + return true + }) + return u +} + +// Get users count +func (v *Validator) GetCount() int64 { + var c int64 = 0 + v.email.Range(func(key, value interface{}) bool { + c++ + return true + }) + return c +} diff --git a/proxy/vless/account.go b/proxy/vless/account.go index 5349a3bd..798b93f4 100644 --- a/proxy/vless/account.go +++ b/proxy/vless/account.go @@ -1,6 +1,8 @@ package vless import ( + "google.golang.org/protobuf/proto" + "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/uuid" @@ -37,3 +39,11 @@ func (a *MemoryAccount) Equals(account protocol.Account) bool { } return a.ID.Equals(vlessAccount.ID) } + +func (a *MemoryAccount) ToProto() proto.Message { + return &Account{ + Id: a.ID.String(), + Flow: a.Flow, + Encryption: a.Encryption, + } +} diff --git a/proxy/vless/inbound/inbound.go b/proxy/vless/inbound/inbound.go index f443007d..48849eb2 100644 --- a/proxy/vless/inbound/inbound.go +++ b/proxy/vless/inbound/inbound.go @@ -172,6 +172,21 @@ func (h *Handler) RemoveUser(ctx context.Context, e string) error { return h.validator.Del(e) } +// GetUser implements proxy.UserManager.GetUser(). +func (h *Handler) GetUser(ctx context.Context, email string) *protocol.MemoryUser { + return h.validator.GetByEmail(email) +} + +// GetUsers implements proxy.UserManager.GetUsers(). +func (h *Handler) GetUsers(ctx context.Context) []*protocol.MemoryUser { + return h.validator.GetAll() +} + +// GetUsersCount implements proxy.UserManager.GetUsersCount(). +func (h *Handler) GetUsersCount(context.Context) int64 { + return h.validator.GetCount() +} + // Network implements proxy.Inbound.Network(). func (*Handler) Network() []net.Network { return []net.Network{net.Network_TCP, net.Network_UNIX} diff --git a/proxy/vless/validator.go b/proxy/vless/validator.go index 596cb62f..ddac6cbb 100644 --- a/proxy/vless/validator.go +++ b/proxy/vless/validator.go @@ -13,6 +13,9 @@ type Validator interface { Get(id uuid.UUID) *protocol.MemoryUser Add(u *protocol.MemoryUser) error Del(email string) error + GetByEmail(email string) *protocol.MemoryUser + GetAll() []*protocol.MemoryUser + GetCount() int64 } // MemoryValidator stores valid VLESS users. @@ -57,3 +60,32 @@ func (v *MemoryValidator) Get(id uuid.UUID) *protocol.MemoryUser { } return nil } + +// Get a VLESS user with email, nil if user doesn't exist. +func (v *MemoryValidator) GetByEmail(email string) *protocol.MemoryUser { + u, _ := v.email.Load(email) + if u != nil { + return u.(*protocol.MemoryUser) + } + return nil +} + +// Get all users +func (v *MemoryValidator) GetAll() []*protocol.MemoryUser { + var u = make([]*protocol.MemoryUser, 0, 100) + v.email.Range(func(key, value interface{}) bool { + u = append(u, value.(*protocol.MemoryUser)) + return true + }) + return u +} + +// Get users count +func (v *MemoryValidator) GetCount() int64 { + var c int64 = 0 + v.email.Range(func(key, value interface{}) bool { + c++ + return true + }) + return c +} diff --git a/proxy/vmess/account.go b/proxy/vmess/account.go index 5ece7a57..d063f9f5 100644 --- a/proxy/vmess/account.go +++ b/proxy/vmess/account.go @@ -1,6 +1,7 @@ package vmess import ( + "google.golang.org/protobuf/proto" "strings" "github.com/xtls/xray-core/common/errors" @@ -28,6 +29,21 @@ func (a *MemoryAccount) Equals(account protocol.Account) bool { return a.ID.Equals(vmessAccount.ID) } +func (a *MemoryAccount) ToProto() proto.Message { + var test = "" + if a.AuthenticatedLengthExperiment { + test = "AuthenticatedLength|" + } + if a.NoTerminationSignal { + test = test + "NoTerminationSignal" + } + return &Account{ + Id: a.ID.String(), + TestsEnabled: test, + SecuritySettings: &protocol.SecurityConfig{Type: a.Security}, + } +} + // AsAccount implements protocol.Account. func (a *Account) AsAccount() (protocol.Account, error) { id, err := uuid.ParseString(a.Id) diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 3102414d..28b560d8 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -56,7 +56,7 @@ func (v *userByEmail) Add(u *protocol.MemoryUser) bool { return v.addNoLock(u) } -func (v *userByEmail) Get(email string) (*protocol.MemoryUser, bool) { +func (v *userByEmail) GetOrGenerate(email string) (*protocol.MemoryUser, bool) { email = strings.ToLower(email) v.Lock() @@ -80,6 +80,13 @@ func (v *userByEmail) Get(email string) (*protocol.MemoryUser, bool) { return user, found } +func (v *userByEmail) Get(email string) *protocol.MemoryUser { + email = strings.ToLower(email) + v.Lock() + defer v.Unlock() + return v.cache[email] +} + func (v *userByEmail) Remove(email string) bool { email = strings.ToLower(email) @@ -141,14 +148,26 @@ func (*Handler) Network() []net.Network { return []net.Network{net.Network_TCP, net.Network_UNIX} } -func (h *Handler) GetUser(email string) *protocol.MemoryUser { - user, existing := h.usersByEmail.Get(email) +func (h *Handler) GetOrGenerateUser(email string) *protocol.MemoryUser { + user, existing := h.usersByEmail.GetOrGenerate(email) if !existing { h.clients.Add(user) } return user } +func (h *Handler) GetUser(ctx context.Context, email string) *protocol.MemoryUser { + return h.usersByEmail.Get(email) +} + +func (h *Handler) GetUsers(ctx context.Context) []*protocol.MemoryUser { + return h.clients.GetUsers() +} + +func (h *Handler) GetUsersCount(context.Context) int64 { + return h.clients.GetCount() +} + func (h *Handler) AddUser(ctx context.Context, user *protocol.MemoryUser) error { if len(user.Email) > 0 && !h.usersByEmail.Add(user) { return errors.New("User ", user.Email, " already exists.") @@ -321,7 +340,7 @@ func (h *Handler) generateCommand(ctx context.Context, request *protocol.Request } errors.LogDebug(ctx, "pick detour handler for port ", port, " for ", availableMin, " minutes.") - user := inboundHandler.GetUser(request.User.Email) + user := inboundHandler.GetOrGenerateUser(request.User.Email) if user == nil { return nil } diff --git a/proxy/vmess/validator.go b/proxy/vmess/validator.go index 43ced006..b3a82f30 100644 --- a/proxy/vmess/validator.go +++ b/proxy/vmess/validator.go @@ -56,6 +56,20 @@ func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error { return nil } +func (v *TimedUserValidator) GetUsers() []*protocol.MemoryUser { + v.Lock() + defer v.Unlock() + dst := make([]*protocol.MemoryUser, len(v.users)) + copy(dst, v.users) + return dst +} + +func (v *TimedUserValidator) GetCount() int64 { + v.Lock() + defer v.Unlock() + return int64(len(v.users)) +} + func (v *TimedUserValidator) GetAEAD(userHash []byte) (*protocol.MemoryUser, bool, error) { v.RLock() defer v.RUnlock()