diff --git a/README.md b/README.md index b1d5d76..0288f4f 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,8 @@ The node uses the `common/service.proto` file messages for both protocols. | `Stat` | Contains:
- `name` (string): Stat name.
- `type` (string): Stat type.
- `link` (string): Link associated with the stat.
- `value` (int64): Stat value. | | `StatResponse` | Contains:
- `stats` ([]Stat): List of stats. | | `StatRequest` | Contains:
- `name` (string): Name of the stat to request, user email or inbound \ outbound tag.
- `reset` (bool) Whether to reset traffic stats. | -| `OnlineStatResponse` | Contains:
- `email` (string): User's email.
- `value` (int64): Online stat value. | +| `OnlineStatResponse` | Contains:
- `name` (string): User's email.
- `value` (int64): Online connection number. | +| `OnlineStatResponse` | Contains:
- `name` (string): User's email.
- `value` (map): Online stat value. | | `BackendStatsResponse` | Contains:
- `num_goroutine` (uint32): Number of goroutines.
- `num_gc` (uint32): Number of garbage collections.
- `alloc` (uint64): Allocated memory.
- `total_alloc` (uint64): Total allocated memory.
- `sys` (uint64): System memory.
- `mallocs` (uint64): Number of mallocs.
- `frees` (uint64): Number of frees.
- `live_objects` (uint64): Number of live objects.
- `pause_total_ns` (uint64): Total pause time in nanoseconds.
- `uptime` (uint32): Uptime in seconds. | | `SystemStatsResponse` | Contains:
- `mem_total` (uint64): Total memory.
- `mem_used` (uint64): Used memory.
- `cpu_cores` (uint64): Number of CPU cores.
- `cpu_usage` (double): CPU usage percentage.
- `incoming_bandwidth_speed` (uint64): Incoming bandwidth speed.
- `outgoing_bandwidth_speed` (uint64): Outgoing bandwidth speed. | | `Users` | Contains:
- `users` ([]User): List of users. | @@ -102,23 +103,24 @@ The node uses the `common/service.proto` file messages for both protocols. - Use `Authorization Bearer ` in the header for authentication with the **REST API**. - Use `authorization Bearer ` in metadata for authentication with **gRPC**. -| gRPC | REST | Input | Output | Description | -|:-----------------------|:---------------------------|---------------|--------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `Start()` | `POST`,`/start` | `Backend` | `BaseInfoResponse` | This is the only method called before creating a connection. | -| `Stop()` | `PUT`,`/stop` | `Empty` | `Empty` | Stops the backend and deactivates the connection with the client. | -| `GetBaseInfo()` | `GET`,`/info` | `Empty` | `BaseInfoResponse` | Returns base info; can be used to check the connection between the node and client. | -| `GetLogs()` | `GET`,`/logs` | `Empty` | gRPC: (stream `Log`)
REST API: (`SSE`) | This method is a `SSE` connection in the REST protocol, but in gRPC, it provides a stream connection. | -| `GetSystemStats()` | `GET`,`/stats/system` | `Empty` | `SystemStatsResponse` | Retrieves system statistics. | -| `GetBackendStats()` | `GET`,`/stats/backend` | `Empty` | `BackendStatsResponse` | Retrieves backend statistics. | -| `GetOutboundsStats()` | `GET`, `/stats/outbounds` | `StatRequest` | `StatResponse` | Retrieves outbound statistics. The `name` field in the request will be ignored. | -| `GetOutboundStats()` | `GET`,`/stats/outbound` | `StatRequest` | `StatResponse` | Retrieves statistics for a specific outbound. | -| `GetInboundsStats()` | `GET`,`/stats/inbounds` | `StatRequest` | `StatResponse` | Retrieves inbound statistics. The `name` field in the request will be ignored. | -| `GetInboundStats()` | `GET`,`/stats/inbound` | `StatRequest` | `StatResponse` | Retrieves statistics for a specific inbound. | -| `GetUsersStats()` | `GET`,`/stats/users` | `StatRequest` | `StatResponse` | Retrieves user statistics and resets traffic stats. The `name` field in the request will be ignored. | -| `GetUserStats()` | `GET`,`/stats/user` | `StatRequest` | `StatResponse` | Retrieves statistics for a specific user. | -| `GetUserOnlineStats()` | `GET`,`/stats/user/online` | `StatRequest` | `StatResponse` | Retrieves online statistics for a specific user. The `reset` field in the request will be ignored | -| `SyncUser()` | `PUT`,`/user/sync` | `User` | `Empty` | Adds/updates/removes a user in the core. To remove a user, ensure you send empty inbounds. Provides a stream in `gRPC` but must be called for each user in the `REST API`. | -| `SyncUsers()` | `PUT`,`/users/sync` | `Users` | `Empty` | Removes all old users and replaces them with the provided users. | +| gRPC | REST | Input | Output | Description | +|:-----------------------------|:------------------------------|---------------|--------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Start()` | `POST`,`/start` | `Backend` | `BaseInfoResponse` | This is the only method called before creating a connection. | +| `Stop()` | `PUT`,`/stop` | `Empty` | `Empty` | Stops the backend and deactivates the connection with the client. | +| `GetBaseInfo()` | `GET`,`/info` | `Empty` | `BaseInfoResponse` | Returns base info; can be used to check the connection between the node and client. | +| `GetLogs()` | `GET`,`/logs` | `Empty` | gRPC: (stream `Log`)
REST API: (`SSE`) | This method is a `SSE` connection in the REST protocol, but in gRPC, it provides a stream connection. | +| `GetSystemStats()` | `GET`,`/stats/system` | `Empty` | `SystemStatsResponse` | Retrieves system statistics. | +| `GetBackendStats()` | `GET`,`/stats/backend` | `Empty` | `BackendStatsResponse` | Retrieves backend statistics. | +| `GetOutboundsStats()` | `GET`, `/stats/outbounds` | `StatRequest` | `StatResponse` | Retrieves outbound statistics. The `name` field in the request will be ignored. | +| `GetOutboundStats()` | `GET`,`/stats/outbound` | `StatRequest` | `StatResponse` | Retrieves statistics for a specific outbound. | +| `GetInboundsStats()` | `GET`,`/stats/inbounds` | `StatRequest` | `StatResponse` | Retrieves inbound statistics. The `name` field in the request will be ignored. | +| `GetInboundStats()` | `GET`,`/stats/inbound` | `StatRequest` | `StatResponse` | Retrieves statistics for a specific inbound. | +| `GetUsersStats()` | `GET`,`/stats/users` | `StatRequest` | `StatResponse` | Retrieves user statistics and resets traffic stats. The `name` field in the request will be ignored. | +| `GetUserStats()` | `GET`,`/stats/user` | `StatRequest` | `StatResponse` | Retrieves statistics for a specific user. | +| `GetUserOnlineStats()` | `GET`,`/stats/user/online` | `StatRequest` | `OnlineStatResponse` | Retrieves online statistics for a specific user. The `reset` field in the request will be ignored | +| `GetUserOnlineIpListStats()` | `GET`,`/stats/user/online_ip` | `StatRequest` | `StatsOnlineIpListResponse` | Retrieves ip list statistics for a specific user. The `reset` field in the request will be ignored | +| `SyncUser()` | `PUT`,`/user/sync` | `User` | `Empty` | Adds/updates/removes a user in the core. To remove a user, ensure you send empty inbounds. Provides a stream in `gRPC` but must be called for each user in the `REST API`. | +| `SyncUsers()` | `PUT`,`/users/sync` | `Users` | `Empty` | Removes all old users and replaces them with the provided users. | # Official library We create some library's for you so make your job easier diff --git a/backend/backend.go b/backend/backend.go index 723470d..6a996c5 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -18,7 +18,8 @@ type Backend interface { GetSysStats(context.Context) (*common.BackendStatsResponse, error) GetUsersStats(context.Context, bool) (*common.StatResponse, error) GetUserStats(context.Context, string, bool) (*common.StatResponse, error) - GetStatOnline(context.Context, string) (*common.OnlineStatResponse, error) + GetUserOnlineStats(context.Context, string) (*common.OnlineStatResponse, error) + GetUserOnlineIpListStats(context.Context, string) (*common.StatsOnlineIpListResponse, error) GetOutboundsStats(context.Context, bool) (*common.StatResponse, error) GetOutboundStats(context.Context, string, bool) (*common.StatResponse, error) GetInboundsStats(context.Context, bool) (*common.StatResponse, error) diff --git a/backend/xray/api/stats.go b/backend/xray/api/stats.go index 8f07a4c..85b27b0 100644 --- a/backend/xray/api/stats.go +++ b/backend/xray/api/stats.go @@ -43,14 +43,24 @@ func (x *XrayHandler) QueryStats(ctx context.Context, pattern string, reset bool return resp, nil } -func (x *XrayHandler) GetStatOnline(ctx context.Context, email string) (*common.OnlineStatResponse, error) { +func (x *XrayHandler) GetUserOnlineStats(ctx context.Context, email string) (*common.OnlineStatResponse, error) { client := *x.StatsServiceClient resp, err := client.GetStatsOnline(ctx, &command.GetStatsRequest{Name: email}) if err != nil { return nil, err } - return &common.OnlineStatResponse{Email: email, Value: resp.GetStat().Value}, nil + return &common.OnlineStatResponse{Name: email, Value: resp.GetStat().GetValue()}, nil +} + +func (x *XrayHandler) GetUserOnlineIpListStats(ctx context.Context, email string) (*common.StatsOnlineIpListResponse, error) { + client := *x.StatsServiceClient + resp, err := client.GetStatsOnlineIpList(ctx, &command.GetStatsRequest{Name: email}) + if err != nil { + return nil, err + } + + return &common.StatsOnlineIpListResponse{Name: email, Ips: resp.GetIps()}, nil } func (x *XrayHandler) GetUsersStats(ctx context.Context, reset bool) (*common.StatResponse, error) { diff --git a/backend/xray/xray.go b/backend/xray/xray.go index 47f853a..6bbe547 100644 --- a/backend/xray/xray.go +++ b/backend/xray/xray.go @@ -191,8 +191,12 @@ func (x *Xray) GetUserStats(ctx context.Context, email string, reset bool) (*com return x.handler.GetUserStats(ctx, email, reset) } -func (x *Xray) GetStatOnline(ctx context.Context, email string) (*common.OnlineStatResponse, error) { - return x.handler.GetStatOnline(ctx, email) +func (x *Xray) GetUserOnlineStats(ctx context.Context, email string) (*common.OnlineStatResponse, error) { + return x.handler.GetUserOnlineStats(ctx, email) +} + +func (x *Xray) GetUserOnlineIpListStats(ctx context.Context, email string) (*common.StatsOnlineIpListResponse, error) { + return x.handler.GetUserOnlineIpListStats(ctx, email) } func (x *Xray) GetOutboundsStats(ctx context.Context, reset bool) (*common.StatResponse, error) { diff --git a/common/service.pb.go b/common/service.pb.go index a703821..88be547 100644 --- a/common/service.pb.go +++ b/common/service.pb.go @@ -465,7 +465,7 @@ type OnlineStatResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Value int64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` } @@ -499,9 +499,9 @@ func (*OnlineStatResponse) Descriptor() ([]byte, []int) { return file_common_service_proto_rawDescGZIP(), []int{7} } -func (x *OnlineStatResponse) GetEmail() string { +func (x *OnlineStatResponse) GetName() string { if x != nil { - return x.Email + return x.Name } return "" } @@ -513,6 +513,59 @@ func (x *OnlineStatResponse) GetValue() int64 { return 0 } +type StatsOnlineIpListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Ips map[string]int64 `protobuf:"bytes,2,rep,name=ips,proto3" json:"ips,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (x *StatsOnlineIpListResponse) Reset() { + *x = StatsOnlineIpListResponse{} + mi := &file_common_service_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StatsOnlineIpListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatsOnlineIpListResponse) ProtoMessage() {} + +func (x *StatsOnlineIpListResponse) ProtoReflect() protoreflect.Message { + mi := &file_common_service_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 StatsOnlineIpListResponse.ProtoReflect.Descriptor instead. +func (*StatsOnlineIpListResponse) Descriptor() ([]byte, []int) { + return file_common_service_proto_rawDescGZIP(), []int{8} +} + +func (x *StatsOnlineIpListResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *StatsOnlineIpListResponse) GetIps() map[string]int64 { + if x != nil { + return x.Ips + } + return nil +} + type BackendStatsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -532,7 +585,7 @@ type BackendStatsResponse struct { func (x *BackendStatsResponse) Reset() { *x = BackendStatsResponse{} - mi := &file_common_service_proto_msgTypes[8] + mi := &file_common_service_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -544,7 +597,7 @@ func (x *BackendStatsResponse) String() string { func (*BackendStatsResponse) ProtoMessage() {} func (x *BackendStatsResponse) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[8] + mi := &file_common_service_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -557,7 +610,7 @@ func (x *BackendStatsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BackendStatsResponse.ProtoReflect.Descriptor instead. func (*BackendStatsResponse) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{8} + return file_common_service_proto_rawDescGZIP(), []int{9} } func (x *BackendStatsResponse) GetNumGoroutine() uint32 { @@ -645,7 +698,7 @@ type SystemStatsResponse struct { func (x *SystemStatsResponse) Reset() { *x = SystemStatsResponse{} - mi := &file_common_service_proto_msgTypes[9] + mi := &file_common_service_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -657,7 +710,7 @@ func (x *SystemStatsResponse) String() string { func (*SystemStatsResponse) ProtoMessage() {} func (x *SystemStatsResponse) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[9] + mi := &file_common_service_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -670,7 +723,7 @@ func (x *SystemStatsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemStatsResponse.ProtoReflect.Descriptor instead. func (*SystemStatsResponse) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{9} + return file_common_service_proto_rawDescGZIP(), []int{10} } func (x *SystemStatsResponse) GetMemTotal() uint64 { @@ -726,7 +779,7 @@ type Vmess struct { func (x *Vmess) Reset() { *x = Vmess{} - mi := &file_common_service_proto_msgTypes[10] + mi := &file_common_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -738,7 +791,7 @@ func (x *Vmess) String() string { func (*Vmess) ProtoMessage() {} func (x *Vmess) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[10] + mi := &file_common_service_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -751,7 +804,7 @@ func (x *Vmess) ProtoReflect() protoreflect.Message { // Deprecated: Use Vmess.ProtoReflect.Descriptor instead. func (*Vmess) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{10} + return file_common_service_proto_rawDescGZIP(), []int{11} } func (x *Vmess) GetId() string { @@ -772,7 +825,7 @@ type Vless struct { func (x *Vless) Reset() { *x = Vless{} - mi := &file_common_service_proto_msgTypes[11] + mi := &file_common_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -784,7 +837,7 @@ func (x *Vless) String() string { func (*Vless) ProtoMessage() {} func (x *Vless) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[11] + mi := &file_common_service_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -797,7 +850,7 @@ func (x *Vless) ProtoReflect() protoreflect.Message { // Deprecated: Use Vless.ProtoReflect.Descriptor instead. func (*Vless) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{11} + return file_common_service_proto_rawDescGZIP(), []int{12} } func (x *Vless) GetId() string { @@ -824,7 +877,7 @@ type Trojan struct { func (x *Trojan) Reset() { *x = Trojan{} - mi := &file_common_service_proto_msgTypes[12] + mi := &file_common_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -836,7 +889,7 @@ func (x *Trojan) String() string { func (*Trojan) ProtoMessage() {} func (x *Trojan) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[12] + mi := &file_common_service_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -849,7 +902,7 @@ func (x *Trojan) ProtoReflect() protoreflect.Message { // Deprecated: Use Trojan.ProtoReflect.Descriptor instead. func (*Trojan) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{12} + return file_common_service_proto_rawDescGZIP(), []int{13} } func (x *Trojan) GetPassword() string { @@ -870,7 +923,7 @@ type Shadowsocks struct { func (x *Shadowsocks) Reset() { *x = Shadowsocks{} - mi := &file_common_service_proto_msgTypes[13] + mi := &file_common_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -882,7 +935,7 @@ func (x *Shadowsocks) String() string { func (*Shadowsocks) ProtoMessage() {} func (x *Shadowsocks) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[13] + mi := &file_common_service_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -895,7 +948,7 @@ func (x *Shadowsocks) ProtoReflect() protoreflect.Message { // Deprecated: Use Shadowsocks.ProtoReflect.Descriptor instead. func (*Shadowsocks) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{13} + return file_common_service_proto_rawDescGZIP(), []int{14} } func (x *Shadowsocks) GetPassword() string { @@ -925,7 +978,7 @@ type Proxy struct { func (x *Proxy) Reset() { *x = Proxy{} - mi := &file_common_service_proto_msgTypes[14] + mi := &file_common_service_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -937,7 +990,7 @@ func (x *Proxy) String() string { func (*Proxy) ProtoMessage() {} func (x *Proxy) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[14] + mi := &file_common_service_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -950,7 +1003,7 @@ func (x *Proxy) ProtoReflect() protoreflect.Message { // Deprecated: Use Proxy.ProtoReflect.Descriptor instead. func (*Proxy) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{14} + return file_common_service_proto_rawDescGZIP(), []int{15} } func (x *Proxy) GetVmess() *Vmess { @@ -993,7 +1046,7 @@ type User struct { func (x *User) Reset() { *x = User{} - mi := &file_common_service_proto_msgTypes[15] + mi := &file_common_service_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1005,7 +1058,7 @@ func (x *User) String() string { func (*User) ProtoMessage() {} func (x *User) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[15] + mi := &file_common_service_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1018,7 +1071,7 @@ func (x *User) ProtoReflect() protoreflect.Message { // Deprecated: Use User.ProtoReflect.Descriptor instead. func (*User) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{15} + return file_common_service_proto_rawDescGZIP(), []int{16} } func (x *User) GetEmail() string { @@ -1052,7 +1105,7 @@ type Users struct { func (x *Users) Reset() { *x = Users{} - mi := &file_common_service_proto_msgTypes[16] + mi := &file_common_service_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1064,7 +1117,7 @@ func (x *Users) String() string { func (*Users) ProtoMessage() {} func (x *Users) ProtoReflect() protoreflect.Message { - mi := &file_common_service_proto_msgTypes[16] + mi := &file_common_service_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1077,7 +1130,7 @@ func (x *Users) ProtoReflect() protoreflect.Message { // Deprecated: Use Users.ProtoReflect.Descriptor instead. func (*Users) Descriptor() ([]byte, []int) { - return file_common_service_proto_rawDescGZIP(), []int{16} + return file_common_service_proto_rawDescGZIP(), []int{17} } func (x *Users) GetUsers() []*User { @@ -1126,139 +1179,155 @@ var file_common_service_proto_rawDesc = []byte{ 0x74, 0x73, 0x22, 0x37, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x22, 0x40, 0x0a, 0x12, 0x4f, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x65, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x0a, 0x12, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xac, 0x02, - 0x0a, 0x14, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x67, 0x6f, - 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, - 0x75, 0x6d, 0x47, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6e, - 0x75, 0x6d, 0x5f, 0x67, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6e, 0x75, 0x6d, - 0x47, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, - 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x73, 0x79, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, - 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, - 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x72, 0x65, 0x65, 0x73, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x66, 0x72, 0x65, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6c, - 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0b, 0x6c, 0x69, 0x76, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x24, - 0x0a, 0x0e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x6e, 0x73, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, 0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, - 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x22, 0xfb, 0x01, 0x0a, - 0x13, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x54, 0x6f, 0x74, 0x61, - 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, - 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x08, 0x63, 0x70, 0x75, 0x43, 0x6f, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, - 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x63, 0x70, - 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x18, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, - 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x73, 0x70, 0x65, - 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, - 0x6e, 0x67, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x53, 0x70, 0x65, 0x65, 0x64, - 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6e, - 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x16, 0x6f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x6e, 0x64, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x53, 0x70, 0x65, 0x65, 0x64, 0x22, 0x17, 0x0a, 0x05, 0x56, 0x6d, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x19, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, + 0x03, 0x69, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, + 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x69, 0x70, 0x73, 0x1a, 0x36, 0x0a, 0x08, + 0x49, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xac, 0x02, 0x0a, 0x14, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, + 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x67, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x47, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, + 0x6e, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x5f, 0x67, 0x63, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x6e, 0x75, 0x6d, 0x47, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x6c, + 0x6f, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x12, + 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, + 0x12, 0x10, 0x0a, 0x03, 0x73, 0x79, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x73, + 0x79, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x66, 0x72, 0x65, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x66, 0x72, 0x65, + 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6c, 0x69, 0x76, 0x65, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x5f, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x6e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x70, + 0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x75, + 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x75, 0x70, 0x74, + 0x69, 0x6d, 0x65, 0x22, 0xfb, 0x01, 0x0a, 0x13, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, + 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, + 0x65, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, + 0x6d, 0x65, 0x6d, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65, 0x6d, 0x5f, + 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x55, + 0x73, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x63, 0x70, 0x75, 0x43, 0x6f, 0x72, 0x65, 0x73, + 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x70, 0x75, 0x5f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x08, 0x63, 0x70, 0x75, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, + 0x18, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x5f, 0x73, 0x70, 0x65, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x16, 0x69, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, + 0x74, 0x68, 0x53, 0x70, 0x65, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x6f, 0x75, 0x74, 0x67, 0x6f, + 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x73, 0x70, + 0x65, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x6f, 0x75, 0x74, 0x67, 0x6f, + 0x69, 0x6e, 0x67, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x53, 0x70, 0x65, 0x65, + 0x64, 0x22, 0x17, 0x0a, 0x05, 0x56, 0x6d, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2b, 0x0a, 0x05, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x22, 0x2b, 0x0a, 0x05, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, - 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, - 0x22, 0x24, 0x0a, 0x06, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, - 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, - 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x41, 0x0a, 0x0b, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, - 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, - 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0xb4, 0x01, 0x0a, 0x05, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x12, 0x24, 0x0a, 0x05, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x56, 0x6d, 0x65, - 0x73, 0x73, 0x52, 0x05, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x05, 0x76, 0x6c, 0x65, - 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x05, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x12, - 0x27, 0x0a, 0x06, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, - 0x52, 0x06, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x64, - 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, - 0x63, 0x6b, 0x73, 0x52, 0x0b, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, - 0x22, 0x62, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x28, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x73, 0x22, 0x2c, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x23, 0x0a, - 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, - 0x72, 0x73, 0x2a, 0x17, 0x0a, 0x0b, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x08, 0x0a, 0x04, 0x58, 0x52, 0x41, 0x59, 0x10, 0x00, 0x32, 0x92, 0x07, 0x0a, 0x0b, - 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x1a, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x28, 0x0a, 0x04, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x0e, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0e, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x07, 0x47, 0x65, 0x74, - 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, - 0x6f, 0x67, 0x22, 0x00, 0x30, 0x01, 0x12, 0x40, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x0e, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x53, 0x74, 0x61, 0x74, - 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x41, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, - 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x22, 0x24, 0x0a, 0x06, 0x54, 0x72, 0x6f, 0x6a, 0x61, + 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x41, 0x0a, + 0x0b, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x22, 0xb4, 0x01, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x24, 0x0a, 0x05, 0x76, 0x6d, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x56, 0x6d, 0x65, 0x73, 0x73, 0x52, 0x05, 0x76, 0x6d, 0x65, 0x73, 0x73, + 0x12, 0x24, 0x0a, 0x05, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, + 0x05, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x27, 0x0a, 0x06, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x54, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x52, 0x06, 0x74, 0x72, 0x6f, 0x6a, 0x61, 0x6e, 0x12, + 0x36, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, + 0x68, 0x61, 0x64, 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x52, 0x0b, 0x73, 0x68, 0x61, 0x64, + 0x6f, 0x77, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x22, 0x62, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, 0x12, + 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x08, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x2c, 0x0a, 0x05, 0x55, + 0x73, 0x65, 0x72, 0x73, 0x12, 0x23, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x2a, 0x17, 0x0a, 0x0b, 0x42, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x58, 0x52, 0x41, 0x59, + 0x10, 0x00, 0x32, 0xea, 0x07, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x1a, 0x19, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61, 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x28, 0x0a, 0x04, 0x53, 0x74, + 0x6f, 0x70, 0x12, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42, 0x61, 0x73, 0x65, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61, + 0x73, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x2b, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x0e, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0c, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x22, 0x00, 0x30, 0x01, 0x12, 0x40, 0x0a, + 0x0e, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, + 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x42, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x12, 0x0e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x42, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4f, 0x6e, - 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x08, 0x53, 0x79, 0x6e, 0x63, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0d, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x0e, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, - 0x01, 0x12, 0x2d, 0x0a, 0x09, 0x53, 0x79, 0x6e, 0x63, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x0e, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x1a, 0x0e, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, - 0x42, 0x18, 0x5a, 0x16, 0x6d, 0x61, 0x72, 0x7a, 0x62, 0x61, 0x6e, 0x5f, 0x6e, 0x6f, 0x64, 0x65, - 0x5f, 0x67, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x75, + 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x10, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x3e, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x3d, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, + 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x49, + 0x0a, 0x12, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x74, 0x61, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x18, 0x47, 0x65, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, + 0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x2d, 0x0a, 0x08, 0x53, 0x79, 0x6e, 0x63, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0d, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x1a, 0x0e, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, + 0x12, 0x2d, 0x0a, 0x09, 0x53, 0x79, 0x6e, 0x63, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x0e, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x73, 0x1a, 0x0e, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, + 0x18, 0x5a, 0x16, 0x6d, 0x61, 0x72, 0x7a, 0x62, 0x61, 0x6e, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, + 0x67, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -1274,72 +1343,77 @@ func file_common_service_proto_rawDescGZIP() []byte { } var file_common_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_common_service_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_common_service_proto_msgTypes = make([]protoimpl.MessageInfo, 19) var file_common_service_proto_goTypes = []any{ - (BackendType)(0), // 0: service.BackendType - (*Empty)(nil), // 1: service.Empty - (*BaseInfoResponse)(nil), // 2: service.BaseInfoResponse - (*Backend)(nil), // 3: service.Backend - (*Log)(nil), // 4: service.Log - (*Stat)(nil), // 5: service.Stat - (*StatResponse)(nil), // 6: service.StatResponse - (*StatRequest)(nil), // 7: service.StatRequest - (*OnlineStatResponse)(nil), // 8: service.OnlineStatResponse - (*BackendStatsResponse)(nil), // 9: service.BackendStatsResponse - (*SystemStatsResponse)(nil), // 10: service.SystemStatsResponse - (*Vmess)(nil), // 11: service.Vmess - (*Vless)(nil), // 12: service.Vless - (*Trojan)(nil), // 13: service.Trojan - (*Shadowsocks)(nil), // 14: service.Shadowsocks - (*Proxy)(nil), // 15: service.Proxy - (*User)(nil), // 16: service.User - (*Users)(nil), // 17: service.Users + (BackendType)(0), // 0: service.BackendType + (*Empty)(nil), // 1: service.Empty + (*BaseInfoResponse)(nil), // 2: service.BaseInfoResponse + (*Backend)(nil), // 3: service.Backend + (*Log)(nil), // 4: service.Log + (*Stat)(nil), // 5: service.Stat + (*StatResponse)(nil), // 6: service.StatResponse + (*StatRequest)(nil), // 7: service.StatRequest + (*OnlineStatResponse)(nil), // 8: service.OnlineStatResponse + (*StatsOnlineIpListResponse)(nil), // 9: service.StatsOnlineIpListResponse + (*BackendStatsResponse)(nil), // 10: service.BackendStatsResponse + (*SystemStatsResponse)(nil), // 11: service.SystemStatsResponse + (*Vmess)(nil), // 12: service.Vmess + (*Vless)(nil), // 13: service.Vless + (*Trojan)(nil), // 14: service.Trojan + (*Shadowsocks)(nil), // 15: service.Shadowsocks + (*Proxy)(nil), // 16: service.Proxy + (*User)(nil), // 17: service.User + (*Users)(nil), // 18: service.Users + nil, // 19: service.StatsOnlineIpListResponse.IpsEntry } var file_common_service_proto_depIdxs = []int32{ 0, // 0: service.Backend.type:type_name -> service.BackendType - 16, // 1: service.Backend.users:type_name -> service.User + 17, // 1: service.Backend.users:type_name -> service.User 5, // 2: service.StatResponse.stats:type_name -> service.Stat - 11, // 3: service.Proxy.vmess:type_name -> service.Vmess - 12, // 4: service.Proxy.vless:type_name -> service.Vless - 13, // 5: service.Proxy.trojan:type_name -> service.Trojan - 14, // 6: service.Proxy.shadowsocks:type_name -> service.Shadowsocks - 15, // 7: service.User.proxies:type_name -> service.Proxy - 16, // 8: service.Users.users:type_name -> service.User - 3, // 9: service.NodeService.Start:input_type -> service.Backend - 1, // 10: service.NodeService.Stop:input_type -> service.Empty - 1, // 11: service.NodeService.GetBaseInfo:input_type -> service.Empty - 1, // 12: service.NodeService.GetLogs:input_type -> service.Empty - 1, // 13: service.NodeService.GetSystemStats:input_type -> service.Empty - 1, // 14: service.NodeService.GetBackendStats:input_type -> service.Empty - 7, // 15: service.NodeService.GetOutboundsStats:input_type -> service.StatRequest - 7, // 16: service.NodeService.GetOutboundStats:input_type -> service.StatRequest - 7, // 17: service.NodeService.GetInboundsStats:input_type -> service.StatRequest - 7, // 18: service.NodeService.GetInboundStats:input_type -> service.StatRequest - 7, // 19: service.NodeService.GetUsersStats:input_type -> service.StatRequest - 7, // 20: service.NodeService.GetUserStats:input_type -> service.StatRequest - 7, // 21: service.NodeService.GetUserOnlineStats:input_type -> service.StatRequest - 16, // 22: service.NodeService.SyncUser:input_type -> service.User - 17, // 23: service.NodeService.SyncUsers:input_type -> service.Users - 2, // 24: service.NodeService.Start:output_type -> service.BaseInfoResponse - 1, // 25: service.NodeService.Stop:output_type -> service.Empty - 2, // 26: service.NodeService.GetBaseInfo:output_type -> service.BaseInfoResponse - 4, // 27: service.NodeService.GetLogs:output_type -> service.Log - 10, // 28: service.NodeService.GetSystemStats:output_type -> service.SystemStatsResponse - 9, // 29: service.NodeService.GetBackendStats:output_type -> service.BackendStatsResponse - 6, // 30: service.NodeService.GetOutboundsStats:output_type -> service.StatResponse - 6, // 31: service.NodeService.GetOutboundStats:output_type -> service.StatResponse - 6, // 32: service.NodeService.GetInboundsStats:output_type -> service.StatResponse - 6, // 33: service.NodeService.GetInboundStats:output_type -> service.StatResponse - 6, // 34: service.NodeService.GetUsersStats:output_type -> service.StatResponse - 6, // 35: service.NodeService.GetUserStats:output_type -> service.StatResponse - 8, // 36: service.NodeService.GetUserOnlineStats:output_type -> service.OnlineStatResponse - 1, // 37: service.NodeService.SyncUser:output_type -> service.Empty - 1, // 38: service.NodeService.SyncUsers:output_type -> service.Empty - 24, // [24:39] is the sub-list for method output_type - 9, // [9:24] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 19, // 3: service.StatsOnlineIpListResponse.ips:type_name -> service.StatsOnlineIpListResponse.IpsEntry + 12, // 4: service.Proxy.vmess:type_name -> service.Vmess + 13, // 5: service.Proxy.vless:type_name -> service.Vless + 14, // 6: service.Proxy.trojan:type_name -> service.Trojan + 15, // 7: service.Proxy.shadowsocks:type_name -> service.Shadowsocks + 16, // 8: service.User.proxies:type_name -> service.Proxy + 17, // 9: service.Users.users:type_name -> service.User + 3, // 10: service.NodeService.Start:input_type -> service.Backend + 1, // 11: service.NodeService.Stop:input_type -> service.Empty + 1, // 12: service.NodeService.GetBaseInfo:input_type -> service.Empty + 1, // 13: service.NodeService.GetLogs:input_type -> service.Empty + 1, // 14: service.NodeService.GetSystemStats:input_type -> service.Empty + 1, // 15: service.NodeService.GetBackendStats:input_type -> service.Empty + 7, // 16: service.NodeService.GetOutboundsStats:input_type -> service.StatRequest + 7, // 17: service.NodeService.GetOutboundStats:input_type -> service.StatRequest + 7, // 18: service.NodeService.GetInboundsStats:input_type -> service.StatRequest + 7, // 19: service.NodeService.GetInboundStats:input_type -> service.StatRequest + 7, // 20: service.NodeService.GetUsersStats:input_type -> service.StatRequest + 7, // 21: service.NodeService.GetUserStats:input_type -> service.StatRequest + 7, // 22: service.NodeService.GetUserOnlineStats:input_type -> service.StatRequest + 7, // 23: service.NodeService.GetUserOnlineIpListStats:input_type -> service.StatRequest + 17, // 24: service.NodeService.SyncUser:input_type -> service.User + 18, // 25: service.NodeService.SyncUsers:input_type -> service.Users + 2, // 26: service.NodeService.Start:output_type -> service.BaseInfoResponse + 1, // 27: service.NodeService.Stop:output_type -> service.Empty + 2, // 28: service.NodeService.GetBaseInfo:output_type -> service.BaseInfoResponse + 4, // 29: service.NodeService.GetLogs:output_type -> service.Log + 11, // 30: service.NodeService.GetSystemStats:output_type -> service.SystemStatsResponse + 10, // 31: service.NodeService.GetBackendStats:output_type -> service.BackendStatsResponse + 6, // 32: service.NodeService.GetOutboundsStats:output_type -> service.StatResponse + 6, // 33: service.NodeService.GetOutboundStats:output_type -> service.StatResponse + 6, // 34: service.NodeService.GetInboundsStats:output_type -> service.StatResponse + 6, // 35: service.NodeService.GetInboundStats:output_type -> service.StatResponse + 6, // 36: service.NodeService.GetUsersStats:output_type -> service.StatResponse + 6, // 37: service.NodeService.GetUserStats:output_type -> service.StatResponse + 8, // 38: service.NodeService.GetUserOnlineStats:output_type -> service.OnlineStatResponse + 9, // 39: service.NodeService.GetUserOnlineIpListStats:output_type -> service.StatsOnlineIpListResponse + 1, // 40: service.NodeService.SyncUser:output_type -> service.Empty + 1, // 41: service.NodeService.SyncUsers:output_type -> service.Empty + 26, // [26:42] is the sub-list for method output_type + 10, // [10:26] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_common_service_proto_init() } @@ -1353,7 +1427,7 @@ func file_common_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_common_service_proto_rawDesc, NumEnums: 1, - NumMessages: 17, + NumMessages: 19, NumExtensions: 0, NumServices: 1, }, diff --git a/common/service.proto b/common/service.proto index f5e69d2..21e289d 100644 --- a/common/service.proto +++ b/common/service.proto @@ -49,10 +49,15 @@ message StatRequest { } message OnlineStatResponse { - string email = 1; + string name = 1; int64 value = 2; } +message StatsOnlineIpListResponse { + string name = 1; + map ips = 2; +} + message BackendStatsResponse { uint32 num_goroutine = 1; uint32 num_gc = 2; @@ -128,6 +133,7 @@ service NodeService { rpc GetUsersStats (StatRequest) returns (StatResponse) {} rpc GetUserStats (StatRequest) returns (StatResponse) {} rpc GetUserOnlineStats (StatRequest) returns (OnlineStatResponse) {} + rpc GetUserOnlineIpListStats(StatRequest) returns (StatsOnlineIpListResponse) {} rpc SyncUser (stream User) returns (Empty) {} rpc SyncUsers (Users) returns (Empty) {} diff --git a/common/service_grpc.pb.go b/common/service_grpc.pb.go index 3de7df4..5141984 100644 --- a/common/service_grpc.pb.go +++ b/common/service_grpc.pb.go @@ -19,21 +19,22 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - NodeService_Start_FullMethodName = "/service.NodeService/Start" - NodeService_Stop_FullMethodName = "/service.NodeService/Stop" - NodeService_GetBaseInfo_FullMethodName = "/service.NodeService/GetBaseInfo" - NodeService_GetLogs_FullMethodName = "/service.NodeService/GetLogs" - NodeService_GetSystemStats_FullMethodName = "/service.NodeService/GetSystemStats" - NodeService_GetBackendStats_FullMethodName = "/service.NodeService/GetBackendStats" - NodeService_GetOutboundsStats_FullMethodName = "/service.NodeService/GetOutboundsStats" - NodeService_GetOutboundStats_FullMethodName = "/service.NodeService/GetOutboundStats" - NodeService_GetInboundsStats_FullMethodName = "/service.NodeService/GetInboundsStats" - NodeService_GetInboundStats_FullMethodName = "/service.NodeService/GetInboundStats" - NodeService_GetUsersStats_FullMethodName = "/service.NodeService/GetUsersStats" - NodeService_GetUserStats_FullMethodName = "/service.NodeService/GetUserStats" - NodeService_GetUserOnlineStats_FullMethodName = "/service.NodeService/GetUserOnlineStats" - NodeService_SyncUser_FullMethodName = "/service.NodeService/SyncUser" - NodeService_SyncUsers_FullMethodName = "/service.NodeService/SyncUsers" + NodeService_Start_FullMethodName = "/service.NodeService/Start" + NodeService_Stop_FullMethodName = "/service.NodeService/Stop" + NodeService_GetBaseInfo_FullMethodName = "/service.NodeService/GetBaseInfo" + NodeService_GetLogs_FullMethodName = "/service.NodeService/GetLogs" + NodeService_GetSystemStats_FullMethodName = "/service.NodeService/GetSystemStats" + NodeService_GetBackendStats_FullMethodName = "/service.NodeService/GetBackendStats" + NodeService_GetOutboundsStats_FullMethodName = "/service.NodeService/GetOutboundsStats" + NodeService_GetOutboundStats_FullMethodName = "/service.NodeService/GetOutboundStats" + NodeService_GetInboundsStats_FullMethodName = "/service.NodeService/GetInboundsStats" + NodeService_GetInboundStats_FullMethodName = "/service.NodeService/GetInboundStats" + NodeService_GetUsersStats_FullMethodName = "/service.NodeService/GetUsersStats" + NodeService_GetUserStats_FullMethodName = "/service.NodeService/GetUserStats" + NodeService_GetUserOnlineStats_FullMethodName = "/service.NodeService/GetUserOnlineStats" + NodeService_GetUserOnlineIpListStats_FullMethodName = "/service.NodeService/GetUserOnlineIpListStats" + NodeService_SyncUser_FullMethodName = "/service.NodeService/SyncUser" + NodeService_SyncUsers_FullMethodName = "/service.NodeService/SyncUsers" ) // NodeServiceClient is the client API for NodeService service. @@ -55,6 +56,7 @@ type NodeServiceClient interface { GetUsersStats(ctx context.Context, in *StatRequest, opts ...grpc.CallOption) (*StatResponse, error) GetUserStats(ctx context.Context, in *StatRequest, opts ...grpc.CallOption) (*StatResponse, error) GetUserOnlineStats(ctx context.Context, in *StatRequest, opts ...grpc.CallOption) (*OnlineStatResponse, error) + GetUserOnlineIpListStats(ctx context.Context, in *StatRequest, opts ...grpc.CallOption) (*StatsOnlineIpListResponse, error) SyncUser(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[User, Empty], error) SyncUsers(ctx context.Context, in *Users, opts ...grpc.CallOption) (*Empty, error) } @@ -206,6 +208,16 @@ func (c *nodeServiceClient) GetUserOnlineStats(ctx context.Context, in *StatRequ return out, nil } +func (c *nodeServiceClient) GetUserOnlineIpListStats(ctx context.Context, in *StatRequest, opts ...grpc.CallOption) (*StatsOnlineIpListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(StatsOnlineIpListResponse) + err := c.cc.Invoke(ctx, NodeService_GetUserOnlineIpListStats_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *nodeServiceClient) SyncUser(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[User, Empty], error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) stream, err := c.cc.NewStream(ctx, &NodeService_ServiceDesc.Streams[1], NodeService_SyncUser_FullMethodName, cOpts...) @@ -248,6 +260,7 @@ type NodeServiceServer interface { GetUsersStats(context.Context, *StatRequest) (*StatResponse, error) GetUserStats(context.Context, *StatRequest) (*StatResponse, error) GetUserOnlineStats(context.Context, *StatRequest) (*OnlineStatResponse, error) + GetUserOnlineIpListStats(context.Context, *StatRequest) (*StatsOnlineIpListResponse, error) SyncUser(grpc.ClientStreamingServer[User, Empty]) error SyncUsers(context.Context, *Users) (*Empty, error) mustEmbedUnimplementedNodeServiceServer() @@ -299,6 +312,9 @@ func (UnimplementedNodeServiceServer) GetUserStats(context.Context, *StatRequest func (UnimplementedNodeServiceServer) GetUserOnlineStats(context.Context, *StatRequest) (*OnlineStatResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetUserOnlineStats not implemented") } +func (UnimplementedNodeServiceServer) GetUserOnlineIpListStats(context.Context, *StatRequest) (*StatsOnlineIpListResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetUserOnlineIpListStats not implemented") +} func (UnimplementedNodeServiceServer) SyncUser(grpc.ClientStreamingServer[User, Empty]) error { return status.Errorf(codes.Unimplemented, "method SyncUser not implemented") } @@ -553,6 +569,24 @@ func _NodeService_GetUserOnlineStats_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _NodeService_GetUserOnlineIpListStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StatRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NodeServiceServer).GetUserOnlineIpListStats(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: NodeService_GetUserOnlineIpListStats_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NodeServiceServer).GetUserOnlineIpListStats(ctx, req.(*StatRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _NodeService_SyncUser_Handler(srv interface{}, stream grpc.ServerStream) error { return srv.(NodeServiceServer).SyncUser(&grpc.GenericServerStream[User, Empty]{ServerStream: stream}) } @@ -633,6 +667,10 @@ var NodeService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetUserOnlineStats", Handler: _NodeService_GetUserOnlineStats_Handler, }, + { + MethodName: "GetUserOnlineIpListStats", + Handler: _NodeService_GetUserOnlineIpListStats_Handler, + }, { MethodName: "SyncUsers", Handler: _NodeService_SyncUsers_Handler, diff --git a/controller/rest/service.go b/controller/rest/service.go index 105a63e..4e3c509 100644 --- a/controller/rest/service.go +++ b/controller/rest/service.go @@ -47,6 +47,7 @@ func (s *Service) setRouter() { statsGroup.Get("/users", s.GetUsersStats) statsGroup.Get("/user", s.GetUserStats) statsGroup.Get("/user/online", s.GetUserOnlineStat) + statsGroup.Get("/user/online_ip", s.GetUserOnlineIpListStats) statsGroup.Get("/backend", s.GetBackendStats) }) private.Put("/user/sync", s.SyncUser) diff --git a/controller/rest/stats.go b/controller/rest/stats.go index bb913aa..0c0785f 100644 --- a/controller/rest/stats.go +++ b/controller/rest/stats.go @@ -129,7 +129,29 @@ func (s *Service) GetUserOnlineStat(w http.ResponseWriter, r *http.Request) { return } - stats, err := s.GetBackend().GetStatOnline(r.Context(), request.GetName()) + stats, err := s.GetBackend().GetUserOnlineStats(r.Context(), request.GetName()) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + common.SendProtoResponse(w, stats) +} + +func (s *Service) GetUserOnlineIpListStats(w http.ResponseWriter, r *http.Request) { + var request common.StatRequest + if err := common.ReadProtoBody(r.Body, &request); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + if request.GetName() == "" { + http.Error(w, "name is required", http.StatusBadRequest) + return + } + + stats, err := s.GetBackend().GetUserOnlineIpListStats(r.Context(), request.GetName()) + if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return diff --git a/controller/rpc/stats.go b/controller/rpc/stats.go index cc67c6f..a754ed4 100644 --- a/controller/rpc/stats.go +++ b/controller/rpc/stats.go @@ -44,7 +44,14 @@ func (s *Service) GetUserOnlineStats(ctx context.Context, request *common.StatRe if request.GetName() == "" { return nil, errors.New("name is required") } - return s.GetBackend().GetStatOnline(ctx, request.GetName()) + return s.GetBackend().GetUserOnlineStats(ctx, request.GetName()) +} + +func (s *Service) GetUserOnlineIpListStats(ctx context.Context, request *common.StatRequest) (*common.StatsOnlineIpListResponse, error) { + if request.GetName() == "" { + return nil, errors.New("name is required") + } + return s.GetBackend().GetUserOnlineIpListStats(ctx, request.GetName()) } func (s *Service) GetBackendStats(ctx context.Context, _ *common.Empty) (*common.BackendStatsResponse, error) { diff --git a/go.mod b/go.mod index 52cba30..16ebc68 100644 --- a/go.mod +++ b/go.mod @@ -8,14 +8,14 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/joho/godotenv v1.5.1 github.com/shirou/gopsutil v3.21.11+incompatible - github.com/xtls/xray-core v1.8.25-0.20241130041635-98a72b6fb49b - google.golang.org/grpc v1.70.0 + github.com/xtls/xray-core v1.250306.0 + google.golang.org/grpc v1.71.0 google.golang.org/protobuf v1.36.5 ) require ( github.com/andybalholm/brotli v1.1.0 // indirect - github.com/cloudflare/circl v1.4.0 // indirect + github.com/cloudflare/circl v1.6.0 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect @@ -26,8 +26,8 @@ require ( github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/onsi/ginkgo/v2 v2.19.0 // indirect github.com/pires/go-proxyproto v0.8.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/quic-go v0.46.0 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.50.0 // indirect github.com/refraction-networking/utls v1.6.7 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/sagernet/sing v0.5.1 // indirect @@ -40,19 +40,19 @@ require ( github.com/vishvananda/netns v0.0.4 // indirect github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.uber.org/mock v0.4.0 // indirect + go.uber.org/mock v0.5.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect - golang.org/x/crypto v0.35.0 // indirect + golang.org/x/crypto v0.36.0 // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect - golang.org/x/mod v0.18.0 // indirect - golang.org/x/net v0.36.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.22.0 // indirect - golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.22.0 // indirect + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.26.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect - gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 // indirect - lukechampine.com/blake3 v1.3.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect + gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 // indirect + lukechampine.com/blake3 v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 660636b..c512e75 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY= github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= +github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= +github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -51,6 +53,7 @@ github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g= github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -73,6 +76,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= @@ -88,8 +92,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y= github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI= +github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo= +github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= @@ -126,24 +134,33 @@ github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhig github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE= github.com/xtls/xray-core v1.8.25-0.20241130041635-98a72b6fb49b h1:h8DhM+nmPMo4yKqNnxQ7TZ3e8YiESKm9h0gE45UiNmA= github.com/xtls/xray-core v1.8.25-0.20241130041635-98a72b6fb49b/go.mod h1:BCeSy6P4xz8vSk46ziVkg0iby82W2Mmqvz2ub5kfYrc= +github.com/xtls/xray-core v1.250306.0 h1:XZyZvSgcpAoVEGnFnxNdoHbSF7Kp77A/0TPk4lhv6rM= +github.com/xtls/xray-core v1.250306.0/go.mod h1:clXnUOnX6CKWBGgJY4ePYhb/EtTdSrUC7vPfT6m5p4c= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU= go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= @@ -153,6 +170,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= @@ -164,6 +183,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -174,6 +194,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -182,6 +204,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -195,12 +218,18 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -212,6 +241,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -227,6 +257,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o= google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -234,6 +266,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ= google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw= +google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -249,7 +283,11 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE= gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk= +gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h1:P+U/06iIKPQ3DLcg+zBfSCia1luZ2msPZrJ8jYDFPs0= +gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w= +lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0=