diff --git a/app/main.go b/app/main.go index e24982c..8909d49 100644 --- a/app/main.go +++ b/app/main.go @@ -90,12 +90,12 @@ func main() { ioutil.WriteFile(path.Join(serverConfig.ConfigDir, "serverbundle"), []byte(server.TofuBundle()), 0600) } - // Graceful Shutdown + // Graceful Stop c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c - server.Shutdown() + server.Destroy() acn.Close() os.Exit(1) }() diff --git a/server.go b/server.go index 9fd9e5d..00b434e 100644 --- a/server.go +++ b/server.go @@ -33,7 +33,8 @@ type Server interface { Run(acn connectivity.ACN) error KeyBundle() *model.KeyBundle CheckStatus() (bool, error) - Shutdown() + Stop() + Destroy() GetStatistics() Statistics Delete(password string) error Onion() string @@ -65,6 +66,10 @@ func NewServer(serverConfig *Config) Server { server.config = serverConfig server.tokenService = server.config.TokenServiceIdentity() server.tokenServicePrivKey = server.config.TokenServerPrivateKey + bs := new(persistence.BoltPersistence) + bs.Open(path.Join(serverConfig.ConfigDir, "tokens.db")) + server.tokenServer = privacypass.NewTokenServerFromStore(&serverConfig.TokenServiceK, bs) + log.Infof("Y: %v", server.tokenServer.Y) return server } @@ -81,11 +86,6 @@ func (s *server) Run(acn connectivity.ACN) error { return nil } - bs := new(persistence.BoltPersistence) - bs.Open(path.Join(s.config.ConfigDir, "tokens.db")) - s.tokenServer = privacypass.NewTokenServerFromStore(&s.config.TokenServiceK, bs) - log.Infof("Y: %v", s.tokenServer.Y) - identity := primitives.InitializeIdentity("", &s.config.PrivateKey, &s.config.PublicKey) var service tapir.Service service = new(tor2.BaseOnionService) @@ -145,8 +145,9 @@ func (s *server) CheckStatus() (bool, error) { return s.running, nil } -// Shutdown kills the app closing all connections and freeing all goroutines -func (s *server) Shutdown() { +// Stop turns off the server so it cannot receive connections and frees most resourses. +// The server is still in a reRunable state and tokenServer still has an active persistance +func (s *server) Stop() { log.Infof("Shutting down server") s.lock.Lock() defer s.lock.Unlock() @@ -154,13 +155,21 @@ func (s *server) Shutdown() { s.service.Shutdown() s.tokenTapirService.Shutdown() log.Infof("Closing Token server Database...") - s.tokenServer.Close() + s.metricsPack.Stop() s.running = false s.SetAttribute(AttrEnabled, "false") } } +// Destroy frees the last of the resources the server has active (toklenServer persistance) leaving it un-re-runable and completely shutdown +func (s *server) Destroy() { + s.Stop() + s.lock.Lock() + defer s.lock.Unlock() + s.tokenServer.Close() +} + // Statistics is an encapsulation of information about the server that an operator might want to know at a glance. type Statistics struct { TotalMessages int diff --git a/servers.go b/servers.go index 27995a4..9964fff 100644 --- a/servers.go +++ b/servers.go @@ -24,8 +24,9 @@ type Servers interface { DeleteServer(onion string, currentPassword string) error LaunchServer(string) - ShutdownServer(string) - Shutdown() + StopServer(string) + Stop() + Destroy() } type servers struct { @@ -105,7 +106,7 @@ func (s *servers) DeleteServer(onion string, password string) error { defer s.lock.Unlock() server := s.servers[onion] if server != nil { - server.Shutdown() + server.Destroy() err := server.Delete(password) delete(s.servers, onion) return err @@ -122,18 +123,27 @@ func (s *servers) LaunchServer(onion string) { } } -// ShutdownServer Shutsdown the specified server -func (s *servers) ShutdownServer(onion string) { +// StopServer stops the specified server +func (s *servers) StopServer(onion string) { s.lock.Lock() defer s.lock.Unlock() - s.servers[onion].Shutdown() + s.servers[onion].Stop() } -// Shutdown shutsdown all the servers -func (s *servers) Shutdown() { +// Stop stops all the servers +func (s *servers) Stop() { s.lock.Lock() defer s.lock.Unlock() for _, server := range s.servers { - server.Shutdown() + server.Stop() + } +} + +// Destroy destroys all the servers +func (s *servers) Destroy() { + s.lock.Lock() + defer s.lock.Unlock() + for _, server := range s.servers { + server.Destroy() } } diff --git a/servers_test.go b/servers_test.go index 8e5c7c2..6dc9c1b 100644 --- a/servers_test.go +++ b/servers_test.go @@ -14,12 +14,12 @@ const TestServerDesc = "a test Server" func TestServers(t *testing.T) { log.SetLevel(log.LevelDebug) - log.Infof("clean up / setup...\n") + log.Infof("clean up / setup...") os.RemoveAll(TestDir) os.Mkdir(TestDir, 0700) acn := connectivity.NewLocalACN() - log.Infof("NewServers()...\n") + log.Infof("NewServers()...") servers := NewServers(acn, TestDir) s, err := servers.CreateServer(DefaultPassword) if err != nil { @@ -29,13 +29,13 @@ func TestServers(t *testing.T) { s.SetAttribute(AttrDescription, TestServerDesc) serverOnion := s.Onion() - s.Shutdown() + s.Destroy() - log.Infof("NewServers()...\n" ) + log.Infof("NewServers()...") servers2 := NewServers(acn, TestDir) - log.Infof("LoadServers()...\n") + log.Infof("LoadServers()...") list, err := servers2.LoadServers(DefaultPassword) - log.Infof("Loaded!\n") + log.Infof("Loaded!") if err != nil { t.Errorf("clould not load server: %s", err) return @@ -54,6 +54,6 @@ func TestServers(t *testing.T) { t.Errorf("expected server description of '%s' but got '%s'", TestServerDesc, s1.GetAttribute(AttrDescription)) } - servers2.Shutdown() + servers2.Destroy() os.RemoveAll(TestDir) -} \ No newline at end of file +}