package plugin import ( "context" "errors" "io" "github.com/Neur0toxine/sshpoke/internal/config" "github.com/Neur0toxine/sshpoke/internal/logger" "github.com/Neur0toxine/sshpoke/internal/model" "github.com/Neur0toxine/sshpoke/internal/server/driver/iface" "github.com/Neur0toxine/sshpoke/internal/server/driver/util" ) // Plugin driver uses RPC to communicate with external plugin. type Plugin struct { ctx context.Context name string params Params send chan model.Event } type EventStream interface { Send(event model.Event) error Recv() error } func New(ctx context.Context, name string, params config.DriverParams) (iface.Driver, error) { drv := &Plugin{ name: name, ctx: ctx, send: make(chan model.Event), } if err := util.UnmarshalParams(params, &drv.params); err != nil { return nil, err } return drv, nil } func (d *Plugin) Handle(event model.Event) error { if d.isDone() { return nil } d.send <- event return nil } func (d *Plugin) Name() string { return d.name } func (d *Plugin) Driver() config.DriverType { return config.DriverPlugin } func (d *Plugin) Token() string { return d.params.Token } func (d *Plugin) Listen(ctx context.Context, stream EventStream) error { for { select { case <-ctx.Done(): return nil default: } err := stream.Recv() if errors.Is(err, io.EOF) { return nil } if err != nil { logger.Sugar.Errorw("error reading poll event from plugin", "server", d.name, "error", err) return err } select { case <-ctx.Done(): return nil case event := <-d.send: err := stream.Send(event) if errors.Is(err, io.EOF) { return nil } if err != nil { logger.Sugar.Errorw("error writing event to plugin", "server", d.name, "error", err) return err } } } } func (d *Plugin) HandleStatus(event model.EventRequest) { logger.Sugar.Errorw("plugin error", "serverName", d.name, "id", event.ID, "error", event.Error) } func (d *Plugin) isDone() bool { select { case <-d.ctx.Done(): close(d.send) return true default: return false } } func (d *Plugin) WaitForShutdown() { <-d.ctx.Done() return }