diff --git a/Makefile.am b/Makefile.am index 76dbaa6..89c812e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,7 +25,12 @@ minilbctl_SOURCES = \ cmd/minilbctl/main.go EXTRA_minilbctl_SOURCES = \ - cmd/minilbctl/service/srvcmd.go + cmd/minilbctl/service/srvcmd.go \ + cmd/minilbctl/forwarder/listforw.go \ + cmd/minilbctl/forwarder/deleteforw.go \ + cmd/minilbctl/forwarder/createforw.go \ + cmd/minilbctl/forwarder/forwcmd.go + minilbctl$(EXEEXT): $(minilbctl_SOURCES) $(EXTRA_minilbctl_SOURCES) $(EXTRA_minilbd_SOURCES) env CGO_ENABLED=0 $(GO) build $(GOFLAGS) -o minilbctl$(EXEEXT) $(minilbctl_SOURCES) diff --git a/Makefile.in b/Makefile.in index b9d0b75..c95cc3c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -242,6 +242,7 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PODMAN = @PODMAN@ +PROTOC = @PROTOC@ ROOT_GROUP = @ROOT_GROUP@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -325,7 +326,11 @@ minilbctl_SOURCES = \ cmd/minilbctl/main.go EXTRA_minilbctl_SOURCES = \ - cmd/minilbctl/service/srvcmd.go + cmd/minilbctl/service/srvcmd.go \ + cmd/minilbctl/forwarder/listforw.go \ + cmd/minilbctl/forwarder/deleteforw.go \ + cmd/minilbctl/forwarder/createforw.go \ + cmd/minilbctl/forwarder/forwcmd.go minilbd_SOURCES = \ cmd/minilbd/main.go diff --git a/app/config/variant.go b/app/config/variant.go index 262e47e..403740b 100644 --- a/app/config/variant.go +++ b/app/config/variant.go @@ -1,9 +1,9 @@ package config const ( - confdirPath = "/home/ziggi/Projects/gserver/etc/minilb" - rundirPath = "/home/ziggi/Projects/gserver/tmp/run" - logdirPath = "/home/ziggi/Projects/gserver/tmp/log" - datadirPath = "/home/ziggi/Projects/gserver/tmp/data" + confdirPath = "/home/ziggi/Projects/minilb/etc/minilb" + rundirPath = "/home/ziggi/Projects/minilb/tmp/run" + logdirPath = "/home/ziggi/Projects/minilb/tmp/log" + datadirPath = "/home/ziggi/Projects/minilb/tmp/data" packageVersion = "0.0.1" ) diff --git a/app/handler/handler.go b/app/handler/handler.go index 121f3d7..c5c4b38 100644 --- a/app/handler/handler.go +++ b/app/handler/handler.go @@ -15,13 +15,13 @@ type HandlerConfig struct { type Handler struct { mlbctl.UnimplementedControlServer - lg *operator.Operator - log *logger.Logger + oper *operator.Operator + log *logger.Logger } func NewHandler(conf *HandlerConfig) *Handler { hand := Handler{ - lg: conf.Operator, + oper: conf.Operator, } hand.log = logger.NewLogger("handler") return &hand diff --git a/app/handler/hello.go b/app/handler/hello.go index c8f1ec8..8f70538 100644 --- a/app/handler/hello.go +++ b/app/handler/hello.go @@ -9,6 +9,6 @@ import ( func (hand *Handler) GetHello(ctx context.Context, req *mlbctl.GetHelloParams) (*mlbctl.GetHelloResult, error) { var err error hand.log.Debugf("Handle getHello request") - res, err := hand.lg.GetHello(ctx, req) + res, err := hand.oper.GetHello(ctx, req) return res, err } diff --git a/app/handler/proxy.go b/app/handler/proxy.go new file mode 100644 index 0000000..2600b09 --- /dev/null +++ b/app/handler/proxy.go @@ -0,0 +1,25 @@ +package handler + +import ( + "context" + + "helmet/pkg/mlbctl" +) + +func (hand *Handler) ListForwarders(ctx context.Context, req *mlbctl.ListForwardersParams) (*mlbctl.ListForwardersResult, error) { + var err error + res, err := hand.oper.ListForwarders(ctx, req) + return res, err +} + +func (hand *Handler) CreateForwarder(ctx context.Context, req *mlbctl.CreateForwarderParams) (*mlbctl.CreateForwarderResult, error) { + var err error + res, err := hand.oper.CreateForwarder(ctx, req) + return res, err +} + +func (hand *Handler) DeleteForwarder(ctx context.Context, req *mlbctl.DeleteForwarderParams) (*mlbctl.DeleteForwarderResult, error) { + var err error + res, err := hand.oper.DeleteForwarder(ctx, req) + return res, err +} diff --git a/app/operator/oper.go b/app/operator/oper.go index 67b5b34..1dc6efc 100644 --- a/app/operator/oper.go +++ b/app/operator/oper.go @@ -4,6 +4,7 @@ import ( "helmet/app/logger" "helmet/app/config" + "helmet/app/rproxy" ) type OperatorConfig struct { @@ -13,13 +14,15 @@ type OperatorConfig struct { type Operator struct { log *logger.Logger auths []config.Auth + proxy *rproxy.Proxy } func NewOperator(conf *OperatorConfig) (*Operator, error) { var err error - lg := &Operator{ + oper := &Operator{ auths: conf.Auths, } - lg.log = logger.NewLogger("operator") - return lg, err + oper.log = logger.NewLogger("operator") + oper.proxy = rproxy.NewProxy() + return oper, err } diff --git a/app/operator/proxy.go b/app/operator/proxy.go new file mode 100644 index 0000000..e850b19 --- /dev/null +++ b/app/operator/proxy.go @@ -0,0 +1,44 @@ +package operator + +import ( + "context" + + "helmet/pkg/mlbctl" +) + +func (oper *Operator) ListForwarders(ctx context.Context, params *mlbctl.ListForwardersParams) (*mlbctl.ListForwardersResult, error) { + var err error + + res := &mlbctl.ListForwardersResult{ + Forwarders: make([]*mlbctl.Forwarder, 0), + } + for _, forw := range oper.proxy.Forwarders { + oForw := &mlbctl.Forwarder{ + Lport: forw.Lport, + Dport: forw.Dport, + Destinations: make([]*mlbctl.Destination, 0), + } + for _, dest := range forw.Dests { + oDest := &mlbctl.Destination{ + Address: dest.Address, + } + oForw.Destinations = append(oForw.Destinations, oDest) + } + res.Forwarders = append(res.Forwarders, oForw) + } + return res, err +} + +func (oper *Operator) CreateForwarder(ctx context.Context, params *mlbctl.CreateForwarderParams) (*mlbctl.CreateForwarderResult, error) { + var err error + res := &mlbctl.CreateForwarderResult{} + err = oper.proxy.AddForwarder(ctx, params.Lport, params.Dport, params.Destinations...) + return res, err +} + +func (oper *Operator) DeleteForwarder(ctx context.Context, params *mlbctl.DeleteForwarderParams) (*mlbctl.DeleteForwarderResult, error) { + var err error + res := &mlbctl.DeleteForwarderResult{} + err = oper.proxy.DeleteForwarder(ctx, params.Lport) + return res, err +} diff --git a/app/rproxy/proxy.go b/app/rproxy/proxy.go new file mode 100644 index 0000000..3d0982d --- /dev/null +++ b/app/rproxy/proxy.go @@ -0,0 +1,192 @@ +package rproxy + +import ( + "context" + "errors" + "io" + "log" + "math/rand" + "net" + "strconv" + "sync" +) + +type Proxy struct { + Forwarders []*Forwarder `json:"forwarders" yaml:"forwarders"` + ctx context.Context `json:"-" yaml:"-"` + cancel context.CancelFunc `json:"-" yaml:"-"` + wg sync.WaitGroup `json:"-" yaml:"-"` +} + +func NewProxy() *Proxy { + ctx, cancel := context.WithCancel(context.Background()) + return &Proxy{ + Forwarders: make([]*Forwarder, 0), + ctx: ctx, + cancel: cancel, + } +} + +func (bal *Proxy) AddForwarder(ctx context.Context, lport, dport uint32, addrs ...string) error { + var err error + forw, err := NewForwarder(ctx, lport, dport, addrs...) + if err != nil { + return err + } + bal.Forwarders = append(bal.Forwarders, forw) + bal.wg.Add(1) + go forw.Listen(&bal.wg) + return err +} + +func (bal *Proxy) DeleteForwarder(ctx context.Context, lport uint32) error { + var err error + forwarders := make([]*Forwarder, 0) + for _, forw := range bal.Forwarders { + if forw.Lport == lport { + forw.Stop() + continue + } + forwarders = append(forwarders, forw) + } + bal.Forwarders = forwarders + return err +} + +func (bal *Proxy) Start() error { + var err error + for _, forw := range bal.Forwarders { + bal.wg.Add(1) + go forw.Listen(&bal.wg) + } + bal.wg.Wait() + return err +} + +func (bal *Proxy) Stop() error { + var err error + for _, forw := range bal.Forwarders { + forw.Stop() + } + return err +} + +type Forwarder struct { + listen net.Listener `json:"-" yaml:"-"` + ctx context.Context `json:"-" yaml:"-"` + cancel context.CancelFunc `json:"-" yaml:"-"` + Lport uint32 `json:"lport" yaml:"lport"` + Dport uint32 `json:"dport" yaml:"dport"` + Dests []*Destination `json:"dests" yaml:"dests"` +} + +func NewForwarder(ctx context.Context, lport, dport uint32, addrs ...string) (*Forwarder, error) { + ctx, cancel := context.WithCancel(ctx) + forw := &Forwarder{ + Dests: make([]*Destination, 0), + Lport: lport, + Dport: dport, + ctx: ctx, + cancel: cancel, + } + for _, addr := range addrs { + dest := NewDestination(addr) + forw.Dests = append(forw.Dests, dest) + } + port := ":" + strconv.FormatUint(uint64(forw.Lport), 10) + listen, err := net.Listen("tcp", port) + if err != nil { + return forw, err + } + forw.listen = listen + return forw, err +} + +func (forw *Forwarder) Listen(wg *sync.WaitGroup) { + log.Printf("Start listening on %d\n", forw.Lport) + defer wg.Done() + for { + conn, err := forw.listen.Accept() + if err != nil { + log.Printf("Listen err: %v\n", err) + return + } + go forw.handle(forw.ctx, conn) + } +} + +func (forw *Forwarder) Stop() error { + return forw.listen.Close() +} + +func (forw *Forwarder) handle(ctx context.Context, inconn net.Conn) { + log.Printf("Handler on %d started\n", forw.Lport) + defer inconn.Close() + if len(forw.Dests) == 0 { + return + } + addrnum := rand.Uint32() % uint32(len(forw.Dests)) + ipaddr := forw.Dests[addrnum].Address + dstaddr := ipaddr + ":" + strconv.FormatUint(uint64(forw.Dport), 10) + outconn, err := net.Dial("tcp", dstaddr) + if err != nil { + return + } + var wg sync.WaitGroup + wg.Add(1) + go forw.stream(&wg, inconn, outconn) + wg.Add(1) + go forw.stream(&wg, outconn, inconn) + wg.Wait() + log.Printf("Handler on %d stopped\n", forw.Lport) +} + +func (forw *Forwarder) stream(wg *sync.WaitGroup, inconn io.Reader, outconn io.Writer) { + defer wg.Done() + _, err := copy(forw.ctx, outconn, inconn) + if err != nil { + log.Printf("Copy err: %v\n", err) + } +} + +type Destination struct { + Address string `json:"address" yaml:"address"` +} + +func NewDestination(addr string) *Destination { + return &Destination{ + Address: addr, + } +} + +func copy(ctx context.Context, writer io.Writer, reader io.Reader) (int64, error) { + var err error + var size int64 + var halt bool + buffer := make([]byte, 1024*4) + for { + select { + case <-ctx.Done(): + err = errors.New("Break copy by context") + break + default: + } + rsize, err := reader.Read(buffer) + if err == io.EOF { + err = nil + halt = true + } + if err != nil { + return size, err + } + wsize, err := writer.Write(buffer[0:rsize]) + size += int64(wsize) + if err != nil { + return size, err + } + if halt { + break + } + } + return size, err +} diff --git a/app/server/server.go b/app/server/server.go index db809ee..9c394d8 100644 --- a/app/server/server.go +++ b/app/server/server.go @@ -253,8 +253,10 @@ func (srv *Server) Daemonize() error { func (srv *Server) Rotator() { srv.wg.Add(1) + var counter uint64 logFunc := func() { for { + counter += 1 select { case <-srv.ctx.Done(): srv.wg.Done() @@ -262,25 +264,27 @@ func (srv *Server) Rotator() { return default: } - stat, err := srv.logf.Stat() - if err == nil && stat.Size() > srv.conf.LogLimit { - srv.log.Infof("Rotate log file") - countFiles := 3 - for i := 1; i < countFiles; i++ { - nextName := fmt.Sprintf("%s.%d", srv.conf.LogPath, i+1) - prevName := fmt.Sprintf("%s.%d", srv.conf.LogPath, i) - os.Rename(prevName, nextName) - } - os.Rename(srv.conf.LogPath, srv.conf.LogPath+".1") - logFile, err := os.OpenFile(srv.conf.LogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640) - if err == nil { - syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd())) - syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd())) - srv.logf.Close() - srv.logf = logFile + if (counter % 60) == 1 { + stat, err := srv.logf.Stat() + if err == nil && stat.Size() > srv.conf.LogLimit { + srv.log.Infof("Rotate log file") + countFiles := 3 + for i := 1; i < countFiles; i++ { + nextName := fmt.Sprintf("%s.%d", srv.conf.LogPath, i+1) + prevName := fmt.Sprintf("%s.%d", srv.conf.LogPath, i) + os.Rename(prevName, nextName) + } + os.Rename(srv.conf.LogPath, srv.conf.LogPath+".1") + logFile, err := os.OpenFile(srv.conf.LogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640) + if err == nil { + syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd())) + syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd())) + srv.logf.Close() + srv.logf = logFile + } } } - time.Sleep(3 * time.Second) + time.Sleep(1 * time.Second) } } go logFunc() diff --git a/cmd/minilbadm/hash/hashcmd.go b/cmd/minilbadm/hash/hashcmd.go new file mode 100644 index 0000000..fde4f32 --- /dev/null +++ b/cmd/minilbadm/hash/hashcmd.go @@ -0,0 +1,117 @@ +package hash + +import ( + "fmt" + + "helmet/pkg/passwd" + + "github.com/spf13/cobra" + "sigs.k8s.io/yaml" +) + +type Tool struct { + cmd *cobra.Command + createHashParams CreateHashParams + checkHashParams CheckHashParams +} + +func NewTool() *Tool { + tool := &Tool{} + tool.cmd = &cobra.Command{ + Use: "hash", + Short: "Hash opeation", + } + createHashCmd := &cobra.Command{ + Use: "create password", + Args: cobra.ExactArgs(1), + Short: "Create authentification hash", + RunE: tool.CreateHash, + } + checkHashCmd := &cobra.Command{ + Use: "check password hash", + Args: cobra.ExactArgs(2), + Short: "Check authentification hash", + RunE: tool.CheckHash, + } + + tool.cmd.AddCommand(createHashCmd) + tool.cmd.AddCommand(checkHashCmd) + return tool +} + +func (tool *Tool) GetCmd() *cobra.Command { + return tool.cmd +} + +type CreateHashParams struct { + Password string +} +type CreateHashResult struct { + Hash string `json:"hash"` +} + +func (tool *Tool) CreateHash(cmd *cobra.Command, args []string) error { + tool.createHashParams.Password = args[0] + res, err := tool.createHash(&tool.createHashParams) + printResponse(res, err) + return err +} + +func (tool *Tool) createHash(params *CreateHashParams) (*CreateHashResult, error) { + var err error + res := &CreateHashResult{} + if params.Password == "" { + err = fmt.Errorf("Empty password") + return res, err + } + res.Hash = passwd.MakeSHA256Hash([]byte(params.Password)) + if !passwd.PasswordMatch([]byte(params.Password), res.Hash) { + err = fmt.Errorf("Error hash validation") + return res, err + } + return res, err +} + +type CheckHashParams struct { + Password string + Hash string +} +type CheckHashResult struct { + Match bool `json:"match"` +} + +func (tool *Tool) CheckHash(cmd *cobra.Command, args []string) error { + tool.checkHashParams.Password = args[0] + tool.checkHashParams.Hash = args[1] + res, err := tool.checkHash(&tool.checkHashParams) + printResponse(res, err) + return err +} + +func (tool *Tool) checkHash(params *CheckHashParams) (*CheckHashResult, error) { + var err error + res := &CheckHashResult{} + if params.Password == "" { + err = fmt.Errorf("Empty password") + return res, err + } + res.Match = passwd.PasswordMatch([]byte(params.Password), params.Hash) + return res, err +} + +func printResponse(res any, err error) { + type Response struct { + Error bool `json:"error" json:"error"` + Message string `json:"message,omitempty" json:"message,omitempty"` + Result any `json:"result,omitempty" json:"result,omitempty"` + } + resp := Response{} + if err != nil { + resp.Error = true + resp.Message = err.Error() + } else { + resp.Result = res + } + respBytes, _ := yaml.Marshal(resp) + fmt.Printf("---\n%s\n", string(respBytes)) +} diff --git a/cmd/minilbadm/main.go b/cmd/minilbadm/main.go new file mode 100644 index 0000000..a066058 --- /dev/null +++ b/cmd/minilbadm/main.go @@ -0,0 +1,22 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package main + +import ( + "os" +) + +func main() { + tool := NewTool() + err := tool.Exec(os.Args[1:]) + if err != nil { + os.Exit(1) + } +} diff --git a/cmd/minilbadm/tool.go b/cmd/minilbadm/tool.go new file mode 100644 index 0000000..278b697 --- /dev/null +++ b/cmd/minilbadm/tool.go @@ -0,0 +1,44 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package main + +import ( + "os" + "path/filepath" + + "helmet/cmd/minilbadm/hash" + + "github.com/spf13/cobra" +) + +type Tool struct { + cmd *cobra.Command + hashTool *hash.Tool +} + +func NewTool() *Tool { + execName := filepath.Base(os.Args[0]) + tool := &Tool{} + tool.cmd = &cobra.Command{ + Use: execName, + Short: "\nHash tool", + SilenceUsage: true, + } + tool.cmd.CompletionOptions.DisableDefaultCmd = true + + tool.hashTool = hash.NewTool() + tool.cmd.AddCommand(tool.hashTool.GetCmd()) + return tool +} + +func (tool *Tool) Exec(args []string) error { + tool.cmd.SetArgs(args) + return tool.cmd.Execute() +} diff --git a/cmd/minilbctl/forwarder/createforw.go b/cmd/minilbctl/forwarder/createforw.go new file mode 100644 index 0000000..9101f81 --- /dev/null +++ b/cmd/minilbctl/forwarder/createforw.go @@ -0,0 +1,51 @@ +package forwarder + +import ( + "context" + "time" + + "helmet/pkg/client" + "helmet/pkg/mlbctl" + + "github.com/spf13/cobra" +) + +type CreateForwarderParams struct { + Hostname string + Lport uint32 + Dport uint32 + Addresses []string +} +type CreateForwarderResult struct{} + +func (tool *Tool) CreateForwarder(cmd *cobra.Command, args []string) { + tool.createForwarderParams.Hostname = args[0] + res, err := tool.createForwarder(&tool.createForwarderParams) + printResponse(res, err) +} + +func (tool *Tool) createForwarder(params *CreateForwarderParams) (*CreateForwarderResult, error) { + var err error + res := &CreateForwarderResult{} + ref, err := client.NewReferer(params.Hostname) + if err != nil { + return res, err + } + authCred := client.NewAuthCredential(ref.Userinfo()) + conn, cli, err := client.NewClient(ref.Hostinfo(), authCred) + if err != nil { + return res, err + } + defer conn.Close() + ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) + opReq := &mlbctl.CreateForwarderParams{ + Lport: params.Lport, + Dport: params.Dport, + Destinations: params.Addresses, + } + _, err = cli.CreateForwarder(ctx, opReq) + if err != nil { + return res, err + } + return res, err +} diff --git a/cmd/minilbctl/forwarder/deleteforw.go b/cmd/minilbctl/forwarder/deleteforw.go new file mode 100644 index 0000000..51e1188 --- /dev/null +++ b/cmd/minilbctl/forwarder/deleteforw.go @@ -0,0 +1,47 @@ +package forwarder + +import ( + "context" + "time" + + "helmet/pkg/client" + "helmet/pkg/mlbctl" + + "github.com/spf13/cobra" +) + +type DeleteForwarderParams struct { + Hostname string + Lport uint32 +} +type DeleteForwarderResult struct{} + +func (tool *Tool) DeleteForwarder(cmd *cobra.Command, args []string) { + tool.deleteForwarderParams.Hostname = args[0] + res, err := tool.deleteForwarder(&tool.deleteForwarderParams) + printResponse(res, err) +} + +func (tool *Tool) deleteForwarder(params *DeleteForwarderParams) (*DeleteForwarderResult, error) { + var err error + res := &DeleteForwarderResult{} + ref, err := client.NewReferer(params.Hostname) + if err != nil { + return res, err + } + authCred := client.NewAuthCredential(ref.Userinfo()) + conn, cli, err := client.NewClient(ref.Hostinfo(), authCred) + if err != nil { + return res, err + } + defer conn.Close() + ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) + opReq := &mlbctl.DeleteForwarderParams{ + Lport: params.Lport, + } + _, err = cli.DeleteForwarder(ctx, opReq) + if err != nil { + return res, err + } + return res, err +} diff --git a/cmd/minilbctl/forwarder/forwcmd.go b/cmd/minilbctl/forwarder/forwcmd.go new file mode 100644 index 0000000..2ba3b4c --- /dev/null +++ b/cmd/minilbctl/forwarder/forwcmd.go @@ -0,0 +1,78 @@ +package forwarder + +import ( + "fmt" + + "github.com/spf13/cobra" + "sigs.k8s.io/yaml" +) + +type Tool struct { + cmd *cobra.Command + listForwardersParams ListForwardersParams + createForwarderParams CreateForwarderParams + deleteForwarderParams DeleteForwarderParams +} + +func NewTool() *Tool { + tool := &Tool{} + tool.cmd = &cobra.Command{ + Use: "forwarder", + Short: "Forwarder operation", + Aliases: []string{"forw"}, + } + listForwardersCmd := &cobra.Command{ + Use: "list", + Args: cobra.ExactArgs(1), + Short: "List forwarders", + Run: tool.ListForwarders, + } + tool.cmd.AddCommand(listForwardersCmd) + + createForwarderCmd := &cobra.Command{ + Use: "create", + Args: cobra.ExactArgs(1), + Short: "Create forwarder", + Run: tool.CreateForwarder, + } + createForwarderCmd.Flags().Uint32VarP(&tool.createForwarderParams.Lport, "lport", "L", 0, "Listening port") + createForwarderCmd.Flags().Uint32VarP(&tool.createForwarderParams.Dport, "dport", "D", 0, "Destination port") + createForwarderCmd.Flags().StringArrayVarP(&tool.createForwarderParams.Addresses, "dests", "A", []string{}, "Destination address list") + createForwarderCmd.MarkFlagRequired("lport") + createForwarderCmd.MarkFlagRequired("dport") + createForwarderCmd.MarkFlagRequired("dests") + tool.cmd.AddCommand(createForwarderCmd) + + deleteForwarderCmd := &cobra.Command{ + Use: "delete", + Args: cobra.ExactArgs(1), + Short: "Delete forwarder", + Run: tool.CreateForwarder, + } + deleteForwarderCmd.Flags().Uint32VarP(&tool.deleteForwarderParams.Lport, "lport", "L", 0, "Listening port") + deleteForwarderCmd.MarkFlagRequired("lport") + tool.cmd.AddCommand(deleteForwarderCmd) + + return tool +} + +func (tool *Tool) GetCmd() *cobra.Command { + return tool.cmd +} + +func printResponse(res any, err error) { + type Response struct { + Error bool `json:"error" json:"error"` + Message string `json:"message,omitempty" json:"message,omitempty"` + Result any `json:"result,omitempty" json:"result,omitempty"` + } + resp := Response{} + if err != nil { + resp.Error = true + resp.Message = err.Error() + } else { + resp.Result = res + } + respBytes, _ := yaml.Marshal(resp) + fmt.Printf("---\n%s\n", string(respBytes)) +} diff --git a/cmd/minilbctl/forwarder/listforw.go b/cmd/minilbctl/forwarder/listforw.go new file mode 100644 index 0000000..943938e --- /dev/null +++ b/cmd/minilbctl/forwarder/listforw.go @@ -0,0 +1,47 @@ +package forwarder + +import ( + "context" + "time" + + "helmet/pkg/client" + "helmet/pkg/mlbctl" + + "github.com/spf13/cobra" +) + +type ListForwardersParams struct { + Hostname string +} +type ListForwardersResult struct { + Forwarders []*mlbctl.Forwarder `json:"forwarders,omitempty"` +} + +func (tool *Tool) ListForwarders(cmd *cobra.Command, args []string) { + tool.listForwardersParams.Hostname = args[0] + res, err := tool.listForwarders(&tool.listForwardersParams) + printResponse(res, err) +} + +func (tool *Tool) listForwarders(params *ListForwardersParams) (*ListForwardersResult, error) { + var err error + res := &ListForwardersResult{} + ref, err := client.NewReferer(params.Hostname) + if err != nil { + return res, err + } + authCred := client.NewAuthCredential(ref.Userinfo()) + conn, cli, err := client.NewClient(ref.Hostinfo(), authCred) + if err != nil { + return res, err + } + defer conn.Close() + ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) + opReq := &mlbctl.ListForwardersParams{} + opRes, err := cli.ListForwarders(ctx, opReq) + if err != nil { + return res, err + } + res.Forwarders = opRes.Forwarders + return res, err +} diff --git a/cmd/minilbctl/main.go b/cmd/minilbctl/main.go new file mode 100644 index 0000000..a066058 --- /dev/null +++ b/cmd/minilbctl/main.go @@ -0,0 +1,22 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package main + +import ( + "os" +) + +func main() { + tool := NewTool() + err := tool.Exec(os.Args[1:]) + if err != nil { + os.Exit(1) + } +} diff --git a/cmd/minilbctl/service/srvcmd.go b/cmd/minilbctl/service/srvcmd.go new file mode 100644 index 0000000..00fb389 --- /dev/null +++ b/cmd/minilbctl/service/srvcmd.go @@ -0,0 +1,91 @@ +package service + +import ( + "context" + "fmt" + "time" + + "helmet/pkg/client" + "helmet/pkg/mlbctl" + + "github.com/spf13/cobra" + "sigs.k8s.io/yaml" +) + +type Tool struct { + cmd *cobra.Command + serviceHelloParams ServiceHelloParams +} + +func NewTool() *Tool { + tool := &Tool{} + tool.cmd = &cobra.Command{ + Use: "service", + Short: "Service operation", + } + serviceHelloCmd := &cobra.Command{ + Use: "hello", + Args: cobra.ExactArgs(1), + Short: "Send and receive hello", + Run: tool.ServiceHello, + } + tool.cmd.AddCommand(serviceHelloCmd) + return tool +} + +func (tool *Tool) GetCmd() *cobra.Command { + return tool.cmd +} + +type ServiceHelloParams struct { + Hostname string +} +type ServiceHelloResult struct { + Message string `json:"message,omitempty"` +} + +func (tool *Tool) ServiceHello(cmd *cobra.Command, args []string) { + tool.serviceHelloParams.Hostname = args[0] + res, err := tool.serviceHello(&tool.serviceHelloParams) + printResponse(res, err) +} + +func (tool *Tool) serviceHello(params *ServiceHelloParams) (*ServiceHelloResult, error) { + var err error + res := &ServiceHelloResult{} + ref, err := client.NewReferer(params.Hostname) + if err != nil { + return res, err + } + authCred := client.NewAuthCredential(ref.Userinfo()) + conn, cli, err := client.NewClient(ref.Hostinfo(), authCred) + if err != nil { + return res, err + } + defer conn.Close() + ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) + opReq := &mlbctl.GetHelloParams{} + opRes, err := cli.GetHello(ctx, opReq) + if err != nil { + return res, err + } + res.Message = opRes.Message + return res, err +} + +func printResponse(res any, err error) { + type Response struct { + Error bool `json:"error" json:"error"` + Message string `json:"message,omitempty" json:"message,omitempty"` + Result any `json:"result,omitempty" json:"result,omitempty"` + } + resp := Response{} + if err != nil { + resp.Error = true + resp.Message = err.Error() + } else { + resp.Result = res + } + respBytes, _ := yaml.Marshal(resp) + fmt.Printf("---\n%s\n", string(respBytes)) +} diff --git a/cmd/minilbctl/tool.go b/cmd/minilbctl/tool.go new file mode 100644 index 0000000..2033214 --- /dev/null +++ b/cmd/minilbctl/tool.go @@ -0,0 +1,49 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package main + +import ( + "os" + "path/filepath" + + "helmet/cmd/minilbctl/forwarder" + "helmet/cmd/minilbctl/service" + + "github.com/spf13/cobra" +) + +type Tool struct { + cmd *cobra.Command + forwarderTool *forwarder.Tool + serviceTool *service.Tool +} + +func NewTool() *Tool { + execName := filepath.Base(os.Args[0]) + tool := &Tool{} + tool.cmd = &cobra.Command{ + Use: execName, + Short: "\nService tools", + SilenceUsage: true, + } + tool.cmd.CompletionOptions.DisableDefaultCmd = true + + tool.serviceTool = service.NewTool() + tool.cmd.AddCommand(tool.serviceTool.GetCmd()) + + tool.forwarderTool = forwarder.NewTool() + tool.cmd.AddCommand(tool.forwarderTool.GetCmd()) + return tool +} + +func (tool *Tool) Exec(args []string) error { + tool.cmd.SetArgs(args) + return tool.cmd.Execute() +} diff --git a/cmd/minilbd/main.go b/cmd/minilbd/main.go new file mode 100644 index 0000000..725b529 --- /dev/null +++ b/cmd/minilbd/main.go @@ -0,0 +1,28 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package main + +import ( + "os" + + "helmet/app/logger" + "helmet/cmd/minilbd/starter" +) + +func main() { + log := logger.NewLogger("main") + sta := starter.NewStarter() + err := sta.Exec() + if err != nil { + log.Errorf("%v", err) + os.Exit(1) + } + os.Exit(0) +} diff --git a/cmd/minilbd/starter/starter.go b/cmd/minilbd/starter/starter.go new file mode 100644 index 0000000..e3c01aa --- /dev/null +++ b/cmd/minilbd/starter/starter.go @@ -0,0 +1,83 @@ +/* + * Copyright 2026 Oleg Borodin + * + * This work is published and licensed under a Creative Commons + * Attribution-NonCommercial-NoDerivatives 4.0 International License. + * + * Distribution of this work is permitted, but commercial use and + * modifications are strictly prohibited. + */ +package starter + +import ( + "os" + "path/filepath" + + "helmet/app/server" + "helmet/pkg/client" + + "github.com/spf13/cobra" +) + +type Starter struct { + runAsDaemon bool + port uint32 + cmd *cobra.Command + srv *server.Server +} + +func NewStarter() *Starter { + execName := filepath.Base(os.Args[0]) + sta := &Starter{} + cmd := &cobra.Command{ + Use: execName, + Short: "\nProxy service", + SilenceUsage: true, + RunE: sta.run, + } + cmd.CompletionOptions.DisableDefaultCmd = true + cmd.Flags().BoolVarP(&sta.runAsDaemon, "asDaemon", "D", false, "Run service as daemon") + cmd.Flags().Uint32VarP(&sta.port, "port", "P", client.DefaultServicePort, "Service port") + + sta.cmd = cmd + return sta +} + +func (sta *Starter) GetCmd() *cobra.Command { + return sta.cmd +} + +func (sta *Starter) run(cmd *cobra.Command, args []string) error { + var err error + srv, err := server.NewServer() + if err != nil { + return err + } + err = srv.Configure() + if err != nil { + return err + } + + srv.Config().AsDaemon = sta.runAsDaemon + srv.Config().Service.Port = sta.port + + err = srv.Daemonize() + if err != nil { + return err + } + err = srv.Build() + if err != nil { + return err + } + srv.Rotator() + err = srv.Run() + if err != nil { + return err + } + sta.srv = srv + return err +} + +func (sta *Starter) Exec() error { + return sta.cmd.Execute() +} diff --git a/configure b/configure index 7304b21..4f24b26 100755 --- a/configure +++ b/configure @@ -635,6 +635,7 @@ DPKGSOURCE DBUILDPACKAGE HELM PODMAN +PROTOC BASENAME CPIO SUDO @@ -3200,6 +3201,57 @@ fi done +for ac_prog in protoc true +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PROTOC+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) case $PROTOC in + [\\/]* | ?:[\\/]*) + ac_cv_path_PROTOC="$PROTOC" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PROTOC="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac ;; +esac +fi +PROTOC=$ac_cv_path_PROTOC +if test -n "$PROTOC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PROTOC" >&5 +printf "%s\n" "$PROTOC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$PROTOC" && break +done + for ac_prog in podman true do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/configure.ac b/configure.ac index fa35e77..04397ff 100644 --- a/configure.ac +++ b/configure.ac @@ -18,6 +18,7 @@ AC_PATH_PROGS([SUDO],[sudo false]) AC_PATH_PROGS([CPIO],[cpio false]) AC_PATH_PROGS([BASENAME],[basename]) +AC_PATH_PROGS([PROTOC],[protoc true]) AC_PATH_PROGS([PODMAN],[podman true]) AC_PATH_PROGS([HELM],[helm true]) AC_PATH_PROGS([DBUILDPACKAGE],[dpkg-buildpackage true]) diff --git a/initrc/minilbd.service b/initrc/minilbd.service index 55536cd..ea610f7 100644 --- a/initrc/minilbd.service +++ b/initrc/minilbd.service @@ -6,7 +6,7 @@ Type=forking ExecStart=@srv_sbindir@/minilbd -asDaemon=true ExecReload=/bin/kill -HUP $MAINPID ExecRestart=/bin/kill -HUP $MAINPID -ExecStartPre=/usr/bin/install -d -o root -g root /home/ziggi/Projects/gserver/tmp/run /home/ziggi/Projects/gserver/tmp/log +ExecStartPre=/usr/bin/install -d -o root -g root /home/ziggi/Projects/minilb/tmp/run /home/ziggi/Projects/minilb/tmp/log [Install] WantedBy=multi-user.target diff --git a/pkg/mlbctl/mlbctl.pb.go b/pkg/mlbctl/mlbctl.pb.go index 9bcd2f3..cc94534 100644 --- a/pkg/mlbctl/mlbctl.pb.go +++ b/pkg/mlbctl/mlbctl.pb.go @@ -101,6 +101,366 @@ func (x *GetHelloResult) GetMessage() string { return "" } +type Forwarder struct { + state protoimpl.MessageState `protogen:"open.v1"` + Lport uint32 `protobuf:"varint,1,opt,name=lport,proto3" json:"lport,omitempty"` + Dport uint32 `protobuf:"varint,2,opt,name=dport,proto3" json:"dport,omitempty"` + Destinations []*Destination `protobuf:"bytes,3,rep,name=destinations,proto3" json:"destinations,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Forwarder) Reset() { + *x = Forwarder{} + mi := &file_mlbctl_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Forwarder) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Forwarder) ProtoMessage() {} + +func (x *Forwarder) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Forwarder.ProtoReflect.Descriptor instead. +func (*Forwarder) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{2} +} + +func (x *Forwarder) GetLport() uint32 { + if x != nil { + return x.Lport + } + return 0 +} + +func (x *Forwarder) GetDport() uint32 { + if x != nil { + return x.Dport + } + return 0 +} + +func (x *Forwarder) GetDestinations() []*Destination { + if x != nil { + return x.Destinations + } + return nil +} + +type Destination struct { + state protoimpl.MessageState `protogen:"open.v1"` + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Destination) Reset() { + *x = Destination{} + mi := &file_mlbctl_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Destination) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Destination) ProtoMessage() {} + +func (x *Destination) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Destination.ProtoReflect.Descriptor instead. +func (*Destination) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{3} +} + +func (x *Destination) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +type ListForwardersParams struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListForwardersParams) Reset() { + *x = ListForwardersParams{} + mi := &file_mlbctl_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListForwardersParams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListForwardersParams) ProtoMessage() {} + +func (x *ListForwardersParams) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListForwardersParams.ProtoReflect.Descriptor instead. +func (*ListForwardersParams) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{4} +} + +type ListForwardersResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + Forwarders []*Forwarder `protobuf:"bytes,1,rep,name=forwarders,proto3" json:"forwarders,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListForwardersResult) Reset() { + *x = ListForwardersResult{} + mi := &file_mlbctl_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListForwardersResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListForwardersResult) ProtoMessage() {} + +func (x *ListForwardersResult) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListForwardersResult.ProtoReflect.Descriptor instead. +func (*ListForwardersResult) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{5} +} + +func (x *ListForwardersResult) GetForwarders() []*Forwarder { + if x != nil { + return x.Forwarders + } + return nil +} + +type CreateForwarderParams struct { + state protoimpl.MessageState `protogen:"open.v1"` + Lport uint32 `protobuf:"varint,1,opt,name=lport,proto3" json:"lport,omitempty"` + Dport uint32 `protobuf:"varint,2,opt,name=dport,proto3" json:"dport,omitempty"` + Destinations []string `protobuf:"bytes,3,rep,name=destinations,proto3" json:"destinations,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateForwarderParams) Reset() { + *x = CreateForwarderParams{} + mi := &file_mlbctl_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateForwarderParams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateForwarderParams) ProtoMessage() {} + +func (x *CreateForwarderParams) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateForwarderParams.ProtoReflect.Descriptor instead. +func (*CreateForwarderParams) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{6} +} + +func (x *CreateForwarderParams) GetLport() uint32 { + if x != nil { + return x.Lport + } + return 0 +} + +func (x *CreateForwarderParams) GetDport() uint32 { + if x != nil { + return x.Dport + } + return 0 +} + +func (x *CreateForwarderParams) GetDestinations() []string { + if x != nil { + return x.Destinations + } + return nil +} + +type CreateForwarderResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateForwarderResult) Reset() { + *x = CreateForwarderResult{} + mi := &file_mlbctl_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateForwarderResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateForwarderResult) ProtoMessage() {} + +func (x *CreateForwarderResult) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateForwarderResult.ProtoReflect.Descriptor instead. +func (*CreateForwarderResult) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{7} +} + +type DeleteForwarderParams struct { + state protoimpl.MessageState `protogen:"open.v1"` + Lport uint32 `protobuf:"varint,1,opt,name=lport,proto3" json:"lport,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteForwarderParams) Reset() { + *x = DeleteForwarderParams{} + mi := &file_mlbctl_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteForwarderParams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteForwarderParams) ProtoMessage() {} + +func (x *DeleteForwarderParams) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteForwarderParams.ProtoReflect.Descriptor instead. +func (*DeleteForwarderParams) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{8} +} + +func (x *DeleteForwarderParams) GetLport() uint32 { + if x != nil { + return x.Lport + } + return 0 +} + +type DeleteForwarderResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteForwarderResult) Reset() { + *x = DeleteForwarderResult{} + mi := &file_mlbctl_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteForwarderResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteForwarderResult) ProtoMessage() {} + +func (x *DeleteForwarderResult) ProtoReflect() protoreflect.Message { + mi := &file_mlbctl_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteForwarderResult.ProtoReflect.Descriptor instead. +func (*DeleteForwarderResult) Descriptor() ([]byte, []int) { + return file_mlbctl_proto_rawDescGZIP(), []int{9} +} + var File_mlbctl_proto protoreflect.FileDescriptor var file_mlbctl_proto_rawDesc = string([]byte{ @@ -109,13 +469,56 @@ var file_mlbctl_proto_rawDesc = string([]byte{ 0x6c, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x2a, 0x0a, 0x0e, 0x67, 0x65, 0x74, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x32, 0x47, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, - 0x3c, 0x0a, 0x08, 0x67, 0x65, 0x74, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x16, 0x2e, 0x6d, 0x6c, - 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x67, 0x65, 0x74, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x1a, 0x16, 0x2e, 0x6d, 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x67, 0x65, 0x74, - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x42, 0x0a, 0x5a, - 0x08, 0x2e, 0x3b, 0x6d, 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x70, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, + 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x05, 0x6c, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x37, 0x0a, + 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x64, 0x65, 0x73, + 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x27, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, + 0x16, 0x0a, 0x14, 0x6c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, + 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x49, 0x0a, 0x14, 0x6c, 0x69, 0x73, 0x74, 0x46, + 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, + 0x31, 0x0a, 0x0a, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6d, 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x66, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, + 0x72, 0x73, 0x22, 0x67, 0x0a, 0x15, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x70, 0x6f, 0x72, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x05, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x64, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x17, 0x0a, 0x15, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0x2d, 0x0a, 0x15, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x6f, + 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x6c, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x70, + 0x6f, 0x72, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0xbd, 0x02, 0x0a, + 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x3c, 0x0a, 0x08, 0x67, 0x65, 0x74, 0x48, + 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x16, 0x2e, 0x6d, 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x67, 0x65, + 0x74, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x16, 0x2e, 0x6d, + 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x67, 0x65, 0x74, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1d, 0x2e, 0x6d, 0x6c, 0x62, 0x63, + 0x74, 0x6c, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, + 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1d, 0x2e, 0x6d, 0x6c, 0x62, 0x63, 0x74, + 0x6c, 0x2e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0e, 0x6c, 0x69, 0x73, + 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1c, 0x2e, 0x6d, 0x6c, + 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, + 0x65, 0x72, 0x73, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1c, 0x2e, 0x6d, 0x6c, 0x62, 0x63, + 0x74, 0x6c, 0x2e, 0x6c, 0x69, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0f, 0x64, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1d, 0x2e, 0x6d, + 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x1a, 0x1d, 0x2e, 0x6d, 0x6c, + 0x62, 0x63, 0x74, 0x6c, 0x2e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, + 0x2e, 0x3b, 0x6d, 0x6c, 0x62, 0x63, 0x74, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -130,19 +533,35 @@ func file_mlbctl_proto_rawDescGZIP() []byte { return file_mlbctl_proto_rawDescData } -var file_mlbctl_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_mlbctl_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_mlbctl_proto_goTypes = []any{ - (*GetHelloParams)(nil), // 0: mlbctl.getHelloParams - (*GetHelloResult)(nil), // 1: mlbctl.getHelloResult + (*GetHelloParams)(nil), // 0: mlbctl.getHelloParams + (*GetHelloResult)(nil), // 1: mlbctl.getHelloResult + (*Forwarder)(nil), // 2: mlbctl.forwarder + (*Destination)(nil), // 3: mlbctl.destination + (*ListForwardersParams)(nil), // 4: mlbctl.listForwardersParams + (*ListForwardersResult)(nil), // 5: mlbctl.listForwardersResult + (*CreateForwarderParams)(nil), // 6: mlbctl.createForwarderParams + (*CreateForwarderResult)(nil), // 7: mlbctl.createForwarderResult + (*DeleteForwarderParams)(nil), // 8: mlbctl.deleteForwarderParams + (*DeleteForwarderResult)(nil), // 9: mlbctl.deleteForwarderResult } var file_mlbctl_proto_depIdxs = []int32{ - 0, // 0: mlbctl.Control.getHello:input_type -> mlbctl.getHelloParams - 1, // 1: mlbctl.Control.getHello:output_type -> mlbctl.getHelloResult - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 3, // 0: mlbctl.forwarder.destinations:type_name -> mlbctl.destination + 2, // 1: mlbctl.listForwardersResult.forwarders:type_name -> mlbctl.forwarder + 0, // 2: mlbctl.Control.getHello:input_type -> mlbctl.getHelloParams + 6, // 3: mlbctl.Control.createForwarder:input_type -> mlbctl.createForwarderParams + 4, // 4: mlbctl.Control.listForwarders:input_type -> mlbctl.listForwardersParams + 8, // 5: mlbctl.Control.deleteForwarder:input_type -> mlbctl.deleteForwarderParams + 1, // 6: mlbctl.Control.getHello:output_type -> mlbctl.getHelloResult + 7, // 7: mlbctl.Control.createForwarder:output_type -> mlbctl.createForwarderResult + 5, // 8: mlbctl.Control.listForwarders:output_type -> mlbctl.listForwardersResult + 9, // 9: mlbctl.Control.deleteForwarder:output_type -> mlbctl.deleteForwarderResult + 6, // [6:10] is the sub-list for method output_type + 2, // [2:6] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_mlbctl_proto_init() } @@ -156,7 +575,7 @@ func file_mlbctl_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_mlbctl_proto_rawDesc), len(file_mlbctl_proto_rawDesc)), NumEnums: 0, - NumMessages: 2, + NumMessages: 10, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/mlbctl/mlbctl_grpc.pb.go b/pkg/mlbctl/mlbctl_grpc.pb.go index 2a26c5b..efc6e8f 100644 --- a/pkg/mlbctl/mlbctl_grpc.pb.go +++ b/pkg/mlbctl/mlbctl_grpc.pb.go @@ -19,7 +19,10 @@ import ( const _ = grpc.SupportPackageIsVersion8 const ( - Control_GetHello_FullMethodName = "/mlbctl.Control/getHello" + Control_GetHello_FullMethodName = "/mlbctl.Control/getHello" + Control_CreateForwarder_FullMethodName = "/mlbctl.Control/createForwarder" + Control_ListForwarders_FullMethodName = "/mlbctl.Control/listForwarders" + Control_DeleteForwarder_FullMethodName = "/mlbctl.Control/deleteForwarder" ) // ControlClient is the client API for Control service. @@ -27,6 +30,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 ControlClient interface { GetHello(ctx context.Context, in *GetHelloParams, opts ...grpc.CallOption) (*GetHelloResult, error) + CreateForwarder(ctx context.Context, in *CreateForwarderParams, opts ...grpc.CallOption) (*CreateForwarderResult, error) + ListForwarders(ctx context.Context, in *ListForwardersParams, opts ...grpc.CallOption) (*ListForwardersResult, error) + DeleteForwarder(ctx context.Context, in *DeleteForwarderParams, opts ...grpc.CallOption) (*DeleteForwarderResult, error) } type controlClient struct { @@ -47,11 +53,44 @@ func (c *controlClient) GetHello(ctx context.Context, in *GetHelloParams, opts . return out, nil } +func (c *controlClient) CreateForwarder(ctx context.Context, in *CreateForwarderParams, opts ...grpc.CallOption) (*CreateForwarderResult, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreateForwarderResult) + err := c.cc.Invoke(ctx, Control_CreateForwarder_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) ListForwarders(ctx context.Context, in *ListForwardersParams, opts ...grpc.CallOption) (*ListForwardersResult, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListForwardersResult) + err := c.cc.Invoke(ctx, Control_ListForwarders_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlClient) DeleteForwarder(ctx context.Context, in *DeleteForwarderParams, opts ...grpc.CallOption) (*DeleteForwarderResult, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteForwarderResult) + err := c.cc.Invoke(ctx, Control_DeleteForwarder_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // ControlServer is the server API for Control service. // All implementations must embed UnimplementedControlServer // for forward compatibility type ControlServer interface { GetHello(context.Context, *GetHelloParams) (*GetHelloResult, error) + CreateForwarder(context.Context, *CreateForwarderParams) (*CreateForwarderResult, error) + ListForwarders(context.Context, *ListForwardersParams) (*ListForwardersResult, error) + DeleteForwarder(context.Context, *DeleteForwarderParams) (*DeleteForwarderResult, error) mustEmbedUnimplementedControlServer() } @@ -62,6 +101,15 @@ type UnimplementedControlServer struct { func (UnimplementedControlServer) GetHello(context.Context, *GetHelloParams) (*GetHelloResult, error) { return nil, status.Errorf(codes.Unimplemented, "method GetHello not implemented") } +func (UnimplementedControlServer) CreateForwarder(context.Context, *CreateForwarderParams) (*CreateForwarderResult, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateForwarder not implemented") +} +func (UnimplementedControlServer) ListForwarders(context.Context, *ListForwardersParams) (*ListForwardersResult, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListForwarders not implemented") +} +func (UnimplementedControlServer) DeleteForwarder(context.Context, *DeleteForwarderParams) (*DeleteForwarderResult, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteForwarder not implemented") +} func (UnimplementedControlServer) mustEmbedUnimplementedControlServer() {} // UnsafeControlServer may be embedded to opt out of forward compatibility for this service. @@ -93,6 +141,60 @@ func _Control_GetHello_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _Control_CreateForwarder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateForwarderParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).CreateForwarder(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_CreateForwarder_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).CreateForwarder(ctx, req.(*CreateForwarderParams)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_ListForwarders_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListForwardersParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).ListForwarders(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_ListForwarders_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).ListForwarders(ctx, req.(*ListForwardersParams)) + } + return interceptor(ctx, in, info, handler) +} + +func _Control_DeleteForwarder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteForwarderParams) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServer).DeleteForwarder(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Control_DeleteForwarder_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServer).DeleteForwarder(ctx, req.(*DeleteForwarderParams)) + } + return interceptor(ctx, in, info, handler) +} + // Control_ServiceDesc is the grpc.ServiceDesc for Control service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -104,6 +206,18 @@ var Control_ServiceDesc = grpc.ServiceDesc{ MethodName: "getHello", Handler: _Control_GetHello_Handler, }, + { + MethodName: "createForwarder", + Handler: _Control_CreateForwarder_Handler, + }, + { + MethodName: "listForwarders", + Handler: _Control_ListForwarders_Handler, + }, + { + MethodName: "deleteForwarder", + Handler: _Control_DeleteForwarder_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "mlbctl.proto", diff --git a/proto/mlbctl.proto b/proto/mlbctl.proto index 41ed1fc..bc2503b 100644 --- a/proto/mlbctl.proto +++ b/proto/mlbctl.proto @@ -6,10 +6,39 @@ package mlbctl; service Control { rpc getHello(getHelloParams) returns (getHelloResult) {}; + rpc createForwarder(createForwarderParams) returns (createForwarderResult) {}; + rpc listForwarders(listForwardersParams) returns (listForwardersResult) {}; + rpc deleteForwarder(deleteForwarderParams) returns (deleteForwarderResult) {}; } message getHelloParams {} message getHelloResult { - string message = 1; + string message = 1; } +message forwarder { + uint32 lport = 1; + uint32 dport = 2; + repeated destination destinations = 3; +} + +message destination { + string address = 1; +} + +message listForwardersParams {} +message listForwardersResult { + repeated forwarder forwarders = 1; +} + +message createForwarderParams { + uint32 lport = 1; + uint32 dport = 2; + repeated string destinations = 3; +} +message createForwarderResult {} + +message deleteForwarderParams { + uint32 lport = 1; +} +message deleteForwarderResult {}