package server import ( "context" "errors" "sync" "github.com/Neur0toxine/sshpoke/internal/config" "github.com/Neur0toxine/sshpoke/internal/logger" "github.com/Neur0toxine/sshpoke/internal/server/driver" "github.com/Neur0toxine/sshpoke/internal/server/driver/iface" "github.com/Neur0toxine/sshpoke/internal/server/driver/plugin" "github.com/Neur0toxine/sshpoke/pkg/dto" ) type Manager struct { rw sync.RWMutex servers map[string]iface.Driver plugins map[string]plugin.Plugin defaultServer string } var DefaultManager *Manager var ( ErrNoServer = errors.New("server is not specified") ErrNoSuchServer = errors.New("server does not exist") ) func NewManager(ctx context.Context, servers []config.Server, defaultServer string) *Manager { m := &Manager{ servers: make(map[string]iface.Driver), plugins: make(map[string]plugin.Plugin), defaultServer: defaultServer, } for _, serverConfig := range servers { server, err := driver.New(ctx, serverConfig.Name, serverConfig.Driver, serverConfig.Params) if err != nil { logger.Sugar.Errorf("cannot initialize server '%s': %s", serverConfig.Name, err) continue } if server.Driver() == config.DriverPlugin { pl := server.(plugin.Plugin) if pl.Token() == "" { logger.Sugar.Warnf("server '%s' will not work because it doesn't have a token", pl.Name()) continue } existing, found := m.plugins[pl.Token()] if found { logger.Sugar.Fatalw("two plugins cannot have the same token", "plugin1", existing.Name(), "plugin2", pl.Name(), "token", pl.Token()) } m.plugins[pl.Token()] = pl } m.servers[serverConfig.Name] = server } return m } func (m *Manager) ProcessEvent(event dto.Event) error { serverName := event.Container.Server if serverName == "" { serverName = m.defaultServer } if serverName == "" { return ErrNoServer } defer m.rw.RUnlock() m.rw.RLock() srv, ok := m.servers[event.Container.Server] if !ok { return ErrNoSuchServer } return srv.Handle(event) } func (m *Manager) PluginByToken(token string) plugin.Plugin { server, ok := m.plugins[token] if !ok { return nil } return server } func (m *Manager) WaitForShutdown() { defer m.rw.RUnlock() m.rw.RLock() for _, srv := range m.servers { srv.WaitForShutdown() } return }