From 252f966bf269b7b84db7bc3f4d2e47a21847b532 Mon Sep 17 00:00:00 2001 From: enfein <83481737+enfein@users.noreply.github.com> Date: Sun, 6 Oct 2024 01:03:44 +0000 Subject: [PATCH] First client API implementation --- Makefile | 6 +- apis/client/interface.go | 68 +++- apis/client/mieru.go | 192 +++++++++++ apis/constant/socks5.go | 35 ++ apis/model/addr.go | 124 +++++++ apis/model/addr_test.go | 111 ++++++ pkg/appctl/{appctlpb => appctlgrpc}/rpc.pb.go | 28 +- .../{appctlpb => appctlgrpc}/rpc_grpc.pb.go | 325 +++++++++--------- pkg/appctl/appctlpb/base.pb.go | 8 +- pkg/appctl/appctlpb/clientcfg.pb.go | 6 +- pkg/appctl/appctlpb/misc.pb.go | 8 +- pkg/appctl/appctlpb/servercfg.pb.go | 6 +- pkg/appctl/client.go | 110 +++--- pkg/appctl/proto/base.proto | 2 +- pkg/appctl/proto/clientcfg.proto | 2 +- pkg/appctl/proto/misc.proto | 2 +- pkg/appctl/proto/rpc.proto | 2 +- pkg/appctl/proto/servercfg.proto | 2 +- pkg/appctl/server.go | 13 +- pkg/cli/client.go | 20 +- pkg/cli/server.go | 5 +- pkg/metrics/export.go | 14 +- pkg/metrics/export_test.go | 18 + pkg/metrics/metricspb/metrics.pb.go | 7 +- pkg/metrics/proto/metrics.proto | 2 +- pkg/socks5/auth.go | 17 +- pkg/socks5/client.go | 29 +- pkg/socks5/client_test.go | 3 +- pkg/socks5/http2socks.go | 3 +- pkg/socks5/request.go | 222 +++--------- pkg/socks5/request_test.go | 3 +- pkg/socks5/socks5.go | 8 +- pkg/socks5/socks5_test.go | 9 +- test/cmd/sockshttpclient/sockshttpclient.go | 5 +- test/cmd/socksudpclient/socksudpclient.go | 3 +- 35 files changed, 929 insertions(+), 489 deletions(-) create mode 100644 apis/constant/socks5.go create mode 100644 apis/model/addr.go create mode 100644 apis/model/addr_test.go rename pkg/appctl/{appctlpb => appctlgrpc}/rpc.pb.go (94%) rename pkg/appctl/{appctlpb => appctlgrpc}/rpc_grpc.pb.go (78%) diff --git a/Makefile b/Makefile index 04890782..94d7427c 100644 --- a/Makefile +++ b/Makefile @@ -413,8 +413,8 @@ protobuf: fi PATH=${PATH}:"${ROOT}/tools/build" ${ROOT}/tools/build/protoc -I="${ROOT}/pkg/appctl/proto" \ - --go_out="${ROOT}/pkg/appctl" --go_opt=module="github.com/enfein/mieru/pkg/appctl" \ - --go-grpc_out="${ROOT}/pkg/appctl" --go-grpc_opt=module="github.com/enfein/mieru/pkg/appctl" \ + --go_out="${ROOT}/pkg/appctl" --go_opt=module="github.com/enfein/mieru/v3/pkg/appctl" \ + --go-grpc_out="${ROOT}/pkg/appctl" --go-grpc_opt=module="github.com/enfein/mieru/v3/pkg/appctl" \ --proto_path="${ROOT}/pkg" \ "${ROOT}/pkg/appctl/proto/base.proto" \ "${ROOT}/pkg/appctl/proto/clientcfg.proto" \ @@ -423,7 +423,7 @@ protobuf: "${ROOT}/pkg/appctl/proto/servercfg.proto" PATH=${PATH}:"${ROOT}/tools/build" ${ROOT}/tools/build/protoc -I="${ROOT}/pkg/metrics/proto" \ - --go_out="${ROOT}/pkg/metrics" --go_opt=module="github.com/enfein/mieru/pkg/metrics" \ + --go_out="${ROOT}/pkg/metrics" --go_opt=module="github.com/enfein/mieru/v3/pkg/metrics" \ --proto_path="${ROOT}/pkg" \ "${ROOT}/pkg/metrics/proto/metrics.proto" diff --git a/apis/client/interface.go b/apis/client/interface.go index 6b14c7fa..07b9128e 100644 --- a/apis/client/interface.go +++ b/apis/client/interface.go @@ -17,26 +17,74 @@ package client import ( "context" + "errors" "net" + + "github.com/enfein/mieru/v3/apis/model" + "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" +) + +var ( + ErrNoClientConfig = errors.New("no client config") + ErrInvalidConfigConfig = errors.New("invalid client config") + ErrClientIsNotRunning = errors.New("client is not running") ) // Client contains methods supported by a mieru client. type Client interface { - ClientConfiguration - ClientLifecycle - - DialContext(ctx context.Context) (net.Conn, error) + ClientConfigurationService + ClientLifecycleService + ClientNetworkService } -// ClientConfiguration contains methods to manage proxy client configuration. -type ClientConfiguration interface { - Load() error - Store() error +// ClientConfigurationService contains methods to manage proxy client configuration. +type ClientConfigurationService interface { + // Load returns the client config. + // It returns ErrNoClientConfig if client config is never stored. + Load() (*ClientConfig, error) + + // Store saves the client config. + // It returns wrapped ErrInvalidConfigConfig if client config is invalid. + Store(*ClientConfig) error } -// ClientLifecycle contains methods to manage proxy client lifecycle. -type ClientLifecycle interface { +// ClientLifecycleService contains methods to manage proxy client lifecycle. +type ClientLifecycleService interface { + // Start activates the client with the stored configuration. + // Calling Start function more than once has undefined behavior. Start() error + + // Stop deactivates the client. + // Established network connections are NOT terminated. + // After stop, the client can't be reused. Stop() error + + // IsRunning returns true if the client has been started + // and has not been stopped. IsRunning() bool } + +// ClientNetworkService contains methods to establish proxy connections. +type ClientNetworkService interface { + // DialContext returns a new mieru connection to reach proxy server. + // It returns an error if the client has not been started, + // or has been stopped. + DialContext(context.Context) (net.Conn, error) + + // HandshakeWithConnect completes the socks5 CONNECT request with proxy server. + // After this, the mieru connection is able to send and receive user payload. + // The mieru connection is NOT terminated when an error is returned. + HandshakeWithConnect(context.Context, net.Conn, model.AddrSpec) error +} + +// ClientConfig stores proxy client configuration. +type ClientConfig struct { + Profile *appctlpb.ClientProfile +} + +// NewClient returns a blank mieru client. +func NewClient() Client { + mc := &mieruClient{} + mc.initOnce() + return mc +} diff --git a/apis/client/mieru.go b/apis/client/mieru.go index 0dd01039..e21fb20c 100644 --- a/apis/client/mieru.go +++ b/apis/client/mieru.go @@ -16,16 +16,39 @@ package client import ( + "bytes" + "context" + "encoding/hex" + "fmt" + "io" + "net" "sync" + "time" + "github.com/enfein/mieru/v3/apis/constant" + "github.com/enfein/mieru/v3/apis/model" + "github.com/enfein/mieru/v3/pkg/appctl" + "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" + "github.com/enfein/mieru/v3/pkg/cipher" "github.com/enfein/mieru/v3/pkg/log" + "github.com/enfein/mieru/v3/pkg/protocol" + "github.com/enfein/mieru/v3/pkg/stderror" + "github.com/enfein/mieru/v3/pkg/util" ) // mieruClient is the official implementation of mieru client APIs. type mieruClient struct { initTask sync.Once + mu sync.RWMutex + + config *ClientConfig + mux *protocol.Mux + + running bool } +var _ Client = &mieruClient{} + // initOnce should be called when constructing the mieru client. func (mc *mieruClient) initOnce() { mc.initTask.Do(func() { @@ -33,3 +56,172 @@ func (mc *mieruClient) initOnce() { log.SetFormatter(&log.NilFormatter{}) }) } + +func (mc *mieruClient) Load() (*ClientConfig, error) { + mc.mu.Lock() + defer mc.mu.Unlock() + if mc.config == nil { + return nil, ErrNoClientConfig + } + return mc.config, nil +} + +func (mc *mieruClient) Store(config *ClientConfig) error { + mc.mu.Lock() + defer mc.mu.Unlock() + if config == nil { + return fmt.Errorf("%w: client config is nil", ErrInvalidConfigConfig) + } + if config.Profile == nil { + return fmt.Errorf("%w: client config profile is nil", ErrInvalidConfigConfig) + } + if err := appctl.ValidateClientConfigSingleProfile(config.Profile); err != nil { + return fmt.Errorf("%w: %s", ErrInvalidConfigConfig, err.Error()) + } + mc.config = config + return nil +} + +func (mc *mieruClient) Start() error { + mc.mu.Lock() + defer mc.mu.Unlock() + if mc.config == nil { + return ErrNoClientConfig + } + + var err error + mc.mux = protocol.NewMux(true) + activeProfile := mc.config.Profile + + // Set user name and password. + user := activeProfile.GetUser() + var hashedPassword []byte + if user.GetHashedPassword() != "" { + hashedPassword, err = hex.DecodeString(user.GetHashedPassword()) + if err != nil { + return fmt.Errorf(stderror.DecodeHashedPasswordFailedErr, err) + } + } else { + hashedPassword = cipher.HashPassword([]byte(user.GetPassword()), []byte(user.GetName())) + } + mc.mux = mc.mux.SetClientUserNamePassword(user.GetName(), hashedPassword) + + // Set multiplex factor. + multiplexFactor := 1 + switch activeProfile.GetMultiplexing().GetLevel() { + case appctlpb.MultiplexingLevel_MULTIPLEXING_OFF: + multiplexFactor = 0 + case appctlpb.MultiplexingLevel_MULTIPLEXING_LOW: + multiplexFactor = 1 + case appctlpb.MultiplexingLevel_MULTIPLEXING_MIDDLE: + multiplexFactor = 2 + case appctlpb.MultiplexingLevel_MULTIPLEXING_HIGH: + multiplexFactor = 3 + } + mc.mux = mc.mux.SetClientMultiplexFactor(multiplexFactor) + + // Set endpoints. + mtu := util.DefaultMTU + if activeProfile.GetMtu() != 0 { + mtu = int(activeProfile.GetMtu()) + } + endpoints := make([]protocol.UnderlayProperties, 0) + resolver := &util.DNSResolver{} + for _, serverInfo := range activeProfile.GetServers() { + var proxyHost string + var proxyIP net.IP + if serverInfo.GetDomainName() != "" { + proxyHost = serverInfo.GetDomainName() + proxyIP, err = resolver.LookupIP(context.Background(), proxyHost) + if err != nil { + return fmt.Errorf(stderror.LookupIPFailedErr, err) + } + } else { + proxyHost = serverInfo.GetIpAddress() + proxyIP = net.ParseIP(proxyHost) + if proxyIP == nil { + return fmt.Errorf(stderror.ParseIPFailed) + } + } + ipVersion := util.GetIPVersion(proxyIP.String()) + portBindings, err := appctl.FlatPortBindings(serverInfo.GetPortBindings()) + if err != nil { + return fmt.Errorf(stderror.InvalidPortBindingsErr, err) + } + for _, bindingInfo := range portBindings { + proxyPort := bindingInfo.GetPort() + switch bindingInfo.GetProtocol() { + case appctlpb.TransportProtocol_TCP: + endpoint := protocol.NewUnderlayProperties(mtu, ipVersion, util.TCPTransport, nil, &net.TCPAddr{IP: proxyIP, Port: int(proxyPort)}) + endpoints = append(endpoints, endpoint) + case appctlpb.TransportProtocol_UDP: + endpoint := protocol.NewUnderlayProperties(mtu, ipVersion, util.UDPTransport, nil, &net.UDPAddr{IP: proxyIP, Port: int(proxyPort)}) + endpoints = append(endpoints, endpoint) + default: + return fmt.Errorf(stderror.InvalidTransportProtocol) + } + } + } + mc.mux.SetEndpoints(endpoints) + + mc.running = true + return nil +} + +func (mc *mieruClient) Stop() error { + mc.mu.Lock() + defer mc.mu.Unlock() + + mc.running = false + if mc.mux != nil { + mc.mux.Close() + } + return nil +} + +func (mc *mieruClient) IsRunning() bool { + mc.mu.RLock() + defer mc.mu.RUnlock() + return mc.running +} + +func (mc *mieruClient) DialContext(ctx context.Context) (net.Conn, error) { + mc.mu.RLock() + defer mc.mu.RUnlock() + if !mc.running { + return nil, ErrClientIsNotRunning + } + return mc.mux.DialContext(ctx) +} + +func (mc *mieruClient) HandshakeWithConnect(ctx context.Context, conn net.Conn, addr model.AddrSpec) error { + mc.mu.RLock() + defer mc.mu.RUnlock() + + var req bytes.Buffer + req.Write([]byte{constant.Socks5Version, constant.Socks5ConnectCmd, 0}) + if err := addr.WriteToSocks5(&req); err != nil { + return err + } + if _, err := conn.Write(req.Bytes()); err != nil { + return fmt.Errorf("failed to write socks5 connection request to the server: %w", err) + } + + util.SetReadTimeout(conn, 10*time.Second) + defer func() { + util.SetReadTimeout(conn, 0) + }() + + resp := make([]byte, 3) + if _, err := io.ReadFull(conn, resp); err != nil { + return fmt.Errorf("failed to read socks5 connection response from the server: %w", err) + } + var respAddr model.AddrSpec + if err := respAddr.ReadFromSocks5(conn); err != nil { + return fmt.Errorf("failed to read socks5 connection address response from the server: %w", err) + } + if resp[1] != 0 { + return fmt.Errorf("server returned socks5 error code %d", resp[1]) + } + return nil +} diff --git a/apis/constant/socks5.go b/apis/constant/socks5.go new file mode 100644 index 00000000..185ca474 --- /dev/null +++ b/apis/constant/socks5.go @@ -0,0 +1,35 @@ +// Copyright (C) 2024 mieru authors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package constant + +const ( + // socks5 version number. + Socks5Version byte = 5 +) + +// socks5 command types. +const ( + Socks5ConnectCmd byte = 1 + Socks5BindCmd byte = 2 + Socks5UDPAssociateCmd byte = 3 +) + +// socks5 address types. +const ( + Socks5IPv4Address byte = 1 + Socks5FQDNAddress byte = 3 + Socks5IPv6Address byte = 4 +) diff --git a/apis/model/addr.go b/apis/model/addr.go new file mode 100644 index 00000000..ffe9c878 --- /dev/null +++ b/apis/model/addr.go @@ -0,0 +1,124 @@ +// Copyright (C) 2024 mieru authors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package model + +import ( + "bytes" + "errors" + "io" + "net" + "strconv" + + "github.com/enfein/mieru/v3/apis/constant" +) + +var ( + ErrUnrecognizedAddrType = errors.New("unrecognized address type") +) + +// AddrSpec is used to specify an IPv4, IPv6, or a FQDN address +// with a port number. +type AddrSpec struct { + FQDN string + IP net.IP + Port int +} + +func (a AddrSpec) String() string { + return a.Address() +} + +// Address returns a string suitable to dial. +// Prefer returning IP-based address, fallback to FQDN. +func (a AddrSpec) Address() string { + if len(a.IP) != 0 { + return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port)) + } + return net.JoinHostPort(a.FQDN, strconv.Itoa(a.Port)) +} + +// ReadFromSocks5 reads the AddrSpec from a socks5 request. +func (a *AddrSpec) ReadFromSocks5(r io.Reader) error { + // Get the address type. + addrType := []byte{0} + if _, err := io.ReadFull(r, addrType); err != nil { + return err + } + + // Handle on a per type basis. + switch addrType[0] { + case constant.Socks5IPv4Address: + addr := make([]byte, 4) + if _, err := io.ReadFull(r, addr); err != nil { + return err + } + a.IP = net.IP(addr) + case constant.Socks5IPv6Address: + addr := make([]byte, 16) + if _, err := io.ReadFull(r, addr); err != nil { + return err + } + a.IP = net.IP(addr) + case constant.Socks5FQDNAddress: + addrLen := []byte{0} + if _, err := io.ReadFull(r, addrLen); err != nil { + return err + } + fqdn := make([]byte, int(addrLen[0])) + if _, err := io.ReadFull(r, fqdn); err != nil { + return err + } + a.FQDN = string(fqdn) + default: + return ErrUnrecognizedAddrType + } + + // Read the port number. + port := []byte{0, 0} + if _, err := io.ReadFull(r, port); err != nil { + return err + } + a.Port = (int(port[0]) << 8) | int(port[1]) + + return nil +} + +// WriteToSocks5 writes a socks5 request from the AddrSpec. +func (a AddrSpec) WriteToSocks5(w io.Writer) error { + var addrPort uint16 + var b bytes.Buffer + + switch { + case a.IP.To4() != nil: + b.WriteByte(constant.Socks5IPv4Address) + b.Write(a.IP.To4()) + case a.IP.To16() != nil: + b.WriteByte(constant.Socks5IPv6Address) + b.Write(a.IP.To16()) + case a.FQDN != "": + b.WriteByte(constant.Socks5FQDNAddress) + b.WriteByte(byte(len(a.FQDN))) + b.Write([]byte(a.FQDN)) + default: + return ErrUnrecognizedAddrType + } + addrPort = uint16(a.Port) + b.WriteByte(byte(addrPort >> 8)) + b.WriteByte(byte(addrPort & 0xff)) + + _, err := w.Write(b.Bytes()) + return err +} diff --git a/apis/model/addr_test.go b/apis/model/addr_test.go new file mode 100644 index 00000000..71f16776 --- /dev/null +++ b/apis/model/addr_test.go @@ -0,0 +1,111 @@ +// Copyright (C) 2024 mieru authors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +package model + +import ( + "bytes" + "net" + "testing" + + "github.com/enfein/mieru/v3/apis/constant" +) + +func TestAddrSpecAddress(t *testing.T) { + testCases := []struct { + input *AddrSpec + wantAddr string + }{ + { + input: &AddrSpec{IP: net.IP{127, 0, 0, 1}, Port: 8080}, + wantAddr: "127.0.0.1:8080", + }, + { + input: &AddrSpec{IP: net.ParseIP("::1"), Port: 8080}, + wantAddr: "[::1]:8080", + }, + { + input: &AddrSpec{FQDN: "localhost", Port: 8080}, + wantAddr: "localhost:8080", + }, + } + + for _, tc := range testCases { + addr := tc.input.Address() + if addr != tc.wantAddr { + t.Errorf("got %v, want %v", addr, tc.wantAddr) + } + addr = tc.input.String() + if addr != tc.wantAddr { + t.Errorf("got %v, want %v", addr, tc.wantAddr) + } + } +} + +func TestAddrSpecReadWrite(t *testing.T) { + testCases := []struct { + input []byte + addr *AddrSpec + }{ + { + input: []byte{constant.Socks5IPv4Address, 127, 0, 0, 1, 0, 80}, + addr: &AddrSpec{ + IP: net.IP{127, 0, 0, 1}, + Port: 80, + }, + }, + { + input: []byte{constant.Socks5IPv6Address, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 80}, + addr: &AddrSpec{ + IP: net.ParseIP("::1"), + Port: 80, + }, + }, + { + input: []byte{constant.Socks5FQDNAddress, 9, 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', 0, 80}, + addr: &AddrSpec{ + FQDN: "localhost", + Port: 80, + }, + }, + } + + for _, tc := range testCases { + addr := &AddrSpec{} + err := addr.ReadFromSocks5(bytes.NewBuffer(tc.input)) + if err != nil { + t.Fatalf("ReadFromSocks5() failed: %v", err) + } + if addr.FQDN != tc.addr.FQDN { + t.Errorf("got %v, want %v", addr.FQDN, tc.addr.FQDN) + } + if !addr.IP.Equal(tc.addr.IP) { + t.Errorf("got %v, want %v", addr.IP, tc.addr.IP) + } + if addr.Port != tc.addr.Port { + t.Errorf("got %v, want %v", addr.Port, tc.addr.Port) + } + + var output bytes.Buffer + err = addr.WriteToSocks5(&output) + if err != nil { + t.Fatalf("WriteToSocks5() failed: %v", err) + } + outputBytes := output.Bytes() + if !bytes.Equal(outputBytes, tc.input) { + t.Errorf("got %v, want %v", outputBytes, tc.input) + } + } +} diff --git a/pkg/appctl/appctlpb/rpc.pb.go b/pkg/appctl/appctlgrpc/rpc.pb.go similarity index 94% rename from pkg/appctl/appctlpb/rpc.pb.go rename to pkg/appctl/appctlgrpc/rpc.pb.go index dfeefe4b..64b9c674 100644 --- a/pkg/appctl/appctlpb/rpc.pb.go +++ b/pkg/appctl/appctlgrpc/rpc.pb.go @@ -19,9 +19,10 @@ // protoc v4.22.3 // source: rpc.proto -package appctlpb +package appctlgrpc import ( + appctlpb "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -118,21 +119,21 @@ var file_rpc_proto_rawDesc = []byte{ 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6e, 0x66, 0x69, 0x67, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, - 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, + 0x70, 0x63, 0x74, 0x6c, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_rpc_proto_goTypes = []interface{}{ - (*Empty)(nil), // 0: appctl.Empty - (*ProfileSavePath)(nil), // 1: appctl.ProfileSavePath - (*ServerConfig)(nil), // 2: appctl.ServerConfig - (*AppStatusMsg)(nil), // 3: appctl.AppStatusMsg - (*Metrics)(nil), // 4: appctl.Metrics - (*SessionInfo)(nil), // 5: appctl.SessionInfo - (*ThreadDump)(nil), // 6: appctl.ThreadDump - (*MemoryStatistics)(nil), // 7: appctl.MemoryStatistics + (*appctlpb.Empty)(nil), // 0: appctl.Empty + (*appctlpb.ProfileSavePath)(nil), // 1: appctl.ProfileSavePath + (*appctlpb.ServerConfig)(nil), // 2: appctl.ServerConfig + (*appctlpb.AppStatusMsg)(nil), // 3: appctl.AppStatusMsg + (*appctlpb.Metrics)(nil), // 4: appctl.Metrics + (*appctlpb.SessionInfo)(nil), // 5: appctl.SessionInfo + (*appctlpb.ThreadDump)(nil), // 6: appctl.ThreadDump + (*appctlpb.MemoryStatistics)(nil), // 7: appctl.MemoryStatistics } var file_rpc_proto_depIdxs = []int32{ 0, // 0: appctl.ClientLifecycleService.GetStatus:input_type -> appctl.Empty @@ -193,9 +194,6 @@ func file_rpc_proto_init() { if File_rpc_proto != nil { return } - file_base_proto_init() - file_misc_proto_init() - file_servercfg_proto_init() type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/pkg/appctl/appctlpb/rpc_grpc.pb.go b/pkg/appctl/appctlgrpc/rpc_grpc.pb.go similarity index 78% rename from pkg/appctl/appctlpb/rpc_grpc.pb.go rename to pkg/appctl/appctlgrpc/rpc_grpc.pb.go index c311148f..b5bed52a 100644 --- a/pkg/appctl/appctlpb/rpc_grpc.pb.go +++ b/pkg/appctl/appctlgrpc/rpc_grpc.pb.go @@ -19,10 +19,11 @@ // - protoc v4.22.3 // source: rpc.proto -package appctlpb +package appctlgrpc import ( context "context" + appctlpb "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -50,23 +51,23 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ClientLifecycleServiceClient interface { // Fetch client application status. - GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*AppStatusMsg, error) + GetStatus(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.AppStatusMsg, error) // Quit client daemon. - Exit(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + Exit(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Get client metrics. - GetMetrics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Metrics, error) + GetMetrics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Metrics, error) // Get client session information. - GetSessionInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*SessionInfo, error) + GetSessionInfo(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.SessionInfo, error) // Generate a thread dump of client daemon. - GetThreadDump(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ThreadDump, error) + GetThreadDump(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.ThreadDump, error) // Start CPU profiling. - StartCPUProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) + StartCPUProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Stop CPU profiling. - StopCPUProfile(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + StopCPUProfile(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Generate a heap profile. - GetHeapProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) + GetHeapProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Get memory statistics of client daemon. - GetMemoryStatistics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*MemoryStatistics, error) + GetMemoryStatistics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.MemoryStatistics, error) } type clientLifecycleServiceClient struct { @@ -77,8 +78,8 @@ func NewClientLifecycleServiceClient(cc grpc.ClientConnInterface) ClientLifecycl return &clientLifecycleServiceClient{cc} } -func (c *clientLifecycleServiceClient) GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*AppStatusMsg, error) { - out := new(AppStatusMsg) +func (c *clientLifecycleServiceClient) GetStatus(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.AppStatusMsg, error) { + out := new(appctlpb.AppStatusMsg) err := c.cc.Invoke(ctx, ClientLifecycleService_GetStatus_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -86,8 +87,8 @@ func (c *clientLifecycleServiceClient) GetStatus(ctx context.Context, in *Empty, return out, nil } -func (c *clientLifecycleServiceClient) Exit(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *clientLifecycleServiceClient) Exit(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ClientLifecycleService_Exit_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -95,8 +96,8 @@ func (c *clientLifecycleServiceClient) Exit(ctx context.Context, in *Empty, opts return out, nil } -func (c *clientLifecycleServiceClient) GetMetrics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Metrics, error) { - out := new(Metrics) +func (c *clientLifecycleServiceClient) GetMetrics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Metrics, error) { + out := new(appctlpb.Metrics) err := c.cc.Invoke(ctx, ClientLifecycleService_GetMetrics_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -104,8 +105,8 @@ func (c *clientLifecycleServiceClient) GetMetrics(ctx context.Context, in *Empty return out, nil } -func (c *clientLifecycleServiceClient) GetSessionInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*SessionInfo, error) { - out := new(SessionInfo) +func (c *clientLifecycleServiceClient) GetSessionInfo(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.SessionInfo, error) { + out := new(appctlpb.SessionInfo) err := c.cc.Invoke(ctx, ClientLifecycleService_GetSessionInfo_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -113,8 +114,8 @@ func (c *clientLifecycleServiceClient) GetSessionInfo(ctx context.Context, in *E return out, nil } -func (c *clientLifecycleServiceClient) GetThreadDump(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ThreadDump, error) { - out := new(ThreadDump) +func (c *clientLifecycleServiceClient) GetThreadDump(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.ThreadDump, error) { + out := new(appctlpb.ThreadDump) err := c.cc.Invoke(ctx, ClientLifecycleService_GetThreadDump_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -122,8 +123,8 @@ func (c *clientLifecycleServiceClient) GetThreadDump(ctx context.Context, in *Em return out, nil } -func (c *clientLifecycleServiceClient) StartCPUProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *clientLifecycleServiceClient) StartCPUProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ClientLifecycleService_StartCPUProfile_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -131,8 +132,8 @@ func (c *clientLifecycleServiceClient) StartCPUProfile(ctx context.Context, in * return out, nil } -func (c *clientLifecycleServiceClient) StopCPUProfile(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *clientLifecycleServiceClient) StopCPUProfile(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ClientLifecycleService_StopCPUProfile_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -140,8 +141,8 @@ func (c *clientLifecycleServiceClient) StopCPUProfile(ctx context.Context, in *E return out, nil } -func (c *clientLifecycleServiceClient) GetHeapProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *clientLifecycleServiceClient) GetHeapProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ClientLifecycleService_GetHeapProfile_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -149,8 +150,8 @@ func (c *clientLifecycleServiceClient) GetHeapProfile(ctx context.Context, in *P return out, nil } -func (c *clientLifecycleServiceClient) GetMemoryStatistics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*MemoryStatistics, error) { - out := new(MemoryStatistics) +func (c *clientLifecycleServiceClient) GetMemoryStatistics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.MemoryStatistics, error) { + out := new(appctlpb.MemoryStatistics) err := c.cc.Invoke(ctx, ClientLifecycleService_GetMemoryStatistics_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -163,23 +164,23 @@ func (c *clientLifecycleServiceClient) GetMemoryStatistics(ctx context.Context, // for forward compatibility type ClientLifecycleServiceServer interface { // Fetch client application status. - GetStatus(context.Context, *Empty) (*AppStatusMsg, error) + GetStatus(context.Context, *appctlpb.Empty) (*appctlpb.AppStatusMsg, error) // Quit client daemon. - Exit(context.Context, *Empty) (*Empty, error) + Exit(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) // Get client metrics. - GetMetrics(context.Context, *Empty) (*Metrics, error) + GetMetrics(context.Context, *appctlpb.Empty) (*appctlpb.Metrics, error) // Get client session information. - GetSessionInfo(context.Context, *Empty) (*SessionInfo, error) + GetSessionInfo(context.Context, *appctlpb.Empty) (*appctlpb.SessionInfo, error) // Generate a thread dump of client daemon. - GetThreadDump(context.Context, *Empty) (*ThreadDump, error) + GetThreadDump(context.Context, *appctlpb.Empty) (*appctlpb.ThreadDump, error) // Start CPU profiling. - StartCPUProfile(context.Context, *ProfileSavePath) (*Empty, error) + StartCPUProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) // Stop CPU profiling. - StopCPUProfile(context.Context, *Empty) (*Empty, error) + StopCPUProfile(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) // Generate a heap profile. - GetHeapProfile(context.Context, *ProfileSavePath) (*Empty, error) + GetHeapProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) // Get memory statistics of client daemon. - GetMemoryStatistics(context.Context, *Empty) (*MemoryStatistics, error) + GetMemoryStatistics(context.Context, *appctlpb.Empty) (*appctlpb.MemoryStatistics, error) mustEmbedUnimplementedClientLifecycleServiceServer() } @@ -187,31 +188,31 @@ type ClientLifecycleServiceServer interface { type UnimplementedClientLifecycleServiceServer struct { } -func (UnimplementedClientLifecycleServiceServer) GetStatus(context.Context, *Empty) (*AppStatusMsg, error) { +func (UnimplementedClientLifecycleServiceServer) GetStatus(context.Context, *appctlpb.Empty) (*appctlpb.AppStatusMsg, error) { return nil, status.Errorf(codes.Unimplemented, "method GetStatus not implemented") } -func (UnimplementedClientLifecycleServiceServer) Exit(context.Context, *Empty) (*Empty, error) { +func (UnimplementedClientLifecycleServiceServer) Exit(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Exit not implemented") } -func (UnimplementedClientLifecycleServiceServer) GetMetrics(context.Context, *Empty) (*Metrics, error) { +func (UnimplementedClientLifecycleServiceServer) GetMetrics(context.Context, *appctlpb.Empty) (*appctlpb.Metrics, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMetrics not implemented") } -func (UnimplementedClientLifecycleServiceServer) GetSessionInfo(context.Context, *Empty) (*SessionInfo, error) { +func (UnimplementedClientLifecycleServiceServer) GetSessionInfo(context.Context, *appctlpb.Empty) (*appctlpb.SessionInfo, error) { return nil, status.Errorf(codes.Unimplemented, "method GetSessionInfo not implemented") } -func (UnimplementedClientLifecycleServiceServer) GetThreadDump(context.Context, *Empty) (*ThreadDump, error) { +func (UnimplementedClientLifecycleServiceServer) GetThreadDump(context.Context, *appctlpb.Empty) (*appctlpb.ThreadDump, error) { return nil, status.Errorf(codes.Unimplemented, "method GetThreadDump not implemented") } -func (UnimplementedClientLifecycleServiceServer) StartCPUProfile(context.Context, *ProfileSavePath) (*Empty, error) { +func (UnimplementedClientLifecycleServiceServer) StartCPUProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method StartCPUProfile not implemented") } -func (UnimplementedClientLifecycleServiceServer) StopCPUProfile(context.Context, *Empty) (*Empty, error) { +func (UnimplementedClientLifecycleServiceServer) StopCPUProfile(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method StopCPUProfile not implemented") } -func (UnimplementedClientLifecycleServiceServer) GetHeapProfile(context.Context, *ProfileSavePath) (*Empty, error) { +func (UnimplementedClientLifecycleServiceServer) GetHeapProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method GetHeapProfile not implemented") } -func (UnimplementedClientLifecycleServiceServer) GetMemoryStatistics(context.Context, *Empty) (*MemoryStatistics, error) { +func (UnimplementedClientLifecycleServiceServer) GetMemoryStatistics(context.Context, *appctlpb.Empty) (*appctlpb.MemoryStatistics, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMemoryStatistics not implemented") } func (UnimplementedClientLifecycleServiceServer) mustEmbedUnimplementedClientLifecycleServiceServer() { @@ -229,7 +230,7 @@ func RegisterClientLifecycleServiceServer(s grpc.ServiceRegistrar, srv ClientLif } func _ClientLifecycleService_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -241,13 +242,13 @@ func _ClientLifecycleService_GetStatus_Handler(srv interface{}, ctx context.Cont FullMethod: ClientLifecycleService_GetStatus_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).GetStatus(ctx, req.(*Empty)) + return srv.(ClientLifecycleServiceServer).GetStatus(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_Exit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -259,13 +260,13 @@ func _ClientLifecycleService_Exit_Handler(srv interface{}, ctx context.Context, FullMethod: ClientLifecycleService_Exit_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).Exit(ctx, req.(*Empty)) + return srv.(ClientLifecycleServiceServer).Exit(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_GetMetrics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -277,13 +278,13 @@ func _ClientLifecycleService_GetMetrics_Handler(srv interface{}, ctx context.Con FullMethod: ClientLifecycleService_GetMetrics_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).GetMetrics(ctx, req.(*Empty)) + return srv.(ClientLifecycleServiceServer).GetMetrics(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_GetSessionInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -295,13 +296,13 @@ func _ClientLifecycleService_GetSessionInfo_Handler(srv interface{}, ctx context FullMethod: ClientLifecycleService_GetSessionInfo_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).GetSessionInfo(ctx, req.(*Empty)) + return srv.(ClientLifecycleServiceServer).GetSessionInfo(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_GetThreadDump_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -313,13 +314,13 @@ func _ClientLifecycleService_GetThreadDump_Handler(srv interface{}, ctx context. FullMethod: ClientLifecycleService_GetThreadDump_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).GetThreadDump(ctx, req.(*Empty)) + return srv.(ClientLifecycleServiceServer).GetThreadDump(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_StartCPUProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProfileSavePath) + in := new(appctlpb.ProfileSavePath) if err := dec(in); err != nil { return nil, err } @@ -331,13 +332,13 @@ func _ClientLifecycleService_StartCPUProfile_Handler(srv interface{}, ctx contex FullMethod: ClientLifecycleService_StartCPUProfile_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).StartCPUProfile(ctx, req.(*ProfileSavePath)) + return srv.(ClientLifecycleServiceServer).StartCPUProfile(ctx, req.(*appctlpb.ProfileSavePath)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_StopCPUProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -349,13 +350,13 @@ func _ClientLifecycleService_StopCPUProfile_Handler(srv interface{}, ctx context FullMethod: ClientLifecycleService_StopCPUProfile_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).StopCPUProfile(ctx, req.(*Empty)) + return srv.(ClientLifecycleServiceServer).StopCPUProfile(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_GetHeapProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProfileSavePath) + in := new(appctlpb.ProfileSavePath) if err := dec(in); err != nil { return nil, err } @@ -367,13 +368,13 @@ func _ClientLifecycleService_GetHeapProfile_Handler(srv interface{}, ctx context FullMethod: ClientLifecycleService_GetHeapProfile_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).GetHeapProfile(ctx, req.(*ProfileSavePath)) + return srv.(ClientLifecycleServiceServer).GetHeapProfile(ctx, req.(*appctlpb.ProfileSavePath)) } return interceptor(ctx, in, info, handler) } func _ClientLifecycleService_GetMemoryStatistics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -385,7 +386,7 @@ func _ClientLifecycleService_GetMemoryStatistics_Handler(srv interface{}, ctx co FullMethod: ClientLifecycleService_GetMemoryStatistics_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ClientLifecycleServiceServer).GetMemoryStatistics(ctx, req.(*Empty)) + return srv.(ClientLifecycleServiceServer).GetMemoryStatistics(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } @@ -458,29 +459,29 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ServerLifecycleServiceClient interface { // Fetch server application status. - GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*AppStatusMsg, error) + GetStatus(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.AppStatusMsg, error) // Start proxy in server application. - Start(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + Start(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Stop proxy in server application. - Stop(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + Stop(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Reload server configuration. - Reload(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + Reload(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Quit server daemon. - Exit(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + Exit(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Get server metrics. - GetMetrics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Metrics, error) + GetMetrics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Metrics, error) // Get server session information. - GetSessionInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*SessionInfo, error) + GetSessionInfo(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.SessionInfo, error) // Generate a thread dump of server daemon. - GetThreadDump(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ThreadDump, error) + GetThreadDump(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.ThreadDump, error) // Start CPU profiling. - StartCPUProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) + StartCPUProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Stop CPU profiling. - StopCPUProfile(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) + StopCPUProfile(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Generate a heap profile. - GetHeapProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) + GetHeapProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) // Get memory statistics of server daemon. - GetMemoryStatistics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*MemoryStatistics, error) + GetMemoryStatistics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.MemoryStatistics, error) } type serverLifecycleServiceClient struct { @@ -491,8 +492,8 @@ func NewServerLifecycleServiceClient(cc grpc.ClientConnInterface) ServerLifecycl return &serverLifecycleServiceClient{cc} } -func (c *serverLifecycleServiceClient) GetStatus(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*AppStatusMsg, error) { - out := new(AppStatusMsg) +func (c *serverLifecycleServiceClient) GetStatus(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.AppStatusMsg, error) { + out := new(appctlpb.AppStatusMsg) err := c.cc.Invoke(ctx, ServerLifecycleService_GetStatus_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -500,8 +501,8 @@ func (c *serverLifecycleServiceClient) GetStatus(ctx context.Context, in *Empty, return out, nil } -func (c *serverLifecycleServiceClient) Start(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *serverLifecycleServiceClient) Start(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ServerLifecycleService_Start_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -509,8 +510,8 @@ func (c *serverLifecycleServiceClient) Start(ctx context.Context, in *Empty, opt return out, nil } -func (c *serverLifecycleServiceClient) Stop(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *serverLifecycleServiceClient) Stop(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ServerLifecycleService_Stop_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -518,8 +519,8 @@ func (c *serverLifecycleServiceClient) Stop(ctx context.Context, in *Empty, opts return out, nil } -func (c *serverLifecycleServiceClient) Reload(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *serverLifecycleServiceClient) Reload(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ServerLifecycleService_Reload_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -527,8 +528,8 @@ func (c *serverLifecycleServiceClient) Reload(ctx context.Context, in *Empty, op return out, nil } -func (c *serverLifecycleServiceClient) Exit(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *serverLifecycleServiceClient) Exit(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ServerLifecycleService_Exit_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -536,8 +537,8 @@ func (c *serverLifecycleServiceClient) Exit(ctx context.Context, in *Empty, opts return out, nil } -func (c *serverLifecycleServiceClient) GetMetrics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Metrics, error) { - out := new(Metrics) +func (c *serverLifecycleServiceClient) GetMetrics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Metrics, error) { + out := new(appctlpb.Metrics) err := c.cc.Invoke(ctx, ServerLifecycleService_GetMetrics_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -545,8 +546,8 @@ func (c *serverLifecycleServiceClient) GetMetrics(ctx context.Context, in *Empty return out, nil } -func (c *serverLifecycleServiceClient) GetSessionInfo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*SessionInfo, error) { - out := new(SessionInfo) +func (c *serverLifecycleServiceClient) GetSessionInfo(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.SessionInfo, error) { + out := new(appctlpb.SessionInfo) err := c.cc.Invoke(ctx, ServerLifecycleService_GetSessionInfo_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -554,8 +555,8 @@ func (c *serverLifecycleServiceClient) GetSessionInfo(ctx context.Context, in *E return out, nil } -func (c *serverLifecycleServiceClient) GetThreadDump(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ThreadDump, error) { - out := new(ThreadDump) +func (c *serverLifecycleServiceClient) GetThreadDump(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.ThreadDump, error) { + out := new(appctlpb.ThreadDump) err := c.cc.Invoke(ctx, ServerLifecycleService_GetThreadDump_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -563,8 +564,8 @@ func (c *serverLifecycleServiceClient) GetThreadDump(ctx context.Context, in *Em return out, nil } -func (c *serverLifecycleServiceClient) StartCPUProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *serverLifecycleServiceClient) StartCPUProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ServerLifecycleService_StartCPUProfile_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -572,8 +573,8 @@ func (c *serverLifecycleServiceClient) StartCPUProfile(ctx context.Context, in * return out, nil } -func (c *serverLifecycleServiceClient) StopCPUProfile(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *serverLifecycleServiceClient) StopCPUProfile(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ServerLifecycleService_StopCPUProfile_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -581,8 +582,8 @@ func (c *serverLifecycleServiceClient) StopCPUProfile(ctx context.Context, in *E return out, nil } -func (c *serverLifecycleServiceClient) GetHeapProfile(ctx context.Context, in *ProfileSavePath, opts ...grpc.CallOption) (*Empty, error) { - out := new(Empty) +func (c *serverLifecycleServiceClient) GetHeapProfile(ctx context.Context, in *appctlpb.ProfileSavePath, opts ...grpc.CallOption) (*appctlpb.Empty, error) { + out := new(appctlpb.Empty) err := c.cc.Invoke(ctx, ServerLifecycleService_GetHeapProfile_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -590,8 +591,8 @@ func (c *serverLifecycleServiceClient) GetHeapProfile(ctx context.Context, in *P return out, nil } -func (c *serverLifecycleServiceClient) GetMemoryStatistics(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*MemoryStatistics, error) { - out := new(MemoryStatistics) +func (c *serverLifecycleServiceClient) GetMemoryStatistics(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.MemoryStatistics, error) { + out := new(appctlpb.MemoryStatistics) err := c.cc.Invoke(ctx, ServerLifecycleService_GetMemoryStatistics_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -604,29 +605,29 @@ func (c *serverLifecycleServiceClient) GetMemoryStatistics(ctx context.Context, // for forward compatibility type ServerLifecycleServiceServer interface { // Fetch server application status. - GetStatus(context.Context, *Empty) (*AppStatusMsg, error) + GetStatus(context.Context, *appctlpb.Empty) (*appctlpb.AppStatusMsg, error) // Start proxy in server application. - Start(context.Context, *Empty) (*Empty, error) + Start(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) // Stop proxy in server application. - Stop(context.Context, *Empty) (*Empty, error) + Stop(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) // Reload server configuration. - Reload(context.Context, *Empty) (*Empty, error) + Reload(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) // Quit server daemon. - Exit(context.Context, *Empty) (*Empty, error) + Exit(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) // Get server metrics. - GetMetrics(context.Context, *Empty) (*Metrics, error) + GetMetrics(context.Context, *appctlpb.Empty) (*appctlpb.Metrics, error) // Get server session information. - GetSessionInfo(context.Context, *Empty) (*SessionInfo, error) + GetSessionInfo(context.Context, *appctlpb.Empty) (*appctlpb.SessionInfo, error) // Generate a thread dump of server daemon. - GetThreadDump(context.Context, *Empty) (*ThreadDump, error) + GetThreadDump(context.Context, *appctlpb.Empty) (*appctlpb.ThreadDump, error) // Start CPU profiling. - StartCPUProfile(context.Context, *ProfileSavePath) (*Empty, error) + StartCPUProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) // Stop CPU profiling. - StopCPUProfile(context.Context, *Empty) (*Empty, error) + StopCPUProfile(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) // Generate a heap profile. - GetHeapProfile(context.Context, *ProfileSavePath) (*Empty, error) + GetHeapProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) // Get memory statistics of server daemon. - GetMemoryStatistics(context.Context, *Empty) (*MemoryStatistics, error) + GetMemoryStatistics(context.Context, *appctlpb.Empty) (*appctlpb.MemoryStatistics, error) mustEmbedUnimplementedServerLifecycleServiceServer() } @@ -634,40 +635,40 @@ type ServerLifecycleServiceServer interface { type UnimplementedServerLifecycleServiceServer struct { } -func (UnimplementedServerLifecycleServiceServer) GetStatus(context.Context, *Empty) (*AppStatusMsg, error) { +func (UnimplementedServerLifecycleServiceServer) GetStatus(context.Context, *appctlpb.Empty) (*appctlpb.AppStatusMsg, error) { return nil, status.Errorf(codes.Unimplemented, "method GetStatus not implemented") } -func (UnimplementedServerLifecycleServiceServer) Start(context.Context, *Empty) (*Empty, error) { +func (UnimplementedServerLifecycleServiceServer) Start(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Start not implemented") } -func (UnimplementedServerLifecycleServiceServer) Stop(context.Context, *Empty) (*Empty, error) { +func (UnimplementedServerLifecycleServiceServer) Stop(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented") } -func (UnimplementedServerLifecycleServiceServer) Reload(context.Context, *Empty) (*Empty, error) { +func (UnimplementedServerLifecycleServiceServer) Reload(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Reload not implemented") } -func (UnimplementedServerLifecycleServiceServer) Exit(context.Context, *Empty) (*Empty, error) { +func (UnimplementedServerLifecycleServiceServer) Exit(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Exit not implemented") } -func (UnimplementedServerLifecycleServiceServer) GetMetrics(context.Context, *Empty) (*Metrics, error) { +func (UnimplementedServerLifecycleServiceServer) GetMetrics(context.Context, *appctlpb.Empty) (*appctlpb.Metrics, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMetrics not implemented") } -func (UnimplementedServerLifecycleServiceServer) GetSessionInfo(context.Context, *Empty) (*SessionInfo, error) { +func (UnimplementedServerLifecycleServiceServer) GetSessionInfo(context.Context, *appctlpb.Empty) (*appctlpb.SessionInfo, error) { return nil, status.Errorf(codes.Unimplemented, "method GetSessionInfo not implemented") } -func (UnimplementedServerLifecycleServiceServer) GetThreadDump(context.Context, *Empty) (*ThreadDump, error) { +func (UnimplementedServerLifecycleServiceServer) GetThreadDump(context.Context, *appctlpb.Empty) (*appctlpb.ThreadDump, error) { return nil, status.Errorf(codes.Unimplemented, "method GetThreadDump not implemented") } -func (UnimplementedServerLifecycleServiceServer) StartCPUProfile(context.Context, *ProfileSavePath) (*Empty, error) { +func (UnimplementedServerLifecycleServiceServer) StartCPUProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method StartCPUProfile not implemented") } -func (UnimplementedServerLifecycleServiceServer) StopCPUProfile(context.Context, *Empty) (*Empty, error) { +func (UnimplementedServerLifecycleServiceServer) StopCPUProfile(context.Context, *appctlpb.Empty) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method StopCPUProfile not implemented") } -func (UnimplementedServerLifecycleServiceServer) GetHeapProfile(context.Context, *ProfileSavePath) (*Empty, error) { +func (UnimplementedServerLifecycleServiceServer) GetHeapProfile(context.Context, *appctlpb.ProfileSavePath) (*appctlpb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method GetHeapProfile not implemented") } -func (UnimplementedServerLifecycleServiceServer) GetMemoryStatistics(context.Context, *Empty) (*MemoryStatistics, error) { +func (UnimplementedServerLifecycleServiceServer) GetMemoryStatistics(context.Context, *appctlpb.Empty) (*appctlpb.MemoryStatistics, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMemoryStatistics not implemented") } func (UnimplementedServerLifecycleServiceServer) mustEmbedUnimplementedServerLifecycleServiceServer() { @@ -685,7 +686,7 @@ func RegisterServerLifecycleServiceServer(s grpc.ServiceRegistrar, srv ServerLif } func _ServerLifecycleService_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -697,13 +698,13 @@ func _ServerLifecycleService_GetStatus_Handler(srv interface{}, ctx context.Cont FullMethod: ServerLifecycleService_GetStatus_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).GetStatus(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).GetStatus(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_Start_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -715,13 +716,13 @@ func _ServerLifecycleService_Start_Handler(srv interface{}, ctx context.Context, FullMethod: ServerLifecycleService_Start_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).Start(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).Start(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_Stop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -733,13 +734,13 @@ func _ServerLifecycleService_Stop_Handler(srv interface{}, ctx context.Context, FullMethod: ServerLifecycleService_Stop_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).Stop(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).Stop(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_Reload_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -751,13 +752,13 @@ func _ServerLifecycleService_Reload_Handler(srv interface{}, ctx context.Context FullMethod: ServerLifecycleService_Reload_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).Reload(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).Reload(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_Exit_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -769,13 +770,13 @@ func _ServerLifecycleService_Exit_Handler(srv interface{}, ctx context.Context, FullMethod: ServerLifecycleService_Exit_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).Exit(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).Exit(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_GetMetrics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -787,13 +788,13 @@ func _ServerLifecycleService_GetMetrics_Handler(srv interface{}, ctx context.Con FullMethod: ServerLifecycleService_GetMetrics_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).GetMetrics(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).GetMetrics(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_GetSessionInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -805,13 +806,13 @@ func _ServerLifecycleService_GetSessionInfo_Handler(srv interface{}, ctx context FullMethod: ServerLifecycleService_GetSessionInfo_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).GetSessionInfo(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).GetSessionInfo(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_GetThreadDump_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -823,13 +824,13 @@ func _ServerLifecycleService_GetThreadDump_Handler(srv interface{}, ctx context. FullMethod: ServerLifecycleService_GetThreadDump_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).GetThreadDump(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).GetThreadDump(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_StartCPUProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProfileSavePath) + in := new(appctlpb.ProfileSavePath) if err := dec(in); err != nil { return nil, err } @@ -841,13 +842,13 @@ func _ServerLifecycleService_StartCPUProfile_Handler(srv interface{}, ctx contex FullMethod: ServerLifecycleService_StartCPUProfile_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).StartCPUProfile(ctx, req.(*ProfileSavePath)) + return srv.(ServerLifecycleServiceServer).StartCPUProfile(ctx, req.(*appctlpb.ProfileSavePath)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_StopCPUProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -859,13 +860,13 @@ func _ServerLifecycleService_StopCPUProfile_Handler(srv interface{}, ctx context FullMethod: ServerLifecycleService_StopCPUProfile_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).StopCPUProfile(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).StopCPUProfile(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_GetHeapProfile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProfileSavePath) + in := new(appctlpb.ProfileSavePath) if err := dec(in); err != nil { return nil, err } @@ -877,13 +878,13 @@ func _ServerLifecycleService_GetHeapProfile_Handler(srv interface{}, ctx context FullMethod: ServerLifecycleService_GetHeapProfile_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).GetHeapProfile(ctx, req.(*ProfileSavePath)) + return srv.(ServerLifecycleServiceServer).GetHeapProfile(ctx, req.(*appctlpb.ProfileSavePath)) } return interceptor(ctx, in, info, handler) } func _ServerLifecycleService_GetMemoryStatistics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -895,7 +896,7 @@ func _ServerLifecycleService_GetMemoryStatistics_Handler(srv interface{}, ctx co FullMethod: ServerLifecycleService_GetMemoryStatistics_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerLifecycleServiceServer).GetMemoryStatistics(ctx, req.(*Empty)) + return srv.(ServerLifecycleServiceServer).GetMemoryStatistics(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } @@ -970,9 +971,9 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type ServerConfigServiceClient interface { // Fetch the server config. - GetConfig(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServerConfig, error) + GetConfig(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.ServerConfig, error) // Update server config. - SetConfig(ctx context.Context, in *ServerConfig, opts ...grpc.CallOption) (*ServerConfig, error) + SetConfig(ctx context.Context, in *appctlpb.ServerConfig, opts ...grpc.CallOption) (*appctlpb.ServerConfig, error) } type serverConfigServiceClient struct { @@ -983,8 +984,8 @@ func NewServerConfigServiceClient(cc grpc.ClientConnInterface) ServerConfigServi return &serverConfigServiceClient{cc} } -func (c *serverConfigServiceClient) GetConfig(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ServerConfig, error) { - out := new(ServerConfig) +func (c *serverConfigServiceClient) GetConfig(ctx context.Context, in *appctlpb.Empty, opts ...grpc.CallOption) (*appctlpb.ServerConfig, error) { + out := new(appctlpb.ServerConfig) err := c.cc.Invoke(ctx, ServerConfigService_GetConfig_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -992,8 +993,8 @@ func (c *serverConfigServiceClient) GetConfig(ctx context.Context, in *Empty, op return out, nil } -func (c *serverConfigServiceClient) SetConfig(ctx context.Context, in *ServerConfig, opts ...grpc.CallOption) (*ServerConfig, error) { - out := new(ServerConfig) +func (c *serverConfigServiceClient) SetConfig(ctx context.Context, in *appctlpb.ServerConfig, opts ...grpc.CallOption) (*appctlpb.ServerConfig, error) { + out := new(appctlpb.ServerConfig) err := c.cc.Invoke(ctx, ServerConfigService_SetConfig_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -1006,9 +1007,9 @@ func (c *serverConfigServiceClient) SetConfig(ctx context.Context, in *ServerCon // for forward compatibility type ServerConfigServiceServer interface { // Fetch the server config. - GetConfig(context.Context, *Empty) (*ServerConfig, error) + GetConfig(context.Context, *appctlpb.Empty) (*appctlpb.ServerConfig, error) // Update server config. - SetConfig(context.Context, *ServerConfig) (*ServerConfig, error) + SetConfig(context.Context, *appctlpb.ServerConfig) (*appctlpb.ServerConfig, error) mustEmbedUnimplementedServerConfigServiceServer() } @@ -1016,10 +1017,10 @@ type ServerConfigServiceServer interface { type UnimplementedServerConfigServiceServer struct { } -func (UnimplementedServerConfigServiceServer) GetConfig(context.Context, *Empty) (*ServerConfig, error) { +func (UnimplementedServerConfigServiceServer) GetConfig(context.Context, *appctlpb.Empty) (*appctlpb.ServerConfig, error) { return nil, status.Errorf(codes.Unimplemented, "method GetConfig not implemented") } -func (UnimplementedServerConfigServiceServer) SetConfig(context.Context, *ServerConfig) (*ServerConfig, error) { +func (UnimplementedServerConfigServiceServer) SetConfig(context.Context, *appctlpb.ServerConfig) (*appctlpb.ServerConfig, error) { return nil, status.Errorf(codes.Unimplemented, "method SetConfig not implemented") } func (UnimplementedServerConfigServiceServer) mustEmbedUnimplementedServerConfigServiceServer() {} @@ -1036,7 +1037,7 @@ func RegisterServerConfigServiceServer(s grpc.ServiceRegistrar, srv ServerConfig } func _ServerConfigService_GetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(Empty) + in := new(appctlpb.Empty) if err := dec(in); err != nil { return nil, err } @@ -1048,13 +1049,13 @@ func _ServerConfigService_GetConfig_Handler(srv interface{}, ctx context.Context FullMethod: ServerConfigService_GetConfig_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerConfigServiceServer).GetConfig(ctx, req.(*Empty)) + return srv.(ServerConfigServiceServer).GetConfig(ctx, req.(*appctlpb.Empty)) } return interceptor(ctx, in, info, handler) } func _ServerConfigService_SetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ServerConfig) + in := new(appctlpb.ServerConfig) if err := dec(in); err != nil { return nil, err } @@ -1066,7 +1067,7 @@ func _ServerConfigService_SetConfig_Handler(srv interface{}, ctx context.Context FullMethod: ServerConfigService_SetConfig_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ServerConfigServiceServer).SetConfig(ctx, req.(*ServerConfig)) + return srv.(ServerConfigServiceServer).SetConfig(ctx, req.(*appctlpb.ServerConfig)) } return interceptor(ctx, in, info, handler) } diff --git a/pkg/appctl/appctlpb/base.pb.go b/pkg/appctl/appctlpb/base.pb.go index af841d07..79e93952 100644 --- a/pkg/appctl/appctlpb/base.pb.go +++ b/pkg/appctl/appctlpb/base.pb.go @@ -688,11 +688,11 @@ var file_base_proto_rawDesc = []byte{ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, - 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, + 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, 0x2f, - 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, - 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, + 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/appctl/appctlpb/clientcfg.pb.go b/pkg/appctl/appctlpb/clientcfg.pb.go index 13f30537..8e98303a 100644 --- a/pkg/appctl/appctlpb/clientcfg.pb.go +++ b/pkg/appctl/appctlpb/clientcfg.pb.go @@ -472,10 +472,10 @@ var file_clientcfg_proto_rawDesc = []byte{ 0x4c, 0x4f, 0x57, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x50, 0x4c, 0x45, 0x58, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x49, 0x44, 0x44, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x50, 0x4c, 0x45, 0x58, 0x49, 0x4e, 0x47, 0x5f, 0x48, - 0x49, 0x47, 0x48, 0x10, 0x04, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x49, 0x47, 0x48, 0x10, 0x04, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, - 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, - 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, + 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/appctl/appctlpb/misc.pb.go b/pkg/appctl/appctlpb/misc.pb.go index dca9b551..ed5e7971 100644 --- a/pkg/appctl/appctlpb/misc.pb.go +++ b/pkg/appctl/appctlpb/misc.pb.go @@ -296,10 +296,10 @@ var file_misc_proto_rawDesc = []byte{ 0x6f, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x17, 0x0a, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x42, - 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, - 0x66, 0x65, 0x69, 0x6e, 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, - 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, + 0x66, 0x65, 0x69, 0x6e, 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/appctl/appctlpb/servercfg.pb.go b/pkg/appctl/appctlpb/servercfg.pb.go index 77debaa1..da1884f0 100644 --- a/pkg/appctl/appctlpb/servercfg.pb.go +++ b/pkg/appctl/appctlpb/servercfg.pb.go @@ -574,10 +574,10 @@ var file_servercfg_proto_rawDesc = []byte{ 0x01, 0x2a, 0x31, 0x0a, 0x0c, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4a, 0x45, - 0x43, 0x54, 0x10, 0x02, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x43, 0x54, 0x10, 0x02, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, - 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, + 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/appctl/client.go b/pkg/appctl/client.go index 34f9fcf7..26381b2b 100644 --- a/pkg/appctl/client.go +++ b/pkg/appctl/client.go @@ -27,6 +27,7 @@ import ( "sync" "sync/atomic" + "github.com/enfein/mieru/v3/pkg/appctl/appctlgrpc" pb "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" "github.com/enfein/mieru/v3/pkg/log" "github.com/enfein/mieru/v3/pkg/metrics" @@ -84,7 +85,7 @@ func SetClientMuxRef(mux *protocol.Mux) { // clientLifecycleService implements ClientLifecycleService defined in lifecycle.proto. type clientLifecycleService struct { - pb.UnimplementedClientLifecycleServiceServer + appctlgrpc.UnimplementedClientLifecycleServiceServer } func (c *clientLifecycleService) GetStatus(ctx context.Context, req *pb.Empty) (*pb.AppStatusMsg, error) { @@ -162,7 +163,7 @@ func NewClientLifecycleService() *clientLifecycleService { // NewClientLifecycleRPCClient creates a new ClientLifecycleService RPC client. // It loads client config to find the server address. -func NewClientLifecycleRPCClient(ctx context.Context) (pb.ClientLifecycleServiceClient, error) { +func NewClientLifecycleRPCClient(ctx context.Context) (appctlgrpc.ClientLifecycleServiceClient, error) { config, err := LoadClientConfig() if err != nil { return nil, fmt.Errorf("LoadClientConfig() failed: %w", err) @@ -351,54 +352,12 @@ func DeleteClientConfigProfile(profileName string) error { // // A client config patch must satisfy: // 1. it has 0 or more profile -// 2. for each profile -// 2.1. profile name is not empty -// 2.2. user name is not empty -// 2.3. user has either a password or a hashed password -// 2.4. user has no quota -// 2.5. it has at least 1 server, and for each server -// 2.5.1. the server has either IP address or domain name -// 2.5.2. if set, server's IP address is parsable -// 2.5.3. the server has at least 1 port binding, and all port bindings are valid -// 2.6. if set, MTU is valid +// 2. validate each profile // 3. for each socks5 authentication, the user and password are not empty func ValidateClientConfigPatch(patch *pb.ClientConfig) error { for _, profile := range patch.GetProfiles() { - name := profile.GetProfileName() - if name == "" { - return fmt.Errorf("profile name is not set") - } - user := profile.GetUser() - if user.GetName() == "" { - return fmt.Errorf("user name is not set") - } - if user.GetPassword() == "" && user.GetHashedPassword() == "" { - return fmt.Errorf("user password is not set") - } - if len(user.GetQuotas()) != 0 { - return fmt.Errorf("user quota is not supported by proxy client") - } - servers := profile.GetServers() - if len(servers) == 0 { - return fmt.Errorf("servers are not set") - } - for _, server := range servers { - if server.GetIpAddress() == "" && server.GetDomainName() == "" { - return fmt.Errorf("neither server IP address nor domain name is set") - } - if server.GetIpAddress() != "" && net.ParseIP(server.GetIpAddress()) == nil { - return fmt.Errorf("failed to parse IP address %q", server.GetIpAddress()) - } - portBindings := server.GetPortBindings() - if len(portBindings) == 0 { - return fmt.Errorf("server port binding is not set") - } - if _, err := FlatPortBindings(portBindings); err != nil { - return err - } - } - if profile.GetMtu() != 0 && (profile.GetMtu() < 1280 || profile.GetMtu() > 1500) { - return fmt.Errorf("MTU value %d is out of range, valid range is [1280, 1500]", profile.GetMtu()) + if err := ValidateClientConfigSingleProfile(profile); err != nil { + return err } } for _, auth := range patch.GetSocks5Authentication() { @@ -412,6 +371,59 @@ func ValidateClientConfigPatch(patch *pb.ClientConfig) error { return nil } +// ValidateClientConfigSingleProfile validates +// a single client config profile. +// +// It validates +// 1. profile name is not empty +// 2. user name is not empty +// 3. user has either a password or a hashed password +// 4. user has no quota +// 5. it has at least 1 server, and for each server +// 5.1. the server has either IP address or domain name +// 5.2. if set, server's IP address is parsable +// 5.3. the server has at least 1 port binding, and all port bindings are valid +// 6. if set, MTU is valid +func ValidateClientConfigSingleProfile(profile *pb.ClientProfile) error { + name := profile.GetProfileName() + if name == "" { + return fmt.Errorf("profile name is not set") + } + user := profile.GetUser() + if user.GetName() == "" { + return fmt.Errorf("user name is not set") + } + if user.GetPassword() == "" && user.GetHashedPassword() == "" { + return fmt.Errorf("user password is not set") + } + if len(user.GetQuotas()) != 0 { + return fmt.Errorf("user quota is not supported by proxy client") + } + servers := profile.GetServers() + if len(servers) == 0 { + return fmt.Errorf("servers are not set") + } + for _, server := range servers { + if server.GetIpAddress() == "" && server.GetDomainName() == "" { + return fmt.Errorf("neither server IP address nor domain name is set") + } + if server.GetIpAddress() != "" && net.ParseIP(server.GetIpAddress()) == nil { + return fmt.Errorf("failed to parse IP address %q", server.GetIpAddress()) + } + portBindings := server.GetPortBindings() + if len(portBindings) == 0 { + return fmt.Errorf("server port binding is not set") + } + if _, err := FlatPortBindings(portBindings); err != nil { + return err + } + } + if profile.GetMtu() != 0 && (profile.GetMtu() < 1280 || profile.GetMtu() > 1500) { + return fmt.Errorf("MTU value %d is out of range, valid range is [1280, 1500]", profile.GetMtu()) + } + return nil +} + // ValidateFullClientConfig validates the full client config. // // In addition to ValidateClientConfigPatch, it also validates: @@ -479,12 +491,12 @@ func GetActiveProfileFromConfig(config *pb.ClientConfig, name string) (*pb.Clien // newClientLifecycleRPCClient creates a new ClientLifecycleService RPC client // and connects to the given server address. -func newClientLifecycleRPCClient(ctx context.Context, serverAddr string) (pb.ClientLifecycleServiceClient, error) { +func newClientLifecycleRPCClient(ctx context.Context, serverAddr string) (appctlgrpc.ClientLifecycleServiceClient, error) { conn, err := grpc.DialContext(ctx, serverAddr, grpc.WithInsecure()) if err != nil { return nil, fmt.Errorf("grpc.DialContext() failed: %w", err) } - return pb.NewClientLifecycleServiceClient(conn), nil + return appctlgrpc.NewClientLifecycleServiceClient(conn), nil } // prepareClientConfigDir creates the client config directory if needed. diff --git a/pkg/appctl/proto/base.proto b/pkg/appctl/proto/base.proto index bac7536d..ee83df02 100644 --- a/pkg/appctl/proto/base.proto +++ b/pkg/appctl/proto/base.proto @@ -17,7 +17,7 @@ syntax = "proto3"; package appctl; -option go_package = "github.com/enfein/mieru/pkg/appctl/appctlpb"; +option go_package = "github.com/enfein/mieru/v3/pkg/appctl/appctlpb"; message Empty {} diff --git a/pkg/appctl/proto/clientcfg.proto b/pkg/appctl/proto/clientcfg.proto index 8f6c39ff..5bbf6cba 100644 --- a/pkg/appctl/proto/clientcfg.proto +++ b/pkg/appctl/proto/clientcfg.proto @@ -19,7 +19,7 @@ package appctl; import "base.proto"; -option go_package = "github.com/enfein/mieru/pkg/appctl/appctlpb"; +option go_package = "github.com/enfein/mieru/v3/pkg/appctl/appctlpb"; message ClientConfig { // A list of known client profiles. diff --git a/pkg/appctl/proto/misc.proto b/pkg/appctl/proto/misc.proto index 390692bd..a68ed163 100644 --- a/pkg/appctl/proto/misc.proto +++ b/pkg/appctl/proto/misc.proto @@ -17,7 +17,7 @@ syntax = "proto3"; package appctl; -option go_package = "github.com/enfein/mieru/pkg/appctl/appctlpb"; +option go_package = "github.com/enfein/mieru/v3/pkg/appctl/appctlpb"; message Metrics { // JSON dump of metrics. diff --git a/pkg/appctl/proto/rpc.proto b/pkg/appctl/proto/rpc.proto index 5970e217..b86fdb6c 100644 --- a/pkg/appctl/proto/rpc.proto +++ b/pkg/appctl/proto/rpc.proto @@ -21,7 +21,7 @@ import "base.proto"; import "misc.proto"; import "servercfg.proto"; -option go_package = "github.com/enfein/mieru/pkg/appctl/appctlpb"; +option go_package = "github.com/enfein/mieru/v3/pkg/appctl/appctlgrpc"; service ClientLifecycleService { // Fetch client application status. diff --git a/pkg/appctl/proto/servercfg.proto b/pkg/appctl/proto/servercfg.proto index 4dd7c0a7..c9fe95c0 100644 --- a/pkg/appctl/proto/servercfg.proto +++ b/pkg/appctl/proto/servercfg.proto @@ -19,7 +19,7 @@ package appctl; import "base.proto"; -option go_package = "github.com/enfein/mieru/pkg/appctl/appctlpb"; +option go_package = "github.com/enfein/mieru/v3/pkg/appctl/appctlpb"; message ServerConfig { // Server's port-protocol bindings. diff --git a/pkg/appctl/server.go b/pkg/appctl/server.go index da51b706..c8146e89 100644 --- a/pkg/appctl/server.go +++ b/pkg/appctl/server.go @@ -27,6 +27,7 @@ import ( "sync/atomic" "time" + "github.com/enfein/mieru/v3/pkg/appctl/appctlgrpc" pb "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" "github.com/enfein/mieru/v3/pkg/egress" "github.com/enfein/mieru/v3/pkg/log" @@ -83,7 +84,7 @@ func ServerUDS() string { // serverLifecycleService implements ServerLifecycleService defined in lifecycle.proto. type serverLifecycleService struct { - pb.UnimplementedServerLifecycleServiceServer + appctlgrpc.UnimplementedServerLifecycleServiceServer } func (s *serverLifecycleService) GetStatus(ctx context.Context, req *pb.Empty) (*pb.AppStatusMsg, error) { @@ -285,7 +286,7 @@ func NewServerLifecycleService() *serverLifecycleService { } // NewServerLifecycleRPCClient creates a new ServerLifecycleService RPC client. -func NewServerLifecycleRPCClient() (pb.ServerLifecycleServiceClient, error) { +func NewServerLifecycleRPCClient() (appctlgrpc.ServerLifecycleServiceClient, error) { rpcAddr := "unix://" + ServerUDS() timedctx, cancelFunc := context.WithTimeout(context.Background(), RPCTimeout) defer cancelFunc() @@ -293,12 +294,12 @@ func NewServerLifecycleRPCClient() (pb.ServerLifecycleServiceClient, error) { if err != nil { return nil, fmt.Errorf("grpc.DialContext() failed: %w", err) } - return pb.NewServerLifecycleServiceClient(conn), nil + return appctlgrpc.NewServerLifecycleServiceClient(conn), nil } // serverConfigService implements ServerConfigService defined in servercfg.proto. type serverConfigService struct { - pb.UnimplementedServerConfigServiceServer + appctlgrpc.UnimplementedServerConfigServiceServer } func (s *serverConfigService) GetConfig(ctx context.Context, req *pb.Empty) (*pb.ServerConfig, error) { @@ -326,7 +327,7 @@ func NewServerConfigService() *serverConfigService { } // NewServerConfigRPCClient creates a new ServerConfigService RPC client. -func NewServerConfigRPCClient() (pb.ServerConfigServiceClient, error) { +func NewServerConfigRPCClient() (appctlgrpc.ServerConfigServiceClient, error) { rpcAddr := "unix://" + ServerUDS() timedctx, cancelFunc := context.WithTimeout(context.Background(), RPCTimeout) defer cancelFunc() @@ -334,7 +335,7 @@ func NewServerConfigRPCClient() (pb.ServerConfigServiceClient, error) { if err != nil { return nil, fmt.Errorf("grpc.DialContext() failed: %w", err) } - return pb.NewServerConfigServiceClient(conn), nil + return appctlgrpc.NewServerConfigServiceClient(conn), nil } // GetServerStatusWithRPC gets server application status via ServerLifecycleService.GetStatus() RPC. diff --git a/pkg/cli/client.go b/pkg/cli/client.go index 85b4e987..3168d19e 100644 --- a/pkg/cli/client.go +++ b/pkg/cli/client.go @@ -31,7 +31,9 @@ import ( "sync" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/appctl" + "github.com/enfein/mieru/v3/pkg/appctl/appctlgrpc" "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" "github.com/enfein/mieru/v3/pkg/cipher" "github.com/enfein/mieru/v3/pkg/log" @@ -444,7 +446,7 @@ var clientRunFunc = func(s []string) error { } grpcServer := grpc.NewServer() appctl.SetClientRPCServerRef(grpcServer) - appctlpb.RegisterClientLifecycleServiceServer(grpcServer, appctl.NewClientLifecycleService()) + appctlgrpc.RegisterClientLifecycleServiceServer(grpcServer, appctl.NewClientLifecycleService()) close(appctl.ClientRPCServerStarted) log.Infof("mieru client RPC server is running") if err = grpcServer.Serve(rpcListener); err != nil { @@ -459,12 +461,12 @@ var clientRunFunc = func(s []string) error { // Collect remote proxy addresses and password. mux := protocol.NewMux(true) appctl.SetClientMuxRef(mux) - var hashedPassword []byte activeProfile, err := appctl.GetActiveProfileFromConfig(config, config.GetActiveProfile()) if err != nil { return fmt.Errorf(stderror.ClientGetActiveProfileFailedErr, err) } user := activeProfile.GetUser() + var hashedPassword []byte if user.GetHashedPassword() != "" { hashedPassword, err = hex.DecodeString(user.GetHashedPassword()) if err != nil { @@ -474,10 +476,7 @@ var clientRunFunc = func(s []string) error { hashedPassword = cipher.HashPassword([]byte(user.GetPassword()), []byte(user.GetName())) } mux = mux.SetClientUserNamePassword(user.GetName(), hashedPassword) - mtu := util.DefaultMTU - if activeProfile.GetMtu() != 0 { - mtu = int(activeProfile.GetMtu()) - } + multiplexFactor := 1 switch activeProfile.GetMultiplexing().GetLevel() { case appctlpb.MultiplexingLevel_MULTIPLEXING_OFF: @@ -490,6 +489,11 @@ var clientRunFunc = func(s []string) error { multiplexFactor = 3 } mux = mux.SetClientMultiplexFactor(multiplexFactor) + + mtu := util.DefaultMTU + if activeProfile.GetMtu() != 0 { + mtu = int(activeProfile.GetMtu()) + } endpoints := make([]protocol.UnderlayProperties, 0) resolver := &util.DNSResolver{} for _, serverInfo := range activeProfile.GetServers() { @@ -659,7 +663,7 @@ var clientTestFunc = func(s []string) error { httpClient := &http.Client{ Transport: &http.Transport{ - Dial: socks5.Dial(fmt.Sprintf("socks5://127.0.0.1:%d", config.GetSocks5Port()), socks5.ConnectCmd), + Dial: socks5.Dial(fmt.Sprintf("socks5://127.0.0.1:%d", config.GetSocks5Port()), constant.Socks5ConnectCmd), }, CheckRedirect: func(req *http.Request, via []*http.Request) error { return nil @@ -912,7 +916,7 @@ var clientStopCPUProfileFunc = func(s []string) error { // newClientLifecycleRPCClient returns a new client lifecycle RPC client. // No RPC client is returned if mieru is not running. -func newClientLifecycleRPCClient(ctx context.Context) (client appctlpb.ClientLifecycleServiceClient, running bool, err error) { +func newClientLifecycleRPCClient(ctx context.Context) (client appctlgrpc.ClientLifecycleServiceClient, running bool, err error) { if err := appctl.IsClientDaemonRunning(ctx); err != nil { return nil, false, nil } diff --git a/pkg/cli/server.go b/pkg/cli/server.go index c6bf9c71..d665aafa 100644 --- a/pkg/cli/server.go +++ b/pkg/cli/server.go @@ -29,6 +29,7 @@ import ( "time" "github.com/enfein/mieru/v3/pkg/appctl" + "github.com/enfein/mieru/v3/pkg/appctl/appctlgrpc" "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" "github.com/enfein/mieru/v3/pkg/cipher" "github.com/enfein/mieru/v3/pkg/egress" @@ -336,8 +337,8 @@ var serverRunFunc = func(s []string) error { } grpcServer := grpc.NewServer() appctl.SetServerRPCServerRef(grpcServer) - appctlpb.RegisterServerLifecycleServiceServer(grpcServer, appctl.NewServerLifecycleService()) - appctlpb.RegisterServerConfigServiceServer(grpcServer, appctl.NewServerConfigService()) + appctlgrpc.RegisterServerLifecycleServiceServer(grpcServer, appctl.NewServerLifecycleService()) + appctlgrpc.RegisterServerConfigServiceServer(grpcServer, appctl.NewServerConfigService()) close(appctl.ServerRPCServerStarted) log.Infof("mita server daemon RPC server is running") if err = grpcServer.Serve(rpcListener); err != nil { diff --git a/pkg/metrics/export.go b/pkg/metrics/export.go index d340a6f1..b5a6c659 100644 --- a/pkg/metrics/export.go +++ b/pkg/metrics/export.go @@ -37,28 +37,32 @@ var logMutex sync.Mutex func init() { logDuration = time.Minute - stopLogging = make(chan struct{}) + stopLogging = make(chan struct{}, 1) // doesn't block } // Enable metrics logging with the given time duration. +// This function should not be called again before disable logging. func EnableLogging() { logMutex.Lock() defer logMutex.Unlock() if logTicker == nil { logTicker = time.NewTicker(logDuration) - go logMetricsLoop() - log.Infof("enabled metrics logging with duration %v", logDuration) + } else { + logTicker.Reset(logDuration) } + go logMetricsLoop() + log.Infof("enabled metrics logging with duration %v", logDuration) } // Disable metrics logging. func DisableLogging() { logMutex.Lock() defer logMutex.Unlock() - stopLogging <- struct{}{} + if len(stopLogging) == 0 { + stopLogging <- struct{}{} + } if logTicker != nil { logTicker.Stop() - logTicker = nil log.Infof("disabled metrics logging") } } diff --git a/pkg/metrics/export_test.go b/pkg/metrics/export_test.go index cd9a2f2a..6d84e9da 100644 --- a/pkg/metrics/export_test.go +++ b/pkg/metrics/export_test.go @@ -20,8 +20,26 @@ import ( "os" "path/filepath" "testing" + "time" ) +func TestEnableAndDisableLogging(t *testing.T) { + if err := SetLoggingDuration(10 * time.Millisecond); err != nil { + t.Fatalf("SetLoggingDuration() failed: %v", err) + } + EnableLogging() + time.Sleep(50 * time.Millisecond) // Allow the log metrics loop to run. + DisableLogging() + + // Disable logging is idempotent. + DisableLogging() + DisableLogging() + + // Can enable and disable logging again. + EnableLogging() + DisableLogging() +} + func TestMetricsDump(t *testing.T) { dumpPath := filepath.Join(t.TempDir(), "metrics.pb") SetMetricsDumpFilePath(dumpPath) diff --git a/pkg/metrics/metricspb/metrics.pb.go b/pkg/metrics/metricspb/metrics.pb.go index d86f5329..8762e9ad 100644 --- a/pkg/metrics/metricspb/metrics.pb.go +++ b/pkg/metrics/metricspb/metrics.pb.go @@ -426,10 +426,11 @@ var file_metrics_proto_rawDesc = []byte{ 0x55, 0x50, 0x5f, 0x54, 0x4f, 0x5f, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x5f, 0x54, 0x4f, 0x5f, 0x48, 0x4f, 0x55, 0x52, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x55, 0x50, 0x5f, 0x54, - 0x4f, 0x5f, 0x44, 0x41, 0x59, 0x10, 0x04, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x4f, 0x5f, 0x44, 0x41, 0x59, 0x10, 0x04, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, 0x2f, 0x6d, 0x69, 0x65, - 0x72, 0x75, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x75, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/metrics/proto/metrics.proto b/pkg/metrics/proto/metrics.proto index ebf76b21..7bab2961 100644 --- a/pkg/metrics/proto/metrics.proto +++ b/pkg/metrics/proto/metrics.proto @@ -17,7 +17,7 @@ syntax = "proto3"; package metrics; -option go_package = "github.com/enfein/mieru/pkg/metrics/metricspb"; +option go_package = "github.com/enfein/mieru/v3/pkg/metrics/metricspb"; message AllMetrics { repeated MetricGroup groups = 1; diff --git a/pkg/socks5/auth.go b/pkg/socks5/auth.go index 199ef16d..73a182c6 100644 --- a/pkg/socks5/auth.go +++ b/pkg/socks5/auth.go @@ -20,6 +20,7 @@ import ( "io" "net" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" "github.com/enfein/mieru/v3/pkg/util" ) @@ -67,7 +68,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error { HandshakeErrors.Add(1) return fmt.Errorf("get socks version failed: %w", err) } - if version[0] != socks5Version { + if version[0] != constant.Socks5Version { HandshakeErrors.Add(1) return fmt.Errorf("unsupported socks version: %v", version) } @@ -102,7 +103,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error { if !requestNoAuth && !requestUserPassAuth { HandshakeErrors.Add(1) - if _, err := conn.Write([]byte{socks5Version, noAcceptableAuth}); err != nil { + if _, err := conn.Write([]byte{constant.Socks5Version, noAcceptableAuth}); err != nil { return fmt.Errorf("write authentication response (no acceptable methods) failed: %w", err) } return fmt.Errorf("socks5 client provided authentication is not supported by socks5 server") @@ -113,7 +114,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error { HandshakeErrors.Add(1) return fmt.Errorf("socks5 client requested no authentication, but user and password are required by socks5 server") } - if _, err := conn.Write([]byte{socks5Version, noAuth}); err != nil { + if _, err := conn.Write([]byte{constant.Socks5Version, noAuth}); err != nil { HandshakeErrors.Add(1) return fmt.Errorf("write authentication response (no authentication required) failed: %w", err) } @@ -125,7 +126,7 @@ func (s *Server) handleAuthentication(conn net.Conn) error { } // Tell the client to use user password authentication. - if _, err := conn.Write([]byte{socks5Version, userPassAuth}); err != nil { + if _, err := conn.Write([]byte{constant.Socks5Version, userPassAuth}); err != nil { HandshakeErrors.Add(1) return fmt.Errorf("write user password authentication request failed: %w", err) } @@ -186,7 +187,7 @@ func (s *Server) dialWithAuthentication(proxyConn net.Conn, auth *appctlpb.Auth) if auth == nil || auth.GetUser() == "" || auth.GetPassword() == "" { // No authentication required. - if _, err := proxyConn.Write([]byte{socks5Version, 1, noAuth}); err != nil { + if _, err := proxyConn.Write([]byte{constant.Socks5Version, 1, noAuth}); err != nil { HandshakeErrors.Add(1) proxyConn.Close() return fmt.Errorf("failed to write socks5 authentication header to egress proxy: %w", err) @@ -198,14 +199,14 @@ func (s *Server) dialWithAuthentication(proxyConn net.Conn, auth *appctlpb.Auth) proxyConn.Close() return fmt.Errorf("failed to read socks5 authentication response from egress proxy: %w", err) } - if resp[0] != socks5Version || resp[1] != noAuth { + if resp[0] != constant.Socks5Version || resp[1] != noAuth { HandshakeErrors.Add(1) proxyConn.Close() return fmt.Errorf("got unexpected socks5 authentication response from egress proxy: %v", resp) } } else { // User password authentication. - if _, err := proxyConn.Write([]byte{socks5Version, 1, userPassAuth}); err != nil { + if _, err := proxyConn.Write([]byte{constant.Socks5Version, 1, userPassAuth}); err != nil { HandshakeErrors.Add(1) proxyConn.Close() return fmt.Errorf("failed to write socks5 authentication header to egress proxy: %w", err) @@ -217,7 +218,7 @@ func (s *Server) dialWithAuthentication(proxyConn net.Conn, auth *appctlpb.Auth) proxyConn.Close() return fmt.Errorf("failed to read socks5 authentication response from egress proxy: %w", err) } - if resp[0] != socks5Version || resp[1] != userPassAuth { + if resp[0] != constant.Socks5Version || resp[1] != userPassAuth { HandshakeErrors.Add(1) proxyConn.Close() return fmt.Errorf("got unexpected socks5 authentication response from egress proxy: %v", resp) diff --git a/pkg/socks5/client.go b/pkg/socks5/client.go index 025165d9..d9ebbdd9 100644 --- a/pkg/socks5/client.go +++ b/pkg/socks5/client.go @@ -12,6 +12,7 @@ import ( "strconv" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/util" ) @@ -27,7 +28,7 @@ type Client struct { // Argument proxyURI should be in the format: "socks5://user:password@127.0.0.1:1080?timeout=5s". // Only socks5 protocol is supported. func Dial(proxyURI string, cmdType byte) func(string, string) (net.Conn, error) { - if cmdType != ConnectCmd && cmdType != BindCmd && cmdType != UDPAssociateCmd { + if cmdType != constant.Socks5ConnectCmd && cmdType != constant.Socks5BindCmd && cmdType != constant.Socks5UDPAssociateCmd { return dialError(fmt.Errorf("command type %d is invalid", cmdType)) } cfg, err := parse(proxyURI) @@ -48,7 +49,7 @@ func DialSocks5Proxy(c *Client) func(string, string) (net.Conn, *net.UDPConn, *n if c.Host == "" { return dialErrorLong(fmt.Errorf("socks5 client configuration has no proxy host")) } - if c.CmdType != ConnectCmd && c.CmdType != BindCmd && c.CmdType != UDPAssociateCmd { + if c.CmdType != constant.Socks5ConnectCmd && c.CmdType != constant.Socks5BindCmd && c.CmdType != constant.Socks5UDPAssociateCmd { return dialErrorLong(fmt.Errorf("socks5 client configuration command type %v is invalid", c.CmdType)) } return func(_, targetAddr string) (net.Conn, *net.UDPConn, *net.UDPAddr, error) { @@ -60,12 +61,12 @@ func DialSocks5Proxy(c *Client) func(string, string) (net.Conn, *net.UDPConn, *n func TransceiveUDPPacket(conn *net.UDPConn, proxyAddr, dstAddr *net.UDPAddr, payload []byte) ([]byte, error) { header := []byte{0, 0, 0} if dstAddr.IP.To4() != nil { - header = append(header, ipv4Address) + header = append(header, constant.Socks5IPv4Address) header = append(header, dstAddr.IP.To4()...) header = append(header, byte(dstAddr.Port>>8)) header = append(header, byte(dstAddr.Port)) } else { - header = append(header, ipv6Address) + header = append(header, constant.Socks5IPv6Address) header = append(header, dstAddr.IP.To16()...) header = append(header, byte(dstAddr.Port>>8)) header = append(header, byte(dstAddr.Port)) @@ -85,10 +86,10 @@ func TransceiveUDPPacket(conn *net.UDPConn, proxyAddr, dstAddr *net.UDPAddr, pay if n <= 10 { return nil, fmt.Errorf("UDP associate response is too short") } - if buf[3] == ipv4Address { + if buf[3] == constant.Socks5IPv4Address { // Header length is 10 bytes. return buf[10:n], nil - } else if buf[3] == ipv6Address { + } else if buf[3] == constant.Socks5IPv6Address { // Header length is 22 bytes. return buf[22:n], nil } else { @@ -133,7 +134,7 @@ func (c *Client) dialSocks5Long(targetAddr string) (conn net.Conn, udpConn *net. // Prepare the first request. var req bytes.Buffer - version := byte(socks5Version) + version := byte(constant.Socks5Version) method := byte(noAuth) if c.Credential != nil { method = userPassAuth @@ -190,7 +191,7 @@ func (c *Client) dialSocks5Long(targetAddr string) (conn net.Conn, udpConn *net. req.Reset() req.Write([]byte{ - socks5Version, + constant.Socks5Version, c.CmdType, 0, // reserved, must be zero }) @@ -198,17 +199,17 @@ func (c *Client) dialSocks5Long(targetAddr string) (conn net.Conn, udpConn *net. hostIP := net.ParseIP(host) if hostIP == nil { // Domain name. - req.Write([]byte{fqdnAddress, byte(len(host))}) + req.Write([]byte{constant.Socks5FQDNAddress, byte(len(host))}) req.Write([]byte(host)) } else { hostIPv4 := hostIP.To4() if hostIPv4 != nil { // IPv4 - req.Write([]byte{ipv4Address}) + req.Write([]byte{constant.Socks5IPv4Address}) req.Write(hostIPv4) } else { // IPv6 - req.Write([]byte{ipv6Address}) + req.Write([]byte{constant.Socks5IPv6Address}) req.Write(hostIP) } } @@ -227,14 +228,14 @@ func (c *Client) dialSocks5Long(targetAddr string) (conn net.Conn, udpConn *net. return nil, nil, nil, fmt.Errorf("socks5 connection is not successful") } - if c.CmdType == UDPAssociateCmd { + if c.CmdType == constant.Socks5UDPAssociateCmd { // Get the endpoint to relay UDP packets. var ip net.IP switch resp[3] { - case ipv4Address: + case constant.Socks5IPv4Address: ip = net.IP(resp[4:8]) port = uint16(resp[8])<<8 + uint16(resp[9]) - case ipv6Address: + case constant.Socks5IPv6Address: if len(resp) < 22 { return nil, nil, nil, fmt.Errorf("server response is too short") } diff --git a/pkg/socks5/client_test.go b/pkg/socks5/client_test.go index d7cabe52..51136fb3 100644 --- a/pkg/socks5/client_test.go +++ b/pkg/socks5/client_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/testtool" "github.com/enfein/mieru/v3/pkg/util" ) @@ -50,7 +51,7 @@ func TestSocks5Anonymous(t *testing.T) { } newTestSocksServer(port) - dialSocksProxy := Dial(fmt.Sprintf("socks5://127.0.0.1:%d?timeout=5s", port), ConnectCmd) + dialSocksProxy := Dial(fmt.Sprintf("socks5://127.0.0.1:%d?timeout=5s", port), constant.Socks5ConnectCmd) tr := &http.Transport{Dial: dialSocksProxy} httpClient := &http.Client{Transport: tr} resp, err := httpClient.Get(fmt.Sprintf("http://localhost" + httpTestServer.Addr)) diff --git a/pkg/socks5/http2socks.go b/pkg/socks5/http2socks.go index 1cc35772..1d15a5b9 100644 --- a/pkg/socks5/http2socks.go +++ b/pkg/socks5/http2socks.go @@ -24,6 +24,7 @@ import ( "sync" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/log" "github.com/enfein/mieru/v3/pkg/metrics" "github.com/enfein/mieru/v3/pkg/util" @@ -85,7 +86,7 @@ func (p *HTTPProxy) ServeHTTP(res http.ResponseWriter, req *http.Request) { } // Dialer to socks5 server. - dialFunc := Dial(p.ProxyURI, ConnectCmd) + dialFunc := Dial(p.ProxyURI, constant.Socks5ConnectCmd) if req.Method == http.MethodConnect { // HTTPS diff --git a/pkg/socks5/request.go b/pkg/socks5/request.go index f01d0f7d..ed127304 100644 --- a/pkg/socks5/request.go +++ b/pkg/socks5/request.go @@ -1,6 +1,7 @@ package socks5 import ( + "bytes" "context" "fmt" "io" @@ -10,25 +11,13 @@ import ( "sync" "sync/atomic" + "github.com/enfein/mieru/v3/apis/constant" + "github.com/enfein/mieru/v3/apis/model" "github.com/enfein/mieru/v3/pkg/log" "github.com/enfein/mieru/v3/pkg/stderror" "github.com/enfein/mieru/v3/pkg/util" ) -// socks5 command types. -const ( - ConnectCmd byte = 1 - BindCmd byte = 2 - UDPAssociateCmd byte = 3 -) - -// socks5 address types. -const ( - ipv4Address byte = 1 - fqdnAddress byte = 3 - ipv6Address byte = 4 -) - // socks5 error types. const ( successReply byte = 0 @@ -42,35 +31,6 @@ const ( addrTypeNotSupported byte = 8 ) -var ( - errUnrecognizedAddrType = fmt.Errorf("unrecognized address type") -) - -// AddrSpec is used to return the target AddrSpec -// which may be specified as IPv4, IPv6, or a FQDN. -type AddrSpec struct { - FQDN string - IP net.IP - Port int - Raw []byte -} - -func (a *AddrSpec) String() string { - if a.FQDN != "" { - return fmt.Sprintf("%s (%s):%d", a.FQDN, a.IP, a.Port) - } - return fmt.Sprintf("%s:%d", a.IP, a.Port) -} - -// Address returns a string suitable to dial; prefer returning IP-based -// address, fallback to FQDN -func (a *AddrSpec) Address() string { - if len(a.IP) != 0 { - return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port)) - } - return net.JoinHostPort(a.FQDN, strconv.Itoa(a.Port)) -} - // A Request represents request received by a server. type Request struct { // Protocol version. @@ -78,7 +38,7 @@ type Request struct { // Requested command. Command uint8 // AddrSpec of the desired destination. - DestAddr *AddrSpec + DstAddr *model.AddrSpec // Raw request bytes. Raw []byte } @@ -96,52 +56,56 @@ func (s *Server) newRequest(conn io.Reader) (*Request, error) { } // Ensure we are compatible. - if header[0] != socks5Version { + if header[0] != constant.Socks5Version { return nil, fmt.Errorf("unsupported command version: %v", header[0]) } // Read in the destination address. - dest, err := readAddrSpec(conn) - if err != nil { + dst := &model.AddrSpec{} + if err := dst.ReadFromSocks5(conn); err != nil { + return nil, err + } + var dstBuf bytes.Buffer + if err := dst.WriteToSocks5(&dstBuf); err != nil { return nil, err } return &Request{ - Version: socks5Version, - Command: header[1], - DestAddr: dest, - Raw: append(header, dest.Raw...), + Version: constant.Socks5Version, + Command: header[1], + DstAddr: dst, + Raw: append(header, dstBuf.Bytes()...), }, nil } // handleRequest is used for request processing after authentication. func (s *Server) handleRequest(ctx context.Context, req *Request, conn io.ReadWriteCloser) error { // Resolve the address if we have a FQDN. - dest := req.DestAddr - if dest.FQDN != "" { - addr, err := s.config.Resolver.LookupIP(ctx, dest.FQDN) + dst := req.DstAddr + if dst.FQDN != "" { + addr, err := s.config.Resolver.LookupIP(ctx, dst.FQDN) if err != nil { DNSResolveErrors.Add(1) if err := sendReply(conn, hostUnreachable, nil); err != nil { return fmt.Errorf("failed to send reply: %w", err) } - return fmt.Errorf("failed to resolve destination %q: %w", dest.FQDN, err) + return fmt.Errorf("failed to resolve destination %q: %w", dst.FQDN, err) } - dest.IP = addr + dst.IP = addr } // Return error if access local destination is not allowed. - if !s.config.AllowLocalDestination && isLocalhostDest(req) { + if !s.config.AllowLocalDestination && isLocalhostDst(req) { return fmt.Errorf("access to localhost resource via proxy is not allowed") } // Switch on the command. switch req.Command { - case ConnectCmd: + case constant.Socks5ConnectCmd: return s.handleConnect(ctx, req, conn) - case BindCmd: + case constant.Socks5BindCmd: return s.handleBind(ctx, req, conn) - case UDPAssociateCmd: + case constant.Socks5UDPAssociateCmd: return s.handleAssociate(ctx, req, conn) default: UnsupportedCommandErrors.Add(1) @@ -155,7 +119,7 @@ func (s *Server) handleRequest(ctx context.Context, req *Request, conn io.ReadWr // handleConnect is used to handle a connect command. func (s *Server) handleConnect(ctx context.Context, req *Request, conn io.ReadWriteCloser) error { var d net.Dialer - target, err := d.DialContext(ctx, "tcp", req.DestAddr.Address()) + target, err := d.DialContext(ctx, "tcp", req.DstAddr.Address()) if err != nil { msg := err.Error() var resp uint8 @@ -172,13 +136,13 @@ func (s *Server) handleConnect(ctx context.Context, req *Request, conn io.ReadWr if err := sendReply(conn, resp, nil); err != nil { return fmt.Errorf("failed to send reply: %w", err) } - return fmt.Errorf("connect to %v failed: %w", req.DestAddr, err) + return fmt.Errorf("connect to %v failed: %w", req.DstAddr, err) } defer target.Close() // Send success. local := target.LocalAddr().(*net.TCPAddr) - bind := AddrSpec{IP: local.IP, Port: local.Port} + bind := model.AddrSpec{IP: local.IP, Port: local.Port} if err := sendReply(conn, successReply, &bind); err != nil { HandshakeErrors.Add(1) return fmt.Errorf("failed to send reply: %w", err) @@ -188,7 +152,7 @@ func (s *Server) handleConnect(ctx context.Context, req *Request, conn io.ReadWr } // handleBind is used to handle a bind command. -func (s *Server) handleBind(ctx context.Context, req *Request, conn io.ReadWriteCloser) error { +func (s *Server) handleBind(_ context.Context, _ *Request, conn io.ReadWriteCloser) error { UnsupportedCommandErrors.Add(1) if err := sendReply(conn, commandNotSupported, nil); err != nil { HandshakeErrors.Add(1) @@ -198,7 +162,7 @@ func (s *Server) handleBind(ctx context.Context, req *Request, conn io.ReadWrite } // handleAssociate is used to handle a associate command. -func (s *Server) handleAssociate(ctx context.Context, req *Request, conn io.ReadWriteCloser) error { +func (s *Server) handleAssociate(_ context.Context, _ *Request, conn io.ReadWriteCloser) error { // Create a UDP listener on a random port. // All the requests associated to this connection will go through this port. udpListenerAddr, err := net.ResolveUDPAddr("udp", util.MaybeDecorateIPv6(util.AllIPAddr())+":0") @@ -226,7 +190,7 @@ func (s *Server) handleAssociate(ctx context.Context, req *Request, conn io.Read UDPAssociateErrors.Add(1) return fmt.Errorf("strconv.Atoi() failed: %w", err) } - bind := AddrSpec{IP: net.IP{0, 0, 0, 0}, Port: udpPort} + bind := model.AddrSpec{IP: net.IP{0, 0, 0, 0}, Port: udpPort} if err := sendReply(conn, successReply, &bind); err != nil { HandshakeErrors.Add(1) return fmt.Errorf("failed to send reply: %w", err) @@ -392,7 +356,7 @@ func (s *Server) proxySocks5AuthReq(conn, proxyConn net.Conn) error { if _, err := io.ReadFull(conn, version); err != nil { return fmt.Errorf("failed to get version byte: %w", err) } - if version[0] != socks5Version { + if version[0] != constant.Socks5Version { return fmt.Errorf("unsupported SOCKS version: %v", version) } nMethods := []byte{0} @@ -441,15 +405,15 @@ func (s *Server) proxySocks5ConnReq(conn, proxyConn net.Conn) (*net.UDPConn, err var reqFQDNLen []byte var dstAddr []byte switch reqAddrType { - case ipv4Address: + case constant.Socks5IPv4Address: dstAddr = make([]byte, 6) - case fqdnAddress: + case constant.Socks5FQDNAddress: reqFQDNLen = []byte{0} if _, err := io.ReadFull(conn, reqFQDNLen); err != nil { return nil, fmt.Errorf("failed to get FQDN length: %w", err) } dstAddr = make([]byte, reqFQDNLen[0]+2) - case ipv6Address: + case constant.Socks5IPv6Address: dstAddr = make([]byte, 18) default: return nil, fmt.Errorf("unsupported address type: %d", reqAddrType) @@ -476,15 +440,15 @@ func (s *Server) proxySocks5ConnReq(conn, proxyConn net.Conn) (*net.UDPConn, err var respFQDNLen []byte var bindAddr []byte switch respAddrType { - case ipv4Address: + case constant.Socks5IPv4Address: bindAddr = make([]byte, 6) - case fqdnAddress: + case constant.Socks5FQDNAddress: respFQDNLen = []byte{0} if _, err := io.ReadFull(proxyConn, respFQDNLen); err != nil { return nil, fmt.Errorf("failed to get FQDN length: %w", err) } bindAddr = make([]byte, respFQDNLen[0]+2) - case ipv6Address: + case constant.Socks5IPv6Address: bindAddr = make([]byte, 18) default: return nil, fmt.Errorf("unsupported address type: %d", respAddrType) @@ -498,7 +462,7 @@ func (s *Server) proxySocks5ConnReq(conn, proxyConn net.Conn) (*net.UDPConn, err connResp = append(connResp, bindAddr...) var udpConn *net.UDPConn - if cmd == UDPAssociateCmd { + if cmd == constant.Socks5UDPAssociateCmd { // Create a UDP listener on a random port in IPv4 network. var err error udpAddr := &net.UDPAddr{IP: net.IP{0, 0, 0, 0}, Port: 0} @@ -529,111 +493,33 @@ func (s *Server) proxySocks5ConnReq(conn, proxyConn net.Conn) (*net.UDPConn, err return udpConn, nil } -// readAddrSpec is used to read AddrSpec. -// Expects an address type byte, follwed by the address and port. -func readAddrSpec(r io.Reader) (*AddrSpec, error) { - d := &AddrSpec{} - - // Get the address type. - addrType := []byte{0} - if _, err := io.ReadFull(r, addrType); err != nil { - return nil, err - } - d.Raw = append(d.Raw, addrType...) - - // Handle on a per type basis. - switch addrType[0] { - case ipv4Address: - addr := make([]byte, 4) - if _, err := io.ReadFull(r, addr); err != nil { - return nil, err - } - d.IP = net.IP(addr) - d.Raw = append(d.Raw, addr...) - case ipv6Address: - addr := make([]byte, 16) - if _, err := io.ReadFull(r, addr); err != nil { - return nil, err - } - d.IP = net.IP(addr) - d.Raw = append(d.Raw, addr...) - case fqdnAddress: - addrLen := []byte{0} - if _, err := io.ReadFull(r, addrLen); err != nil { - return nil, err - } - fqdn := make([]byte, int(addrLen[0])) - if _, err := io.ReadFull(r, fqdn); err != nil { - return nil, err +// sendReply is used to send a reply message. +func sendReply(w io.Writer, resp uint8, addr *model.AddrSpec) error { + if addr == nil { + // Assume it is an unspecified IPv4 address. + addr = &model.AddrSpec{ + IP: net.IPv4(0, 0, 0, 0), } - d.FQDN = string(fqdn) - d.Raw = append(d.Raw, addrLen...) - d.Raw = append(d.Raw, fqdn...) - default: - return nil, errUnrecognizedAddrType } - // Read the port number. - port := []byte{0, 0} - if _, err := io.ReadFull(r, port); err != nil { - return nil, err + var buf bytes.Buffer + buf.WriteByte(constant.Socks5Version) + buf.WriteByte(resp) + buf.WriteByte(0) // reserved byte + if err := addr.WriteToSocks5(&buf); err != nil { + return err } - d.Port = (int(port[0]) << 8) | int(port[1]) - d.Raw = append(d.Raw, port...) - return d, nil -} - -// sendReply is used to send a reply message. -func sendReply(w io.Writer, resp uint8, addr *AddrSpec) error { - // Format the address. - var addrType uint8 - var addrBody []byte - var addrPort uint16 - switch { - case addr == nil: - addrType = ipv4Address - addrBody = []byte{0, 0, 0, 0} - addrPort = 0 - - case addr.FQDN != "": - addrType = fqdnAddress - addrBody = append([]byte{byte(len(addr.FQDN))}, addr.FQDN...) - addrPort = uint16(addr.Port) - - case addr.IP.To4() != nil: - addrType = ipv4Address - addrBody = []byte(addr.IP.To4()) - addrPort = uint16(addr.Port) - - case addr.IP.To16() != nil: - addrType = ipv6Address - addrBody = []byte(addr.IP.To16()) - addrPort = uint16(addr.Port) - - default: - return fmt.Errorf("failed to format address: %v", addr) - } - - // Format the message. - msg := make([]byte, 6+len(addrBody)) - msg[0] = socks5Version - msg[1] = resp - msg[2] = 0 // reserved byte - msg[3] = addrType - copy(msg[4:], addrBody) - msg[4+len(addrBody)] = byte(addrPort >> 8) - msg[4+len(addrBody)+1] = byte(addrPort & 0xff) // Send the message. - _, err := w.Write(msg) + _, err := w.Write(buf.Bytes()) return err } -func isLocalhostDest(req *Request) bool { - if req == nil || req.DestAddr == nil { +func isLocalhostDst(req *Request) bool { + if req == nil || req.DstAddr == nil { return false } - if req.DestAddr.FQDN == "localhost" || req.DestAddr.IP.IsLoopback() { + if req.DstAddr.FQDN == "localhost" || req.DstAddr.IP.IsLoopback() { return true } return false diff --git a/pkg/socks5/request_test.go b/pkg/socks5/request_test.go index 2fd4dcdc..3521b32c 100644 --- a/pkg/socks5/request_test.go +++ b/pkg/socks5/request_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/stderror" "github.com/enfein/mieru/v3/pkg/testtool" ) @@ -98,7 +99,7 @@ func TestRequestUnsupportedCommand(t *testing.T) { resp []byte }{ { - []byte{5, BindCmd, 0, 1, 127, 0, 0, 1, 0, 1}, + []byte{5, constant.Socks5BindCmd, 0, 1, 127, 0, 0, 1, 0, 1}, []byte{5, commandNotSupported, 0, 1, 0, 0, 0, 0, 0, 0}, }, } diff --git a/pkg/socks5/socks5.go b/pkg/socks5/socks5.go index b4a46a5b..fee166ed 100644 --- a/pkg/socks5/socks5.go +++ b/pkg/socks5/socks5.go @@ -8,6 +8,7 @@ import ( "strconv" "time" + "github.com/enfein/mieru/v3/apis/model" "github.com/enfein/mieru/v3/pkg/appctl/appctlpb" "github.com/enfein/mieru/v3/pkg/egress" "github.com/enfein/mieru/v3/pkg/log" @@ -17,11 +18,6 @@ import ( "github.com/enfein/mieru/v3/pkg/util" ) -const ( - // socks5 version number. - socks5Version byte = 5 -) - var ( HandshakeErrors = metrics.RegisterMetric("socks5", "HandshakeErrors", metrics.COUNTER) DNSResolveErrors = metrics.RegisterMetric("socks5", "DNSResolveErrors", metrics.COUNTER) @@ -231,7 +227,7 @@ func (s *Server) serverServeConn(conn net.Conn) error { request, err := s.newRequest(conn) if err != nil { HandshakeErrors.Add(1) - if errors.Is(err, errUnrecognizedAddrType) { + if errors.Is(err, model.ErrUnrecognizedAddrType) { if err := sendReply(conn, addrTypeNotSupported, nil); err != nil { return fmt.Errorf("failed to send reply: %w", err) } diff --git a/pkg/socks5/socks5_test.go b/pkg/socks5/socks5_test.go index 80ab700b..3134fd5a 100644 --- a/pkg/socks5/socks5_test.go +++ b/pkg/socks5/socks5_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/util" ) @@ -87,8 +88,8 @@ func TestSocks5Connect(t *testing.T) { // Verify response from socks server. want := []byte{ - socks5Version, noAuth, - socks5Version, 0, 0, 1, + constant.Socks5Version, noAuth, + constant.Socks5Version, 0, 0, 1, 127, 0, 0, 1, 0, 0, 'p', 'o', 'n', 'g', @@ -192,8 +193,8 @@ func TestSocks5UDPAssociation(t *testing.T) { // Verify response from socks server. want := []byte{ - socks5Version, noAuth, - socks5Version, 0, 0, 1, + constant.Socks5Version, noAuth, + constant.Socks5Version, 0, 0, 1, 0, 0, 0, 0, 0, 0, } diff --git a/test/cmd/sockshttpclient/sockshttpclient.go b/test/cmd/sockshttpclient/sockshttpclient.go index 9ffec1ea..79c7d3e5 100644 --- a/test/cmd/sockshttpclient/sockshttpclient.go +++ b/test/cmd/sockshttpclient/sockshttpclient.go @@ -31,6 +31,7 @@ import ( "sync/atomic" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/log" "github.com/enfein/mieru/v3/pkg/socks5" ) @@ -133,7 +134,7 @@ func main() { if *proxyMode == Socks5ProxyMode { socksDialer := socks5.DialSocks5Proxy(&socks5.Client{ Host: *localProxyHost + ":" + strconv.Itoa(*localProxyPort), - CmdType: socks5.ConnectCmd, + CmdType: constant.Socks5ConnectCmd, }) conn, _, _, err = socksDialer("tcp", *dstHost+":"+strconv.Itoa(*dstPort)) } else if *proxyMode == HTTPProxyMode { @@ -210,7 +211,7 @@ func CreateNewConnAndDoRequest(seq int, proxyMode string) { if proxyMode == Socks5ProxyMode { socksDialer := socks5.DialSocks5Proxy(&socks5.Client{ Host: *localProxyHost + ":" + strconv.Itoa(*localProxyPort), - CmdType: socks5.ConnectCmd, + CmdType: constant.Socks5ConnectCmd, }) conn, _, _, err = socksDialer("tcp", *dstHost+":"+strconv.Itoa(*dstPort)) } else if proxyMode == HTTPProxyMode { diff --git a/test/cmd/socksudpclient/socksudpclient.go b/test/cmd/socksudpclient/socksudpclient.go index a725742e..2782ec98 100644 --- a/test/cmd/socksudpclient/socksudpclient.go +++ b/test/cmd/socksudpclient/socksudpclient.go @@ -24,6 +24,7 @@ import ( "strconv" "time" + "github.com/enfein/mieru/v3/apis/constant" "github.com/enfein/mieru/v3/pkg/log" "github.com/enfein/mieru/v3/pkg/socks5" "github.com/enfein/mieru/v3/pkg/testtool" @@ -80,7 +81,7 @@ func main() { func CreateNewConnAndDoRequest(nRequest int, dstAddr *net.UDPAddr) { socksDialer := socks5.DialSocks5Proxy(&socks5.Client{ Host: *localProxyHost + ":" + strconv.Itoa(*localProxyPort), - CmdType: socks5.UDPAssociateCmd, + CmdType: constant.Socks5UDPAssociateCmd, }) ctrlConn, udpConn, proxyAddr, err := socksDialer("tcp", *dstHost+":"+strconv.Itoa(*dstPort)) if err != nil {