1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
package eduvpn
import (
"errors"
"github.com/jwijenbergh/eduvpn-common/internal"
)
type VPNState struct {
// The chosen server
Servers internal.Servers `json:"servers"`
// The list of servers and organizations from disco
Discovery internal.Discovery `json:"-"`
// The fsm
FSM internal.FSM `json:"-"`
// The logger
Logger internal.FileLogger `json:"-"`
// The config
Config internal.Config `json:"-"`
// Whether to enable debugging
Debug bool `json:"-"`
}
var VPNStateInstance *VPNState
func GetVPNState() *VPNState {
if VPNStateInstance == nil {
VPNStateInstance = &VPNState{}
}
return VPNStateInstance
}
func (state *VPNState) Register(name string, directory string, stateCallback func(string, string, string), debug bool) error {
if !state.FSM.InState(internal.DEREGISTERED) {
return errors.New("app already registered")
}
// Initialize the logger
logLevel := internal.LOG_WARNING
if debug {
logLevel = internal.LOG_INFO
}
loggerErr := state.Logger.Init(logLevel, name, directory)
if loggerErr != nil {
return errors.New("Failed to create a logger")
}
// Initialize the FSM
state.FSM.Init(stateCallback, &state.Logger, debug)
state.Debug = debug
// Initialize the Config
state.Config.Init(name, directory)
// Initialize Discovery
state.Discovery.Init(&state.FSM, &state.Logger)
// Try to load the previous configuration
if state.Config.Load(&state) != nil {
// This error can be safely ignored, as when the config does not load, the struct will not be filled
state.Logger.Log(internal.LOG_INFO, "Previous configuration not found")
}
state.FSM.GoTransition(internal.NO_SERVER)
return nil
}
func (state *VPNState) Deregister() error {
// Close the log file
state.Logger.Close()
// Save the config
state.Config.Save(&state)
// Empty out fsm
state.FSM = internal.FSM{}
return nil
}
func (state *VPNState) Connect(url string) (string, error) {
if state.FSM.InState(internal.DEREGISTERED) {
return "", errors.New("app not registered")
}
// New server chosen, ensure the server is fresh
server, serverErr := state.Servers.EnsureServer(url, &state.FSM, &state.Logger)
if serverErr != nil {
return "", serverErr
}
// Make sure we are in the chosen state if available
state.FSM.GoTransition(internal.CHOSEN_SERVER)
// Relogin with oauth
// This moves the state to authenticated
if server.NeedsRelogin() {
loginErr := server.Login()
if loginErr != nil {
return "", loginErr
}
} else { // OAuth was valid, ensure we are in the authenticated state
state.FSM.GoTransition(internal.AUTHENTICATED)
}
state.FSM.GoTransition(internal.REQUEST_CONFIG)
config, configErr := server.GetConfig()
if configErr != nil {
return "", configErr
} else {
state.FSM.GoTransition(internal.HAS_CONFIG)
}
return config, nil
}
func (state *VPNState) GetDiscoOrganizations() (string, error) {
if state.FSM.InState(internal.DEREGISTERED) {
return "", errors.New("app not registered")
}
return state.Discovery.GetOrganizationsList()
}
func (state *VPNState) GetDiscoServers() (string, error) {
if state.FSM.InState(internal.DEREGISTERED) {
return "", errors.New("app not registered")
}
return state.Discovery.GetServersList()
}
func (state *VPNState) SetProfileID(profileID string) error {
if !state.FSM.InState(internal.ASK_PROFILE) {
return errors.New("Invalid state for setting a profile")
}
server, serverErr := state.Servers.GetCurrentServer()
if serverErr != nil {
return errors.New("No server found for setting a profile ID")
}
server.Profiles.Current = profileID
return nil
}
|