diff options
| author | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-09-07 18:41:01 +0200 |
|---|---|---|
| committer | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-09-07 18:41:01 +0200 |
| commit | 7f7b6884d11e0e2b891814b84eb906db284a50b0 (patch) | |
| tree | ed3f2ec29b5efda3fbb628a09628464d98fce336 | |
| parent | 809bc265d11b508903313f5b0a8c1a04add7209b (diff) | |
Refactor: Define FSM state constants inside the public package
| -rw-r--r-- | cmd/cli/main.go | 14 | ||||
| -rw-r--r-- | exports/exports.go | 8 | ||||
| -rw-r--r-- | fsm.go | 237 | ||||
| -rw-r--r-- | internal/fsm/fsm.go | 238 | ||||
| -rw-r--r-- | state.go | 129 | ||||
| -rw-r--r-- | state_test.go | 19 |
6 files changed, 334 insertions, 311 deletions
diff --git a/cmd/cli/main.go b/cmd/cli/main.go index e900585..4561517 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/jwijenbergh/eduvpn-common" - "github.com/jwijenbergh/eduvpn-common/internal/fsm" "github.com/jwijenbergh/eduvpn-common/internal/server" ) @@ -94,16 +93,15 @@ func sendProfile(state *eduvpn.VPNState, data interface{}) { // Note that this has an additional argument, the vpn state which was wrapped into this callback function below func stateCallback( state *eduvpn.VPNState, - oldState eduvpn.StateID, - newState eduvpn.StateID, + oldState eduvpn.FSMStateID, + newState eduvpn.FSMStateID, data interface{}, ) { - // TODO: Remove internal usage of fsm - if newState == fsm.OAUTH_STARTED { + if newState == eduvpn.STATE_OAUTH_STARTED { openBrowser(data) } - if newState == fsm.ASK_PROFILE { + if newState == eduvpn.STATE_ASK_PROFILE { sendProfile(state, data) } } @@ -177,7 +175,7 @@ func getSecureInternetAll(homeURL string) { state.Register( "org.eduvpn.app.linux", "configs", - func(old eduvpn.StateID, new eduvpn.StateID, data interface{}) { + func(old eduvpn.FSMStateID, new eduvpn.FSMStateID, data interface{}) { stateCallback(state, old, new, data) }, true, @@ -223,7 +221,7 @@ func printConfig(url string, serverType ServerTypes) { state.Register( "org.eduvpn.app.linux", "configs", - func(old eduvpn.StateID, new eduvpn.StateID, data interface{}) { + func(old eduvpn.FSMStateID, new eduvpn.FSMStateID, data interface{}) { stateCallback(state, old, new, data) }, true, diff --git a/exports/exports.go b/exports/exports.go index e2b02a1..daf84bb 100644 --- a/exports/exports.go +++ b/exports/exports.go @@ -28,8 +28,8 @@ var VPNStates map[string]*eduvpn.VPNState func StateCallback( name string, - old_state eduvpn.StateID, - new_state eduvpn.StateID, + old_state eduvpn.FSMStateID, + new_state eduvpn.FSMStateID, data interface{}, ) { P_StateCallback, exists := P_StateCallbacks[name] @@ -86,7 +86,7 @@ func Register( registerErr := state.Register( nameStr, C.GoString(config_directory), - func(old eduvpn.StateID, new eduvpn.StateID, data interface{}) { + func(old eduvpn.FSMStateID, new eduvpn.FSMStateID, data interface{}) { StateCallback(nameStr, old, new, data) }, debug != 0, @@ -367,7 +367,7 @@ func InFSMState(name *C.char, checkState C.int) C.int { if stateErr != nil { return C.int(0) } - inStateBool := state.InFSMState(eduvpn.StateID(checkState)) + inStateBool := state.InFSMState(eduvpn.FSMStateID(checkState)) if inStateBool { return C.int(1) } @@ -0,0 +1,237 @@ +package eduvpn + +import ( + "errors" + "fmt" + "github.com/jwijenbergh/eduvpn-common/internal/fsm" + "github.com/jwijenbergh/eduvpn-common/internal/types" +) + +type FSMStateID = fsm.FSMStateID +type FSMStates = fsm.FSMStates +type FSMState = fsm.FSMState +type FSMTransition = fsm.FSMTransition + +const ( + // Deregistered means the app is not registered with the wrapper + STATE_DEREGISTERED FSMStateID = iota + + // No Server means the user has not chosen a server yet + STATE_NO_SERVER + + // The user selected a Secure Internet server but needs to choose a location + STATE_ASK_LOCATION + + // The user is currently selecting a server in the UI + STATE_SEARCH_SERVER + + // We are loading the server details + STATE_LOADING_SERVER + + // Chosen Server means the user has chosen a server to connect to + STATE_CHOSEN_SERVER + + // OAuth Started means the OAuth process has started + STATE_OAUTH_STARTED + + // Authorized means the OAuth process has finished and the user is now authorized with the server + STATE_AUTHORIZED + + // Requested config means the user has requested a config for connecting + STATE_REQUEST_CONFIG + + // Ask profile means the go code is asking for a profile selection from the UI + STATE_ASK_PROFILE + + // Disconnected means the user has gotten a config for a server but is not connected yet + STATE_DISCONNECTED + + // Disconnecting means the OS is disconnecting and the Go code is doing the /disconnect + STATE_DISCONNECTING + + // Connecting means the OS is establishing a connection to the server + STATE_CONNECTING + + // Connected means the user has been connected to the server + STATE_CONNECTED +) + +func GetStateName(s FSMStateID) string { + switch s { + case STATE_DEREGISTERED: + return "Deregistered" + case STATE_NO_SERVER: + return "No_Server" + case STATE_ASK_LOCATION: + return "Ask_Location" + case STATE_SEARCH_SERVER: + return "Search_Server" + case STATE_LOADING_SERVER: + return "Loading_Server" + case STATE_CHOSEN_SERVER: + return "Chosen_Server" + case STATE_OAUTH_STARTED: + return "OAuth_Started" + case STATE_DISCONNECTED: + return "Disconnected" + case STATE_REQUEST_CONFIG: + return "Request_Config" + case STATE_ASK_PROFILE: + return "Ask_Profile" + case STATE_AUTHORIZED: + return "Authorized" + case STATE_DISCONNECTING: + return "Disconnecting" + case STATE_CONNECTING: + return "Connecting" + case STATE_CONNECTED: + return "Connected" + default: + panic("unknown conversion of state to string") + } +} + +func newFSM(name string, callback func(FSMStateID, FSMStateID, interface{}), directory string, debug bool) fsm.FSM { + states := FSMStates{ + STATE_DEREGISTERED: FSMState{Transitions: []FSMTransition{{STATE_NO_SERVER, "Client registers"}}}, + STATE_NO_SERVER: FSMState{ + Transitions: []FSMTransition{ + {STATE_NO_SERVER, "Reload list"}, + {STATE_CHOSEN_SERVER, "User chooses a server"}, + {STATE_SEARCH_SERVER, "The user is trying to choose a Server in the UI"}, + {STATE_CONNECTED, "The user is already connected"}, + {STATE_ASK_LOCATION, "Change the location in the main screen"}, + }, + }, + STATE_SEARCH_SERVER: FSMState{ + Transitions: []FSMTransition{ + {STATE_LOADING_SERVER, "User clicks a server in the UI"}, + {STATE_NO_SERVER, "Cancel or Error"}, + }, + BackState: STATE_NO_SERVER, + }, + STATE_ASK_LOCATION: FSMState{ + Transitions: []FSMTransition{ + {STATE_CHOSEN_SERVER, "Location chosen"}, + {STATE_NO_SERVER, "Go back or Error"}, + {STATE_SEARCH_SERVER, "Cancel or Error"}, + }, + }, + STATE_LOADING_SERVER: FSMState{ + Transitions: []FSMTransition{ + {STATE_CHOSEN_SERVER, "Server info loaded"}, + { + STATE_ASK_LOCATION, + "User chooses a Secure Internet server but no location is configured", + }, + {STATE_NO_SERVER, "Go back or Error"}, + }, + BackState: STATE_NO_SERVER, + }, + STATE_CHOSEN_SERVER: FSMState{ + Transitions: []FSMTransition{ + {STATE_AUTHORIZED, "Found tokens in config"}, + {STATE_OAUTH_STARTED, "No tokens found in config"}, + }, + }, + STATE_OAUTH_STARTED: FSMState{ + Transitions: []FSMTransition{ + {STATE_AUTHORIZED, "User authorizes with browser"}, + {STATE_NO_SERVER, "Cancel or Error"}, + {STATE_SEARCH_SERVER, "Cancel or Error"}, + }, + BackState: STATE_NO_SERVER, + }, + STATE_AUTHORIZED: FSMState{ + Transitions: []FSMTransition{ + {STATE_OAUTH_STARTED, "Re-authorize with OAuth"}, + {STATE_REQUEST_CONFIG, "Client requests a config"}, + }, + }, + STATE_REQUEST_CONFIG: FSMState{ + Transitions: []FSMTransition{ + {STATE_ASK_PROFILE, "Multiple profiles found and no profile chosen"}, + {STATE_DISCONNECTED, "Only one profile or profile already chosen"}, + {STATE_NO_SERVER, "Cancel or Error"}, + {STATE_OAUTH_STARTED, "Re-authorize"}, + }, + }, + STATE_ASK_PROFILE: FSMState{ + Transitions: []FSMTransition{ + {STATE_DISCONNECTED, "User chooses profile"}, + {STATE_NO_SERVER, "Cancel or Error"}, + {STATE_SEARCH_SERVER, "Cancel or Error"}, + }, + }, + STATE_DISCONNECTED: FSMState{ + Transitions: []FSMTransition{ + {STATE_CONNECTING, "OS reports it is trying to connect"}, + {STATE_REQUEST_CONFIG, "User reconnects"}, + {STATE_NO_SERVER, "User wants to choose a new server"}, + {STATE_OAUTH_STARTED, "Re-authorize with OAuth"}, + }, + BackState: STATE_NO_SERVER, + }, + STATE_DISCONNECTING: FSMState{ + Transitions: []FSMTransition{ + {STATE_DISCONNECTED, "Cancel or Error"}, + {STATE_DISCONNECTED, "Done disconnecting"}, + }, + }, + STATE_CONNECTING: FSMState{ + Transitions: []FSMTransition{ + {STATE_DISCONNECTED, "Cancel or Error"}, + {STATE_CONNECTED, "Done connecting"}, + }, + }, + STATE_CONNECTED: FSMState{ + Transitions: []FSMTransition{{STATE_DISCONNECTING, "App wants to disconnect"}}, + }, + } + returnedFSM := fsm.FSM{} + returnedFSM.Init(name, STATE_DEREGISTERED, states, callback, directory, GetStateName, debug) + return returnedFSM +} + +type FSMDeregisteredError struct{} + +func (e FSMDeregisteredError) CustomError() *types.WrappedErrorMessage { + return &types.WrappedErrorMessage{ + Message: "Client not registered with the GO library", + Err: errors.New( + "the current FSM state is deregistered, but the function needs a state that is not deregistered", + ), + } +} + +type FSMWrongStateTransitionError struct { + Got FSMStateID + Want FSMStateID +} + +func (e FSMWrongStateTransitionError) CustomError() *types.WrappedErrorMessage { + return &types.WrappedErrorMessage{ + Message: "Wrong FSM transition", + Err: errors.New( + fmt.Sprintf( + "wrong FSM state, got: %s, want: a state with a transition to: %s", + GetStateName(e.Got), + GetStateName(e.Want), + ), + ), + } +} + +type FSMWrongStateError struct { + Got FSMStateID + Want FSMStateID +} + +func (e FSMWrongStateError) CustomError() *types.WrappedErrorMessage { + return &types.WrappedErrorMessage{ + Message: "Wrong FSM State", + Err: errors.New( + fmt.Sprintf("wrong FSM state, got: %s, want: %s", GetStateName(e.Got), GetStateName(e.Want)), + ), + } +} diff --git a/internal/fsm/fsm.go b/internal/fsm/fsm.go index 6178af9..63c9ac2 100644 --- a/internal/fsm/fsm.go +++ b/internal/fsm/fsm.go @@ -1,14 +1,11 @@ package fsm import ( - "errors" - "fmt" "os" "os/exec" + "fmt" "path" "sort" - - "github.com/jwijenbergh/eduvpn-common/internal/types" ) type ( @@ -28,85 +25,6 @@ func (v FSMStateIDSlice) Swap(i, j int) { v[i], v[j] = v[j], v[i] } -const ( - // Deregistered means the app is not registered with the wrapper - DEREGISTERED FSMStateID = iota - - // No Server means the user has not chosen a server yet - NO_SERVER - - // The user selected a Secure Internet server but needs to choose a location - ASK_LOCATION - - // The user is currently selecting a server in the UI - SEARCH_SERVER - - // We are loading the server details - LOADING_SERVER - - // Chosen Server means the user has chosen a server to connect to - CHOSEN_SERVER - - // OAuth Started means the OAuth process has started - OAUTH_STARTED - - // Authorized means the OAuth process has finished and the user is now authorized with the server - AUTHORIZED - - // Requested config means the user has requested a config for connecting - REQUEST_CONFIG - - // Ask profile means the go code is asking for a profile selection from the UI - ASK_PROFILE - - // Disconnected means the user has gotten a config for a server but is not connected yet - DISCONNECTED - - // Disconnecting means the OS is disconnecting and the Go code is doing the /disconnect - DISCONNECTING - - // Connecting means the OS is establishing a connection to the server - CONNECTING - - // Connected means the user has been connected to the server - CONNECTED -) - -func (s FSMStateID) String() string { - switch s { - case DEREGISTERED: - return "Deregistered" - case NO_SERVER: - return "No_Server" - case ASK_LOCATION: - return "Ask_Location" - case SEARCH_SERVER: - return "Search_Server" - case LOADING_SERVER: - return "Loading_Server" - case CHOSEN_SERVER: - return "Chosen_Server" - case OAUTH_STARTED: - return "OAuth_Started" - case DISCONNECTED: - return "Disconnected" - case REQUEST_CONFIG: - return "Request_Config" - case ASK_PROFILE: - return "Ask_Profile" - case AUTHORIZED: - return "Authorized" - case DISCONNECTING: - return "Disconnecting" - case CONNECTING: - return "Connecting" - case CONNECTED: - return "Connected" - default: - panic("unknown conversion of state to string") - } -} - type FSMTransition struct { To FSMStateID Description string @@ -132,114 +50,24 @@ type FSM struct { StateCallback func(FSMStateID, FSMStateID, interface{}) Directory string Debug bool + GetName func(FSMStateID) string } func (fsm *FSM) Init( name string, + current FSMStateID, + states map[FSMStateID]FSMState, callback func(FSMStateID, FSMStateID, interface{}), directory string, + nameGen func(FSMStateID) string, debug bool, ) { - fsm.States = FSMStates{ - DEREGISTERED: FSMState{Transitions: []FSMTransition{{NO_SERVER, "Client registers"}}}, - NO_SERVER: FSMState{ - Transitions: []FSMTransition{ - {NO_SERVER, "Reload list"}, - {CHOSEN_SERVER, "User chooses a server"}, - {SEARCH_SERVER, "The user is trying to choose a Server in the UI"}, - {CONNECTED, "The user is already connected"}, - {ASK_LOCATION, "Change the location in the main screen"}, - }, - }, - SEARCH_SERVER: FSMState{ - Transitions: []FSMTransition{ - {LOADING_SERVER, "User clicks a server in the UI"}, - {NO_SERVER, "Cancel or Error"}, - }, - BackState: NO_SERVER, - }, - ASK_LOCATION: FSMState{ - Transitions: []FSMTransition{ - {CHOSEN_SERVER, "Location chosen"}, - {NO_SERVER, "Go back or Error"}, - {SEARCH_SERVER, "Cancel or Error"}, - }, - }, - LOADING_SERVER: FSMState{ - Transitions: []FSMTransition{ - {CHOSEN_SERVER, "Server info loaded"}, - { - ASK_LOCATION, - "User chooses a Secure Internet server but no location is configured", - }, - {NO_SERVER, "Go back or Error"}, - }, - BackState: NO_SERVER, - }, - CHOSEN_SERVER: FSMState{ - Transitions: []FSMTransition{ - {AUTHORIZED, "Found tokens in config"}, - {OAUTH_STARTED, "No tokens found in config"}, - }, - }, - OAUTH_STARTED: FSMState{ - Transitions: []FSMTransition{ - {AUTHORIZED, "User authorizes with browser"}, - {NO_SERVER, "Cancel or Error"}, - {SEARCH_SERVER, "Cancel or Error"}, - }, - BackState: NO_SERVER, - }, - AUTHORIZED: FSMState{ - Transitions: []FSMTransition{ - {OAUTH_STARTED, "Re-authorize with OAuth"}, - {REQUEST_CONFIG, "Client requests a config"}, - }, - }, - REQUEST_CONFIG: FSMState{ - Transitions: []FSMTransition{ - {ASK_PROFILE, "Multiple profiles found and no profile chosen"}, - {DISCONNECTED, "Only one profile or profile already chosen"}, - {NO_SERVER, "Cancel or Error"}, - {OAUTH_STARTED, "Re-authorize"}, - }, - }, - ASK_PROFILE: FSMState{ - Transitions: []FSMTransition{ - {DISCONNECTED, "User chooses profile"}, - {NO_SERVER, "Cancel or Error"}, - {SEARCH_SERVER, "Cancel or Error"}, - }, - }, - DISCONNECTED: FSMState{ - Transitions: []FSMTransition{ - {CONNECTING, "OS reports it is trying to connect"}, - {REQUEST_CONFIG, "User reconnects"}, - {NO_SERVER, "User wants to choose a new server"}, - {OAUTH_STARTED, "Re-authorize with OAuth"}, - }, - BackState: NO_SERVER, - }, - DISCONNECTING: FSMState{ - Transitions: []FSMTransition{ - {DISCONNECTED, "Cancel or Error"}, - {DISCONNECTED, "Done disconnecting"}, - }, - }, - CONNECTING: FSMState{ - Transitions: []FSMTransition{ - {DISCONNECTED, "Cancel or Error"}, - {CONNECTED, "Done connecting"}, - }, - }, - CONNECTED: FSMState{ - Transitions: []FSMTransition{{DISCONNECTING, "App wants to disconnect"}}, - }, - } - fsm.Current = DEREGISTERED + fsm.States = states + fsm.Current = current fsm.Name = name fsm.StateCallback = callback fsm.Directory = directory + fsm.GetName = nameGen fsm.Debug = debug } @@ -317,59 +145,21 @@ func (fsm *FSM) generateMermaidGraph() string { transitions := fsm.States[state].Transitions for _, transition := range transitions { if state == fsm.Current { - graph += "\nstyle " + state.String() + " fill:cyan\n" + graph += "\nstyle " + fsm.GetName(state) + " fill:cyan\n" } else { - graph += "\nstyle " + state.String() + " fill:white\n" + graph += "\nstyle " + fsm.GetName(state) + " fill:white\n" } - graph += state.String() + "(" + state.String() + ") " + "-->|" + transition.Description + "| " + transition.To.String() + "\n" + graph += fsm.GetName(state) + "(" + fsm.GetName(state) + ") " + "-->|" + transition.Description + "| " + fsm.GetName(transition.To) + "\n" } } return graph } func (fsm *FSM) GenerateGraph() string { - return fsm.generateMermaidGraph() -} - -type DeregisteredError struct{} - -func (e DeregisteredError) CustomError() *types.WrappedErrorMessage { - return &types.WrappedErrorMessage{ - Message: "Client not registered with the GO library", - Err: errors.New( - "the current FSM state is deregistered, but the function needs a state that is not deregistered", - ), + if fsm.GetName != nil { + return fsm.generateMermaidGraph() } -} - -type WrongStateTransitionError struct { - Got FSMStateID - Want FSMStateID -} - -func (e WrongStateTransitionError) CustomError() *types.WrappedErrorMessage { - return &types.WrappedErrorMessage{ - Message: "Wrong FSM transition", - Err: errors.New( - fmt.Sprintf( - "wrong FSM state, got: %s, want: a state with a transition to: %s", - e.Got.String(), - e.Want.String(), - ), - ), - } -} -type WrongStateError struct { - Got FSMStateID - Want FSMStateID + return "" } -func (e WrongStateError) CustomError() *types.WrappedErrorMessage { - return &types.WrappedErrorMessage{ - Message: "Wrong FSM State", - Err: errors.New( - fmt.Sprintf("wrong FSM state, got: %s, want: %s", e.Got.String(), e.Want.String()), - ), - } -} @@ -15,7 +15,6 @@ import ( ) type ServerInfo = server.ServerInfoScreen -type StateID = fsm.FSMStateID type VPNState struct { // The chosen server @@ -44,14 +43,14 @@ func (state *VPNState) GetSavedServers() *server.ServersConfiguredScreen { func (state *VPNState) Register( name string, directory string, - stateCallback func(StateID, StateID, interface{}), + stateCallback func(FSMStateID, FSMStateID, interface{}), debug bool, ) error { errorMessage := "failed to register with the GO library" - if !state.InFSMState(fsm.DEREGISTERED) { + if !state.InFSMState(STATE_DEREGISTERED) { return &types.WrappedErrorMessage{ Message: errorMessage, - Err: fsm.DeregisteredError{}.CustomError(), + Err: FSMDeregisteredError{}.CustomError(), } } // Initialize the logger @@ -67,7 +66,7 @@ func (state *VPNState) Register( } // Initialize the FSM - state.FSM.Init(name, stateCallback, directory, debug) + state.FSM = newFSM(name, stateCallback, directory, debug) state.Debug = debug // Initialize the Config @@ -95,7 +94,7 @@ func (state *VPNState) Register( return &types.WrappedErrorMessage{Message: errorMessage, Err: discoOrgsErr} } // Go to the No Server state with the saved servers - state.FSM.GoTransitionWithData(fsm.NO_SERVER, state.GetSavedServers(), true) + state.FSM.GoTransitionWithData(STATE_NO_SERVER, state.GetSavedServers(), true) return nil } @@ -113,21 +112,21 @@ func (state *VPNState) Deregister() error { func (state *VPNState) GoBack() error { errorMessage := "failed to go back" - if state.InFSMState(fsm.DEREGISTERED) { + if state.InFSMState(STATE_DEREGISTERED) { return &types.WrappedErrorMessage{ Message: errorMessage, - Err: fsm.DeregisteredError{}.CustomError(), + Err: FSMDeregisteredError{}.CustomError(), } } // FIXME: Abitrary back transitions don't work because we need the approriate data - state.FSM.GoTransitionWithData(fsm.NO_SERVER, state.GetSavedServers(), false) + state.FSM.GoTransitionWithData(STATE_NO_SERVER, state.GetSavedServers(), false) // state.FSM.GoBack() return nil } func (state *VPNState) doAuth(authURL string) error { - state.FSM.GoTransitionWithData(fsm.OAUTH_STARTED, authURL, true) + state.FSM.GoTransitionWithData(STATE_OAUTH_STARTED, authURL, true) return nil } @@ -145,7 +144,7 @@ func (state *VPNState) ensureLogin(chosenServer server.Server) error { } } // OAuth was valid, ensure we are in the authorized state - state.FSM.GoTransition(fsm.AUTHORIZED) + state.FSM.GoTransition(STATE_AUTHORIZED) return nil } @@ -154,7 +153,7 @@ func (state *VPNState) getConfigAuth(chosenServer server.Server, forceTCP bool) if loginErr != nil { return "", "", loginErr } - state.FSM.GoTransition(fsm.REQUEST_CONFIG) + state.FSM.GoTransition(STATE_REQUEST_CONFIG) validProfile, profileErr := server.HasValidProfile(chosenServer) if profileErr != nil { @@ -198,10 +197,10 @@ func (state *VPNState) getConfig( forceTCP bool, ) (string, string, error) { errorMessage := "failed to get a configuration for OpenVPN/Wireguard" - if state.InFSMState(fsm.DEREGISTERED) { + if state.InFSMState(STATE_DEREGISTERED) { return "", "", &types.WrappedErrorMessage{ Message: errorMessage, - Err: fsm.DeregisteredError{}.CustomError(), + Err: FSMDeregisteredError{}.CustomError(), } } @@ -214,7 +213,7 @@ func (state *VPNState) getConfig( } // Signal the server display info - state.FSM.GoTransitionWithData(fsm.DISCONNECTED, state.getServerInfoData(), false) + state.FSM.GoTransitionWithData(STATE_DISCONNECTED, state.getServerInfoData(), false) // Save the config state.Config.Save(&state) @@ -243,7 +242,7 @@ func (state *VPNState) askProfile(chosenServer server.Server) error { if baseErr != nil { return &types.WrappedErrorMessage{Message: "failed asking for profiles", Err: baseErr} } - state.FSM.GoTransitionWithData(fsm.ASK_PROFILE, &base.Profiles, false) + state.FSM.GoTransitionWithData(STATE_ASK_PROFILE, &base.Profiles, false) return nil } @@ -251,10 +250,10 @@ func (state *VPNState) askSecureLocation() error { locations := state.Discovery.GetSecureLocationList() // Ask for the location in the callback - state.FSM.GoTransitionWithData(fsm.ASK_LOCATION, locations, false) + state.FSM.GoTransitionWithData(STATE_ASK_LOCATION, locations, false) // The state has changed, meaning setting the secure location was not successful - if state.FSM.Current != fsm.ASK_LOCATION { + if state.FSM.Current != STATE_ASK_LOCATION { // TODO: maybe a custom type for this errors.new? return &types.WrappedErrorMessage{Message: "failed setting secure location", Err: errors.New("failed setting secure location due to state change")} } @@ -296,45 +295,45 @@ func (state *VPNState) addSecureInternetHomeServer(orgID string) (server.Server, } func (state *VPNState) RemoveSecureInternet() error { - if state.InFSMState(fsm.DEREGISTERED) { + if state.InFSMState(STATE_DEREGISTERED) { return &types.WrappedErrorMessage{ Message: "failed to remove Secure Internet", - Err: fsm.DeregisteredError{}.CustomError(), + Err: FSMDeregisteredError{}.CustomError(), } } // No error because we can only have one secure internet server and if there are no secure internet servers, this is a NO-OP state.Servers.RemoveSecureInternet() - state.FSM.GoTransitionWithData(fsm.NO_SERVER, state.GetSavedServers(), false) + state.FSM.GoTransitionWithData(STATE_NO_SERVER, state.GetSavedServers(), false) // Save the config state.Config.Save(&state) return nil } func (state *VPNState) RemoveInstituteAccess(url string) error { - if state.InFSMState(fsm.DEREGISTERED) { + if state.InFSMState(STATE_DEREGISTERED) { return &types.WrappedErrorMessage{ Message: "failed to remove Institute Access", - Err: fsm.DeregisteredError{}.CustomError(), + Err: FSMDeregisteredError{}.CustomError(), } } // No error because this is a NO-OP if the server doesn't exist state.Servers.RemoveInstituteAccess(url) - state.FSM.GoTransitionWithData(fsm.NO_SERVER, state.GetSavedServers(), false) + state.FSM.GoTransitionWithData(STATE_NO_SERVER, state.GetSavedServers(), false) // Save the config state.Config.Save(&state) return nil } func (state *VPNState) RemoveCustomServer(url string) error { - if state.InFSMState(fsm.DEREGISTERED) { + if state.InFSMState(STATE_DEREGISTERED) { return &types.WrappedErrorMessage{ Message: "failed to remove Custom Server", - Err: fsm.DeregisteredError{}.CustomError(), + Err: FSMDeregisteredError{}.CustomError(), } } // No error because this is a NO-OP if the server doesn't exist state.Servers.RemoveCustomServer(url) - state.FSM.GoTransitionWithData(fsm.NO_SERVER, state.GetSavedServers(), false) + state.FSM.GoTransitionWithData(STATE_NO_SERVER, state.GetSavedServers(), false) // Save the config state.Config.Save(&state) return nil @@ -348,7 +347,7 @@ func (state *VPNState) GetConfigSecureInternet( "failed getting a configuration for Secure Internet organization %s", orgID, ) - state.FSM.GoTransition(fsm.LOADING_SERVER) + state.FSM.GoTransition(STATE_LOADING_SERVER) server, serverErr := state.addSecureInternetHomeServer(orgID) if serverErr != nil { @@ -356,7 +355,7 @@ func (state *VPNState) GetConfigSecureInternet( return "", "", &types.WrappedErrorMessage{Message: errorMessage, Err: serverErr} } - state.FSM.GoTransition(fsm.CHOSEN_SERVER) + state.FSM.GoTransition(STATE_CHOSEN_SERVER) return state.getConfig(server, forceTCP) } @@ -374,7 +373,7 @@ func (state *VPNState) addInstituteServer(url string) (server.Server, error) { return nil, &types.WrappedErrorMessage{Message: errorMessage, Err: serverErr} } - state.FSM.GoTransition(fsm.CHOSEN_SERVER) + state.FSM.GoTransition(STATE_CHOSEN_SERVER) return server, nil } @@ -402,14 +401,14 @@ func (state *VPNState) addCustomServer(url string) (server.Server, error) { return nil, &types.WrappedErrorMessage{Message: errorMessage, Err: serverErr} } - state.FSM.GoTransition(fsm.CHOSEN_SERVER) + state.FSM.GoTransition(STATE_CHOSEN_SERVER) return server, nil } func (state *VPNState) GetConfigInstituteAccess(url string, forceTCP bool) (string, string, error) { errorMessage := fmt.Sprintf("failed getting a configuration for Institute Access %s", url) - state.FSM.GoTransition(fsm.LOADING_SERVER) + state.FSM.GoTransition(STATE_LOADING_SERVER) server, serverErr := state.addInstituteServer(url) if serverErr != nil { @@ -422,7 +421,7 @@ func (state *VPNState) GetConfigInstituteAccess(url string, forceTCP bool) (stri func (state *VPNState) GetConfigCustomServer(url string, forceTCP bool) (string, string, error) { errorMessage := fmt.Sprintf("failed getting a configuration for custom server %s", url) - state.FSM.GoTransition(fsm.LOADING_SERVER) + state.FSM.GoTransition(STATE_LOADING_SERVER) server, serverErr := state.addCustomServer(url) if serverErr != nil { @@ -436,12 +435,12 @@ func (state *VPNState) GetConfigCustomServer(url string, forceTCP bool) (string, func (state *VPNState) CancelOAuth() error { errorMessage := "failed to cancel OAuth" - if !state.InFSMState(fsm.OAUTH_STARTED) { + if !state.InFSMState(STATE_OAUTH_STARTED) { return &types.WrappedErrorMessage{ Message: errorMessage, - Err: fsm.WrongStateError{ + Err: FSMWrongStateError{ Got: state.FSM.Current, - Want: fsm.OAUTH_STARTED, + Want: STATE_OAUTH_STARTED, }.CustomError(), } } @@ -458,10 +457,10 @@ func (state *VPNState) CancelOAuth() error { func (state *VPNState) ChangeSecureLocation() error { errorMessage := "failed to change location from the main screen" - if !state.InFSMState(fsm.NO_SERVER) { + if !state.InFSMState(STATE_NO_SERVER) { return &types.WrappedErrorMessage{ Message: errorMessage, - Err: fsm.WrongStateError{Got: state.FSM.Current, Want: fsm.NO_SERVER}.CustomError(), + Err: FSMWrongStateError{Got: state.FSM.Current, Want: STATE_NO_SERVER}.CustomError(), } } @@ -472,7 +471,7 @@ func (state *VPNState) ChangeSecureLocation() error { } // Go back to the main screen - state.FSM.GoTransitionWithData(fsm.NO_SERVER, state.GetSavedServers(), false) + state.FSM.GoTransitionWithData(STATE_NO_SERVER, state.GetSavedServers(), false) return nil } @@ -502,17 +501,17 @@ func (state *VPNState) SetProfileID(profileID string) error { } func (state *VPNState) SetSearchServer() error { - if !state.FSM.HasTransition(fsm.SEARCH_SERVER) { + if !state.FSM.HasTransition(STATE_SEARCH_SERVER) { return &types.WrappedErrorMessage{ Message: "failed to set search server", - Err: fsm.WrongStateTransitionError{ + Err: FSMWrongStateTransitionError{ Got: state.FSM.Current, - Want: fsm.CONNECTED, + Want: STATE_CONNECTED, }.CustomError(), } } - state.FSM.GoTransition(fsm.SEARCH_SERVER) + state.FSM.GoTransition(STATE_SEARCH_SERVER) return nil } @@ -523,74 +522,74 @@ func (state *VPNState) getServerInfoData() *server.ServerInfoScreen { } func (state *VPNState) SetConnected() error { - if state.InFSMState(fsm.CONNECTED) { + if state.InFSMState(STATE_CONNECTED) { // already connected, show no error return nil } - if !state.FSM.HasTransition(fsm.CONNECTED) { + if !state.FSM.HasTransition(STATE_CONNECTED) { return &types.WrappedErrorMessage{ Message: "failed to set connected", - Err: fsm.WrongStateTransitionError{ + Err: FSMWrongStateTransitionError{ Got: state.FSM.Current, - Want: fsm.CONNECTED, + Want: STATE_CONNECTED, }.CustomError(), } } - state.FSM.GoTransitionWithData(fsm.CONNECTED, state.getServerInfoData(), false) + state.FSM.GoTransitionWithData(STATE_CONNECTED, state.getServerInfoData(), false) return nil } func (state *VPNState) SetConnecting() error { - if state.InFSMState(fsm.CONNECTING) { + if state.InFSMState(STATE_CONNECTING) { // already loading connection, show no error return nil } - if !state.FSM.HasTransition(fsm.CONNECTING) { + if !state.FSM.HasTransition(STATE_CONNECTING) { return &types.WrappedErrorMessage{ Message: "failed to set connecting", - Err: fsm.WrongStateTransitionError{ + Err: FSMWrongStateTransitionError{ Got: state.FSM.Current, - Want: fsm.CONNECTING, + Want: STATE_CONNECTING, }.CustomError(), } } - state.FSM.GoTransition(fsm.CONNECTING) + state.FSM.GoTransition(STATE_CONNECTING) return nil } func (state *VPNState) SetDisconnecting() error { - if state.InFSMState(fsm.DISCONNECTING) { + if state.InFSMState(STATE_DISCONNECTING) { // already disconnecting, show no error return nil } - if !state.FSM.HasTransition(fsm.DISCONNECTING) { + if !state.FSM.HasTransition(STATE_DISCONNECTING) { return &types.WrappedErrorMessage{ Message: "failed to set disconnecting", - Err: fsm.WrongStateTransitionError{ + Err: FSMWrongStateTransitionError{ Got: state.FSM.Current, - Want: fsm.DISCONNECTING, + Want: STATE_DISCONNECTING, }.CustomError(), } } - state.FSM.GoTransitionWithData(fsm.DISCONNECTING, state.getServerInfoData(), false) + state.FSM.GoTransitionWithData(STATE_DISCONNECTING, state.getServerInfoData(), false) return nil } func (state *VPNState) SetDisconnected(cleanup bool) error { errorMessage := "failed to set disconnected" - if state.InFSMState(fsm.DISCONNECTED) { + if state.InFSMState(STATE_DISCONNECTED) { // already disconnected, show no error return nil } - if !state.FSM.HasTransition(fsm.DISCONNECTED) { + if !state.FSM.HasTransition(STATE_DISCONNECTED) { return &types.WrappedErrorMessage{ Message: errorMessage, - Err: fsm.WrongStateTransitionError{ + Err: FSMWrongStateTransitionError{ Got: state.FSM.Current, - Want: fsm.DISCONNECTED, + Want: STATE_DISCONNECTED, }.CustomError(), } } @@ -605,7 +604,7 @@ func (state *VPNState) SetDisconnected(cleanup bool) error { server.Disconnect(currentServer) } - state.FSM.GoTransitionWithData(fsm.DISCONNECTED, state.getServerInfoData(), false) + state.FSM.GoTransitionWithData(STATE_DISCONNECTED, state.getServerInfoData(), false) return nil } @@ -630,7 +629,7 @@ func (state *VPNState) RenewSession() error { } func (state *VPNState) ShouldRenewButton() bool { - if !state.InFSMState(fsm.CONNECTED) && !state.InFSMState(fsm.CONNECTING) && !state.InFSMState(fsm.DISCONNECTED) && !state.InFSMState(fsm.DISCONNECTING) { + if !state.InFSMState(STATE_CONNECTED) && !state.InFSMState(STATE_CONNECTING) && !state.InFSMState(STATE_DISCONNECTED) && !state.InFSMState(STATE_DISCONNECTING) { return false } @@ -650,7 +649,7 @@ func (state *VPNState) ShouldRenewButton() bool { return server.ShouldRenewButton(currentServer) } -func (state *VPNState) InFSMState(checkState StateID) bool { +func (state *VPNState) InFSMState(checkState FSMStateID) bool { return state.FSM.InState(checkState) } diff --git a/state_test.go b/state_test.go index 2106f40..b87b1ef 100644 --- a/state_test.go +++ b/state_test.go @@ -11,7 +11,6 @@ import ( "testing" "time" - "github.com/jwijenbergh/eduvpn-common/internal/fsm" httpw "github.com/jwijenbergh/eduvpn-common/internal/http" "github.com/jwijenbergh/eduvpn-common/internal/oauth" "github.com/jwijenbergh/eduvpn-common/internal/server" @@ -63,12 +62,12 @@ func loginOAuthSelenium(t *testing.T, url string, state *VPNState) { func stateCallback( t *testing.T, - oldState StateID, - newState StateID, + oldState FSMStateID, + newState FSMStateID, data interface{}, state *VPNState, ) { - if newState == fsm.OAUTH_STARTED { + if newState == STATE_OAUTH_STARTED { url, ok := data.(string) if !ok { @@ -86,7 +85,7 @@ func Test_server(t *testing.T) { state.Register( "org.eduvpn.app.linux", "configstest", - func(old StateID, new StateID, data interface{}) { + func(old FSMStateID, new FSMStateID, data interface{}) { stateCallback(t, old, new, data, state) }, false, @@ -111,8 +110,8 @@ func test_connect_oauth_parameter( state.Register( "org.eduvpn.app.linux", configDirectory, - func(oldState StateID, newState StateID, data interface{}) { - if newState == fsm.OAUTH_STARTED { + func(oldState FSMStateID, newState FSMStateID, data interface{}) { + if newState == STATE_OAUTH_STARTED { baseURL := "http://127.0.0.1:8000/callback" url, err := httpw.HTTPConstructURL(baseURL, parameters) if err != nil { @@ -190,7 +189,7 @@ func Test_token_expired(t *testing.T) { state.Register( "org.eduvpn.app.linux", "configsexpired", - func(old StateID, new StateID, data interface{}) { + func(old FSMStateID, new FSMStateID, data interface{}) { stateCallback(t, old, new, data, state) }, false, @@ -243,7 +242,7 @@ func Test_token_invalid(t *testing.T) { state.Register( "org.eduvpn.app.linux", "configsinvalid", - func(old StateID, new StateID, data interface{}) { + func(old FSMStateID, new FSMStateID, data interface{}) { stateCallback(t, old, new, data, state) }, false, @@ -293,7 +292,7 @@ func Test_invalid_profile_corrected(t *testing.T) { state.Register( "org.eduvpn.app.linux", "configscancelprofile", - func(old StateID, new StateID, data interface{}) { + func(old FSMStateID, new FSMStateID, data interface{}) { stateCallback(t, old, new, data, state) }, false, |
