diff --git a/code/client/app/app.go b/code/client/app/program.go similarity index 100% rename from code/client/app/app.go rename to code/client/app/program.go diff --git a/code/client/main.go b/code/client/main.go index c2e88ec..0fea777 100644 --- a/code/client/main.go +++ b/code/client/main.go @@ -103,97 +103,4 @@ func main() { fmt.Println(err.Error()) os.Exit(1) } - - // user := flag.String("user", "", "service user") - // conf := flag.String("conf", "", "configure file path") - // act := flag.String("action", "", "install or uninstall") - // name := flag.String("name", "", "rule name") - // vport := flag.Uint("vport", 6155, "vnc worker listen port") - // vcursor := flag.Bool("vcursor", false, "vnc show cursor") - // flag.Parse() - - // if len(*conf) == 0 { - // fmt.Println("missing -conf param") - // os.Exit(1) - // } - - // // for test - // // work := worker.NewWorker() - // // work.TestCapture() - // // return - - // dir, err := filepath.Abs(*conf) - // runtime.Assert(err) - - // var depends []string - // if rt.GOOS != "windows" { - // depends = append(depends, "After=network.target") - // } - // var opt service.KeyValue - // switch rt.GOOS { - // case "windows": - // opt = service.KeyValue{ - // "StartType": "automatic", - // "OnFailure": "restart", - // "OnFailureDelayDuration": "5s", - // "OnFailureResetPeriod": 10, - // } - // case "linux": - // opt = service.KeyValue{ - // "LimitNOFILE": 65000, - // } - // case "darwin": - // opt = service.KeyValue{ - // "SessionCreate": true, - // } - // } - - // appCfg := &service.Config{ - // Name: "np-cli", - // DisplayName: "np-cli", - // Description: "nat forward service", - // UserName: *user, - // Arguments: []string{"-conf", dir}, - // Dependencies: depends, - // Option: opt, - // } - - // cfg := global.LoadConf(*conf) - - // if *act == "vnc.worker" { - // defer utils.Recover("vnc.worker") - // stdout := true - // if rt.GOOS == "windows" { - // stdout = false - // } - // // go func() { - // // http.ListenAndServe(":9001", nil) - // // }() - // logging.SetSizeRotate(logging.SizeRotateConfig{ - // Dir: cfg.LogDir, - // Name: "np-cli.vnc." + *name, - // Size: int64(cfg.LogSize.Bytes()), - // Rotate: cfg.LogRotate, - // WriteStdout: stdout, - // WriteFile: true, - // }) - // defer logging.Flush() - // vnc.RunWorker(uint16(*vport), *vcursor) - // return - // } - - // app := app.New(version, *conf, cfg) - // sv, err := service.New(app, appCfg) - // runtime.Assert(err) - - // switch *act { - // case "install": - // runtime.Assert(sv.Install()) - // utils.BuildDir(cfg.LogDir, *user) - // utils.BuildDir(cfg.CodeDir, *user) - // case "uninstall": - // runtime.Assert(sv.Uninstall()) - // default: - // runtime.Assert(sv.Run()) - // } } diff --git a/code/server/app/cmd.go b/code/server/app/cmd.go new file mode 100644 index 0000000..5b59df6 --- /dev/null +++ b/code/server/app/cmd.go @@ -0,0 +1,153 @@ +package app + +import ( + "fmt" + "os" + "path/filepath" + rt "runtime" + + "github.com/kardianos/service" + "github.com/lwch/natpass/code/server/global" + "github.com/lwch/natpass/code/utils" + "github.com/lwch/runtime" + "github.com/spf13/cobra" +) + +var User string +var ConfDir string +var Version string + +// vnc child process params +var ( + VncName string + VncPort uint16 + VncCursor bool +) + +type App struct { + p *program +} + +// NewApp create application +func NewApp() *App { + return &App{ + p: newProgram(), + } +} + +func buildService(p *program) service.Service { + dir, err := filepath.Abs(ConfDir) + runtime.Assert(err) + + var depends []string + if rt.GOOS != "windows" { + depends = append(depends, "After=network.target") + } + var opt service.KeyValue + switch rt.GOOS { + case "windows": + opt = service.KeyValue{ + "StartType": "automatic", + "OnFailure": "restart", + "OnFailureDelayDuration": "5s", + "OnFailureResetPeriod": 10, + } + case "linux": + opt = service.KeyValue{ + "LimitNOFILE": 65000, + } + case "darwin": + opt = service.KeyValue{ + "SessionCreate": true, + } + } + + svc, err := service.New(p, &service.Config{ + Name: "np-svr", + DisplayName: "np-svr", + Description: "natpass server", + UserName: User, + Arguments: []string{"--conf", dir}, + Dependencies: depends, + Option: opt, + }) + runtime.Assert(err) + return svc +} + +// Run run application +func (a *App) Run(*cobra.Command, []string) { + a.p.setConfigure(global.LoadConf(ConfDir)) + + runtime.Assert(buildService(a.p).Run()) +} + +// Install register service +func (a *App) Install(*cobra.Command, []string) { + cfg := global.LoadConf(ConfDir) + + err := buildService(a.p).Install() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + utils.BuildDir(cfg.LogDir, User) + fmt.Println("register service np-svr success") +} + +// Uninstall unregister service +func (a *App) Uninstall(*cobra.Command, []string) { + err := buildService(a.p).Uninstall() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + fmt.Println("unregister service np-svr success") +} + +// Start start service +func (a *App) Start(*cobra.Command, []string) { + err := buildService(a.p).Start() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + fmt.Println("start service np-svr success") +} + +// Stop stop service +func (a *App) Stop(*cobra.Command, []string) { + err := buildService(a.p).Stop() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + fmt.Println("stop service np-svr success") +} + +// Restart restart service +func (a *App) Restart(*cobra.Command, []string) { + err := buildService(a.p).Restart() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + fmt.Println("restart service np-svr success") +} + +// Status show service status +func (a *App) Status(*cobra.Command, []string) { + status, err := buildService(a.p).Status() + if err != nil { + fmt.Println(err.Error()) + os.Exit(1) + } + switch status { + case service.StatusRunning: + fmt.Println("service is running") + case service.StatusStopped: + fmt.Println("service is stopped") + case service.StatusUnknown: + fmt.Println("service status is unknown") + } +} diff --git a/code/server/app/program.go b/code/server/app/program.go new file mode 100644 index 0000000..179176b --- /dev/null +++ b/code/server/app/program.go @@ -0,0 +1,85 @@ +package app + +import ( + "crypto/tls" + "fmt" + "net" + rt "runtime" + + "github.com/kardianos/service" + "github.com/lwch/logging" + "github.com/lwch/natpass/code/server/global" + "github.com/lwch/natpass/code/server/handler" + "github.com/lwch/runtime" +) + +type program struct { + cfg *global.Configure +} + +func newProgram() *program { + return &program{} +} + +func (p *program) setConfigure(cfg *global.Configure) *program { + p.cfg = cfg + return p +} + +func (p *program) Start(s service.Service) error { + go p.run() + return nil +} + +func (p *program) run() { + // initialize logging + stdout := true + if rt.GOOS == "windows" { + stdout = false + } + logging.SetSizeRotate(logging.SizeRotateConfig{ + Dir: p.cfg.LogDir, + Name: "np-svr", + Size: int64(p.cfg.LogSize.Bytes()), + Rotate: p.cfg.LogRotate, + WriteStdout: stdout, + WriteFile: true, + }) + defer logging.Flush() + + // go func() { + // http.ListenAndServe(":7878", nil) + // }() + + var l net.Listener + if len(p.cfg.TLSCrt) > 0 && len(p.cfg.TLSKey) > 0 { + cert, err := tls.LoadX509KeyPair(p.cfg.TLSCrt, p.cfg.TLSKey) + runtime.Assert(err) + l, err = tls.Listen("tcp", fmt.Sprintf(":%d", p.cfg.Listen), &tls.Config{ + Certificates: []tls.Certificate{cert}, + }) + runtime.Assert(err) + logging.Info("listen on %d", p.cfg.Listen) + } else { + var err error + l, err = net.Listen("tcp", fmt.Sprintf(":%d", p.cfg.Listen)) + runtime.Assert(err) + } + + p.serve(l) +} + +func (p *program) Stop(s service.Service) error { + return nil +} + +func (p *program) serve(l net.Listener) { + h := handler.New(p.cfg) + for { + conn, err := l.Accept() + if err != nil { + continue + } + go h.Handle(conn) + } +} diff --git a/code/server/main.go b/code/server/main.go index f618b31..600e700 100644 --- a/code/server/main.go +++ b/code/server/main.go @@ -1,22 +1,13 @@ package main import ( - "crypto/tls" - "flag" "fmt" - "net" "os" - "path/filepath" - rt "runtime" _ "net/http/pprof" - "github.com/kardianos/service" - "github.com/lwch/logging" - "github.com/lwch/natpass/code/server/global" - "github.com/lwch/natpass/code/server/handler" - "github.com/lwch/natpass/code/utils" - "github.com/lwch/runtime" + "github.com/lwch/natpass/code/server/app" + "github.com/spf13/cobra" ) var ( @@ -26,137 +17,77 @@ var ( buildTime string ) -func showVersion() { - fmt.Printf("version: v%s\ntime: %s\ncommit: %s.%s\n", - version, - buildTime, - gitHash, gitReversion) - os.Exit(0) +var a = app.NewApp() + +var rootCmd = &cobra.Command{ + Use: "np-cli", + Short: "natpass client", + Run: a.Run, } -type app struct { - cfg *global.Configure +var installCmd = &cobra.Command{ + Use: "install", + Short: "register service", + Run: a.Install, } -func (a *app) Start(s service.Service) error { - go a.run() - return nil +var uninstallCmd = &cobra.Command{ + Use: "uninstall", + Short: "unregister service", + Run: a.Uninstall, } -func (a *app) run() { - logging.SetSizeRotate(logging.SizeRotateConfig{ - Dir: a.cfg.LogDir, - Name: "np-svr", - Size: int64(a.cfg.LogSize.Bytes()), - Rotate: a.cfg.LogRotate, - WriteStdout: true, - WriteFile: true, - }) - defer logging.Flush() - - // go func() { - // http.ListenAndServe(":7878", nil) - // }() - - var l net.Listener - if len(a.cfg.TLSCrt) > 0 && len(a.cfg.TLSKey) > 0 { - cert, err := tls.LoadX509KeyPair(a.cfg.TLSCrt, a.cfg.TLSKey) - runtime.Assert(err) - l, err = tls.Listen("tcp", fmt.Sprintf(":%d", a.cfg.Listen), &tls.Config{ - Certificates: []tls.Certificate{cert}, - }) - runtime.Assert(err) - logging.Info("listen on %d", a.cfg.Listen) - } else { - var err error - l, err = net.Listen("tcp", fmt.Sprintf(":%d", a.cfg.Listen)) - runtime.Assert(err) - } - - run(a.cfg, l) +var startCmd = &cobra.Command{ + Use: "start", + Short: "start service", + Run: a.Start, } -func (a *app) Stop(s service.Service) error { - return nil +var stopCmd = &cobra.Command{ + Use: "stop", + Short: "stop service", + Run: a.Stop, +} + +var restartCmd = &cobra.Command{ + Use: "restart", + Short: "restart service", + Run: a.Restart, +} + +var statusCmd = &cobra.Command{ + Use: "status", + Short: "show service status", + Run: a.Status, +} + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "show version info", + Run: func(*cobra.Command, []string) { + fmt.Printf("version: v%s\ntime: %s\ncommit: %s.%s\n", + version, + buildTime, + gitHash, gitReversion) + os.Exit(0) + }, } func main() { - user := flag.String("user", "", "daemon user") - conf := flag.String("conf", "", "configure file path") - version := flag.Bool("version", false, "show version info") - act := flag.String("action", "", "install or uninstall") - flag.Parse() + app.Version = version + installCmd.Flags().StringVarP(&app.ConfDir, "conf", "c", "", "configure file path") + installCmd.Flags().StringVarP(&app.User, "user", "u", "", "service user") + installCmd.MarkFlagRequired("conf") + rootCmd.AddCommand(installCmd, uninstallCmd) + rootCmd.AddCommand(startCmd, stopCmd, restartCmd, statusCmd) + rootCmd.AddCommand(versionCmd) - if *version { - showVersion() - os.Exit(0) - } - - if len(*conf) == 0 { - fmt.Println("missing -conf param") + rootCmd.CompletionOptions.DisableDefaultCmd = true + rootCmd.Flags().StringVarP(&app.ConfDir, "conf", "c", "", "configure file path") + rootCmd.MarkFlagRequired("conf") + err := rootCmd.Execute() + if err != nil { + fmt.Println(err.Error()) os.Exit(1) } - - dir, err := filepath.Abs(*conf) - runtime.Assert(err) - - var depends []string - if rt.GOOS != "windows" { - depends = append(depends, "After=network.target") - } - var opt service.KeyValue - switch rt.GOOS { - case "windows": - opt = service.KeyValue{ - "StartType": "automatic", - "OnFailure": "restart", - "OnFailureDelayDuration": "5s", - "OnFailureResetPeriod": 10, - } - case "linux": - opt = service.KeyValue{ - "LimitNOFILE": 65000, - } - case "darwin": - opt = service.KeyValue{ - "SessionCreate": true, - } - } - - appCfg := &service.Config{ - Name: "np-svr", - DisplayName: "np-svr", - Description: "nat forward service", - UserName: *user, - Arguments: []string{"-conf", dir}, - Dependencies: depends, - Option: opt, - } - - cfg := global.LoadConf(*conf) - - app := &app{cfg: cfg} - sv, err := service.New(app, appCfg) - runtime.Assert(err) - - switch *act { - case "install": - runtime.Assert(sv.Install()) - utils.BuildDir(cfg.LogDir, *user) - case "uninstall": - runtime.Assert(sv.Uninstall()) - default: - runtime.Assert(sv.Run()) - } -} - -func run(cfg *global.Configure, l net.Listener) { - h := handler.New(cfg) - for { - conn, err := l.Accept() - if err != nil { - continue - } - go h.Handle(conn) - } }