From 6ebee06861339abb1d8b53a4051f58a8153f4f13 Mon Sep 17 00:00:00 2001 From: Kioubit Date: Mon, 27 Dec 2021 11:24:21 -0500 Subject: [PATCH] Make the user interface a module, Rework modules --- config.go | 148 ++++------------------ main.go | 67 +++------- modules/example/example.go | 28 +++-- modules/modules.go | 74 +++++++++-- modules/userInterface/userInterface.go | 162 +++++++++++++++++++++++++ 5 files changed, 288 insertions(+), 191 deletions(-) create mode 100644 modules/userInterface/userInterface.go diff --git a/config.go b/config.go index 00c2ae9..a0eb381 100644 --- a/config.go +++ b/config.go @@ -10,24 +10,6 @@ import ( "strings" ) -type configResponder struct { - Iface string - Filter string - autosense string - instance *pndp.ResponderObj -} - -type configProxy struct { - Iface1 string - Iface2 string - Filter string - autosense string - instance *pndp.ProxyObj -} - -var allResponders []*configResponder -var allProxies []*configProxy - func readConfig(dest string) { file, err := os.Open(dest) if err != nil { @@ -52,120 +34,40 @@ func readConfig(dest string) { continue } - if strings.HasPrefix(line, "responder") && strings.Contains(line, "{") { - obj := configResponder{} - filter := "" - for { - if !scanner.Scan() { - break - } - line = strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, "iface") { - obj.Iface = strings.TrimSpace(strings.TrimPrefix(line, "iface")) - } - if strings.HasPrefix(line, "filter") { - filter += strings.TrimSpace(strings.TrimPrefix(line, "filter")) + ";" - if strings.Contains(line, ";") { - panic("Invalid config file syntax") - } - } - if strings.HasPrefix(line, "autosense") { - obj.autosense = strings.TrimSpace(strings.TrimPrefix(line, "autosense")) - } - if strings.HasPrefix(line, "}") { - obj.Filter = strings.TrimSuffix(filter, ";") - break - } - } - - allResponders = append(allResponders, &obj) - } else if strings.HasPrefix(line, "proxy") && strings.Contains(line, "{") { - obj := configProxy{} - filter := "" - for { - if !scanner.Scan() { - break - } - line = strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, "iface1") { - obj.Iface1 = strings.TrimSpace(strings.TrimPrefix(line, "iface1")) - } - if strings.HasPrefix(line, "iface2") { - obj.Iface2 = strings.TrimSpace(strings.TrimPrefix(line, "iface2")) - } - if strings.HasPrefix(line, "filter") { - filter += strings.TrimSpace(strings.TrimPrefix(line, "filter")) + ";" - if strings.Contains(line, ";") { - panic("Invalid config file syntax") - } - } - if strings.HasPrefix(line, "autosense") { - obj.autosense = strings.TrimSpace(strings.TrimPrefix(line, "autosense")) - } - if strings.HasPrefix(line, "}") { - obj.Filter = strings.TrimSuffix(filter, ";") - break - } - if strings.HasPrefix(line, "}") { - break - } - } - allProxies = append(allProxies, &obj) - } else if strings.Contains(line, "{") { + if strings.HasSuffix(line, "{") { option := strings.TrimSuffix(strings.TrimSpace(line), "{") option = strings.TrimSpace(option) - if modules.ModuleList != nil { - for i := range modules.ModuleList { - for d := range (*modules.ModuleList[i]).Option { - if (*modules.ModuleList[i]).Option[d].Option == option { - var lines []string - for { - if !scanner.Scan() { - break - } - line = strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, "}") { - break - } - lines = append(lines, line) - } - (*modules.ModuleList[i]).Callback(modules.Callback{ - CallbackType: modules.Config, - Option: option, - Arguments: lines, - }) - return - } + module, command := modules.GetCommand(option) + var lines = make([]string, 0) + if module != nil { + for { + if !scanner.Scan() { + break } + line := strings.TrimSpace(scanner.Text()) + if strings.Contains(line, "}") { + break + } + + lines = append(lines, line) } + modules.ExecuteInit(module, modules.CallbackInfo{ + CallbackType: modules.Config, + Command: command, + Arguments: lines, + }) } } + + } + if modules.ExistsBlockingModule() { + modules.ExecuteComplete() + waitForSignal() + modules.ShutdownAll() } if err := scanner.Err(); err != nil { - log.Fatal(err) - } - - for _, n := range allProxies { - o := pndp.NewProxy(n.Iface1, n.Iface2, pndp.ParseFilter(n.Filter), n.autosense) - n.instance = o - o.Start() - } - - for _, n := range allResponders { - o := pndp.NewResponder(n.Iface, pndp.ParseFilter(n.Filter), n.autosense) - n.instance = o - o.Start() - } - - WaitForSignal() - - for _, n := range allProxies { - n.instance.Stop() - } - - for _, n := range allResponders { - n.instance.Stop() + panic(err) } } diff --git a/main.go b/main.go index 6ea0347..54de121 100644 --- a/main.go +++ b/main.go @@ -5,12 +5,12 @@ import ( "os" "os/signal" "pndpd/modules" - "pndpd/pndp" + _ "pndpd/modules/userInterface" "syscall" ) -// WaitForSignal Waits (blocking) for the program to be interrupted by the OS -func WaitForSignal() { +// waitForSignal Waits (blocking) for the program to be interrupted by the OS +func waitForSignal() { var sigCh = make(chan os.Signal, 1) signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) <-sigCh @@ -18,57 +18,32 @@ func WaitForSignal() { } func main() { - fmt.Println("PNDPD Version 1.2 - Kioubit 2021") - if modules.ModuleList != nil { - fmt.Print("Loaded Modules: Core ") - for i := range modules.ModuleList { - fmt.Print((*modules.ModuleList[i]).Name + " ") - } - fmt.Println() - } + fmt.Println("PNDPD Version 1.2.1 - Kioubit 2021") if len(os.Args) <= 2 { printUsage() return } + switch os.Args[1] { - case "respond": - var r *pndp.ResponderObj - if len(os.Args) == 4 { - r = pndp.NewResponder(os.Args[2], pndp.ParseFilter(os.Args[3]), "") - r.Start() - } else { - r = pndp.NewResponder(os.Args[2], nil, "") - r.Start() - } - WaitForSignal() - r.Stop() - case "proxy": - var p *pndp.ProxyObj - if len(os.Args) == 5 { - p = pndp.NewProxy(os.Args[2], os.Args[3], pndp.ParseFilter(os.Args[4]), "") - } else { - p = pndp.NewProxy(os.Args[2], os.Args[3], nil, "") - } - WaitForSignal() - p.Stop() case "config": readConfig(os.Args[2]) default: - for i := range modules.ModuleList { - for d := range (*modules.ModuleList[i]).Option { - if (*modules.ModuleList[i]).Option[d].Option == os.Args[1] { - (*modules.ModuleList[i]).Callback(modules.Callback{ - CallbackType: modules.CommandLine, - Option: os.Args[1], - Arguments: os.Args[1:], - }) - return - } + module, command := modules.GetCommand(os.Args[1]) + if module != nil { + modules.ExecuteInit(module, modules.CallbackInfo{ + CallbackType: modules.CommandLine, + Command: command, + Arguments: os.Args[2:], + }) + if modules.ExistsBlockingModule() { + modules.ExecuteComplete() + waitForSignal() + modules.ShutdownAll() } + } else { + printUsage() } - printUsage() - return } } @@ -77,11 +52,9 @@ func printUsage() { fmt.Println("More options and additional documentation in the example config file") fmt.Println("Usage:") fmt.Println("pndpd config ") - fmt.Println("pndpd respond ") - fmt.Println("pndpd proxy ") for i := range modules.ModuleList { - for d := range (*modules.ModuleList[i]).Option { - fmt.Println((*modules.ModuleList[i]).Option[d].Description) + for d := range (*modules.ModuleList[i]).Commands { + fmt.Println("pndpd", (*modules.ModuleList[i]).Commands[d].Description) } } } diff --git a/modules/example/example.go b/modules/example/example.go index e0ec47e..c6407fc 100644 --- a/modules/example/example.go +++ b/modules/example/example.go @@ -7,29 +7,39 @@ import ( // This is an example module that is not imported by the main program func init() { - option := []modules.Option{{ - Option: "command1", - Description: "This is the usage description for command1", + commands := []modules.Command{{ + CommandText: "command1", + Description: "This is the usage description for command1", + BlockTerminate: true, }, { - Option: "command2", - Description: "This is the usage description for command2", + CommandText: "command2", + Description: "This is the usage description for command2", + BlockTerminate: false, }, } - modules.RegisterModule("Example", option, callback) + modules.RegisterModule("Example", commands, initCallback, completeCallback, shutdownCallback) } -func callback(callback modules.Callback) { +func initCallback(callback modules.CallbackInfo) { if callback.CallbackType == modules.CommandLine { // The command registered by the module has been run in the commandline // "arguments" contains the os.Args[] passed to the program after the command registered by this module - fmt.Println("Command: ", callback.Option) + fmt.Println("Command: ", callback.Command.CommandText) fmt.Println(callback.Arguments) } else { // The command registered by the module was found in the config file // "arguments" contains the lines between the curly braces - fmt.Println("Command: ", callback.Option) + fmt.Println("Command: ", callback.Command.CommandText) fmt.Println(callback.Arguments) } fmt.Println() } + +func completeCallback() { + //Called after the program has passed all options by calls to initCallback() +} + +func shutdownCallback() { + fmt.Println("Terminate all work") +} diff --git a/modules/modules.go b/modules/modules.go index 36d0be3..8ae3d60 100644 --- a/modules/modules.go +++ b/modules/modules.go @@ -3,14 +3,17 @@ package modules var ModuleList []*Module type Module struct { - Name string - Option []Option - Callback func(Callback) + Name string + Commands []Command + InitCallback func(CallbackInfo) + CompleteCallback func() + ShutdownCallback func() } -type Option struct { - Option string - Description string +type Command struct { + CommandText string + Description string + BlockTerminate bool } type CallbackType int @@ -20,16 +23,63 @@ const ( Config CallbackType = 1 ) -type Callback struct { +type CallbackInfo struct { CallbackType CallbackType - Option string + Command Command Arguments []string } -func RegisterModule(name string, option []Option, Callback func(Callback)) { +func RegisterModule(name string, commands []Command, initCallback func(CallbackInfo), CompleteCallback func(), shutdownCallback func()) { ModuleList = append(ModuleList, &Module{ - Name: name, - Option: option, - Callback: Callback, + Name: name, + Commands: commands, + InitCallback: initCallback, + CompleteCallback: CompleteCallback, + ShutdownCallback: shutdownCallback, }) } + +func GetCommand(target string) (*Module, Command) { + for i := range ModuleList { + for _, command := range ModuleList[i].Commands { + if command.CommandText == target { + return ModuleList[i], command + } + } + } + return nil, Command{} +} + +var runningModules []*Module + +func ExecuteInit(module *Module, info CallbackInfo) { + if info.Command.BlockTerminate { + found := false + for _, n := range runningModules { + if n == module { + found = true + break + } + } + if !found { + runningModules = append(runningModules, module) + } + } + module.InitCallback(info) +} + +func ExecuteComplete() { + for i := range runningModules { + (*runningModules[i]).CompleteCallback() + } +} + +func ShutdownAll() { + for i := range runningModules { + (*runningModules[i]).ShutdownCallback() + } +} + +func ExistsBlockingModule() bool { + return len(runningModules) != 0 +} diff --git a/modules/userInterface/userInterface.go b/modules/userInterface/userInterface.go new file mode 100644 index 0000000..0a883e7 --- /dev/null +++ b/modules/userInterface/userInterface.go @@ -0,0 +1,162 @@ +package userInterface + +import ( + "fmt" + "pndpd/modules" + "pndpd/pndp" + "strings" +) + +func init() { + commands := []modules.Command{{ + CommandText: "proxy", + Description: "proxy ", + BlockTerminate: true, + }, { + CommandText: "responder", + Description: "responder ", + BlockTerminate: true, + }, { + CommandText: "modules", + Description: "modules available - list available modules", + BlockTerminate: false, + }} + modules.RegisterModule("Core", commands, initCallback, completeCallback, shutdownCallback) +} + +type configResponder struct { + Iface string + Filter string + autosense string + instance *pndp.ResponderObj +} + +type configProxy struct { + Iface1 string + Iface2 string + Filter string + autosense string + instance *pndp.ProxyObj +} + +var allResponders []*configResponder +var allProxies []*configProxy + +func initCallback(callback modules.CallbackInfo) { + if callback.CallbackType == modules.CommandLine { + switch callback.Command.CommandText { + case "proxy": + if len(callback.Arguments) == 3 { + allProxies = append(allProxies, &configProxy{ + Iface1: callback.Arguments[0], + Iface2: callback.Arguments[1], + Filter: callback.Arguments[2], + autosense: "", + instance: nil, + }) + } else { + allProxies = append(allProxies, &configProxy{ + Iface1: callback.Arguments[0], + Iface2: callback.Arguments[1], + Filter: "", + autosense: "", + instance: nil, + }) + } + case "responder": + if len(callback.Arguments) == 2 { + allResponders = append(allResponders, &configResponder{ + Iface: callback.Arguments[0], + Filter: callback.Arguments[1], + autosense: "", + instance: nil, + }) + } else { + allResponders = append(allResponders, &configResponder{ + Iface: callback.Arguments[0], + Filter: "", + autosense: "", + instance: nil, + }) + } + case "modules": + if modules.ModuleList != nil { + fmt.Print("Available Modules: ") + for i := range modules.ModuleList { + fmt.Print((*modules.ModuleList[i]).Name + " ") + } + fmt.Println() + } + + } + + } else { + switch callback.Command.CommandText { + case "proxy": + obj := configProxy{} + filter := "" + for _, n := range callback.Arguments { + if strings.HasPrefix(n, "iface1") { + obj.Iface1 = strings.TrimSpace(strings.TrimPrefix(n, "iface1")) + } + if strings.HasPrefix(n, "iface2") { + obj.Iface2 = strings.TrimSpace(strings.TrimPrefix(n, "iface2")) + } + if strings.HasPrefix(n, "filter") { + filter += strings.TrimSpace(strings.TrimPrefix(n, "filter")) + ";" + if strings.Contains(n, ";") { + panic("Invalid config file syntax") + } + } + if strings.HasPrefix(n, "autosense") { + obj.autosense = strings.TrimSpace(strings.TrimPrefix(n, "autosense")) + } + } + obj.Filter = strings.TrimSuffix(filter, ";") + allProxies = append(allProxies, &obj) + case "responder": + obj := configResponder{} + filter := "" + for _, n := range callback.Arguments { + if strings.HasPrefix(n, "iface") { + obj.Iface = strings.TrimSpace(strings.TrimPrefix(n, "iface")) + } + if strings.HasPrefix(n, "filter") { + filter += strings.TrimSpace(strings.TrimPrefix(n, "filter")) + ";" + if strings.Contains(n, ";") { + panic("Invalid config file syntax") + } + } + if strings.HasPrefix(n, "autosense") { + obj.autosense = strings.TrimSpace(strings.TrimPrefix(n, "autosense")) + } + + } + obj.Filter = strings.TrimSuffix(filter, ";") + allResponders = append(allResponders, &obj) + + } + } +} + +func completeCallback() { + for _, n := range allProxies { + o := pndp.NewProxy(n.Iface1, n.Iface2, pndp.ParseFilter(n.Filter), n.autosense) + n.instance = o + o.Start() + } + for _, n := range allResponders { + o := pndp.NewResponder(n.Iface, pndp.ParseFilter(n.Filter), n.autosense) + n.instance = o + o.Start() + } +} +func shutdownCallback() { + for _, n := range allProxies { + n.instance.Stop() + } + + for _, n := range allResponders { + n.instance.Stop() + } +}