From c83d10b6813d171bf349da71256d719b9148bde4 Mon Sep 17 00:00:00 2001 From: jwijenbergh Date: Tue, 5 Apr 2022 10:05:32 +0200 Subject: Add debug variable to save a live fsm graph --- src/fsm.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/state.go | 28 +++++++++++++++---------- 2 files changed, 84 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/fsm.go b/src/fsm.go index 9978fde..2b61cda 100644 --- a/src/fsm.go +++ b/src/fsm.go @@ -2,6 +2,7 @@ package eduvpn import ( "errors" + "os" ) type FSMStateID int8 @@ -152,18 +153,84 @@ func (eduvpn *VPNState) HasTransition(check FSMStateID) bool { return ok && fsm != nil } +func (eduvpn *VPNState) InState(check FSMStateID) bool { + fsm := FindFSMState(check, eduvpn.FSM) + + if fsm == nil { + return false + } + + return fsm.Current == check +} + +func (eduvpn *VPNState) writeGraph() { + graph := eduvpn.GenerateGraph() + + f, err := os.Create("debug.graph") + + if err != nil { + panic(err) + } + + defer f.Close() + + f.WriteString(graph) +} + func (eduvpn *VPNState) GoTransition(newState FSMStateID, data string) bool { fsm, ok := eduvpn.findTransition(newState) if ok { oldState := fsm.Current fsm.Current = newState + if eduvpn.Debug { + eduvpn.writeGraph() + } eduvpn.StateCallback(oldState.String(), newState.String(), data) } return ok } +func getGraphviz(fsm *FSM, graph string) string { + if fsm == nil { + return graph + } + + for name, state := range fsm.States { + for _, transition := range state.Transition { + graph += "\n" + "cluster_" + name.String() + " -> cluster_" + transition.String() + } + + graph += "\nsubgraph cluster_" + name.String() + "{\n" + if (state.Locked) { + graph += "style=\"dotted\"\n" + } else { + graph += "style=\"\"\n" + } + if (fsm.Current == name) { + graph += "color=\"blue\"\n" + graph += "fontcolor=\"blue\"\n" + } else { + graph += "color=\"\"\n" + graph += "fontcolor=\"\"\n" + } + graph += "label=" + name.String() + graph = getGraphviz(state.Sub, graph) + graph += "\n}" + } + return graph +} + +func (eduvpn *VPNState) GenerateGraph() string { + graph := "digraph fsm {\n" + graph += "nodesep=2" + graph = getGraphviz(eduvpn.FSM, graph) + graph += "\n}" + + return graph +} + func (eduvpn *VPNState) InitializeFSM() { // The states when a server is authenticated serverAuthenticated := &FSMState{Sub: &FSM{States: FSMStates{ diff --git a/src/state.go b/src/state.go index aa31513..ec927f9 100644 --- a/src/state.go +++ b/src/state.go @@ -19,29 +19,36 @@ type VPNState struct { // The file we keep open for logging LogFile *FileLogger `json:"-"` + // The fsm FSM *FSM `json:"-"` + + // Whether to enable debugging + Debug bool `json:"-"` } -func (state *VPNState) Register(name string, directory string, stateCallback func(string, string, string)) error { - if state.FSM == nil { - state.InitializeFSM() - } +func (state *VPNState) Register(name string, directory string, stateCallback func(string, string, string), debug bool) error { + state.InitializeFSM() if !state.HasTransition(APP_REGISTERED) { return errors.New("app already registered") } state.Name = name state.ConfigDirectory = directory state.StateCallback = stateCallback + state.Debug = debug - // Initialize the logger - // state.InitLog(LOG_WARNING) + LogLevel := LOG_WARNING - // state.Log(LOG_INFO, "App registered") + if debug { + LogLevel = LOG_INFO + } + + // Initialize the logger + state.InitLog(LogLevel) // Try to load the previous configuration if state.LoadConfig() != nil { // This error can be safely ignored, as when the config does not load, the struct will not be filled - // state.Log(LOG_INFO, "Previous configuration not found") + state.Log(LOG_INFO, "Previous configuration not found") } state.GoTransition(APP_REGISTERED, "HALLO") return nil @@ -54,9 +61,8 @@ func (state *VPNState) Deregister() error { // Close the log file state.CloseLog() - // Re-initialize everything - state = &VPNState{} - state.GoTransition(APP_DEREGISTERED, "") + state.Server = &Server{} + state.InitializeFSM() return nil } -- cgit v1.2.3