func (s *Session) Subscribe(events ...string) error {
	return s.el.registerEvents(events)
}
Subscribe registers the session to listen for all events given. To receive
events that are registered here, use NextEvent. An error is returned if
Subscribe is not able to register the given events with the charon daemon.
package vici
import (
	"context"
	"net"
	"sync"
)
type Session struct {
	mu  sync.Mutex
	ctr *transport
	el *eventListener
	*sessionOpts
}
func NewSession(opts ...SessionOption) (*Session, error) {
	s := &Session{
		sessionOpts: &sessionOpts{
			network: "unix",
			addr:    defaultSocketPath,
			dialer:  (&net.Dialer{}).DialContext,
			conn:    nil,
		},
	}
	for _, opt := range opts {
		opt.apply(s.sessionOpts)
	}
	ctr, err := s.newTransport()
	if err != nil {
		return nil, err
	}
	s.ctr = ctr
	elt, err := s.newTransport()
	if err != nil {
		return nil, err
	}
	s.el = newEventListener(elt)
	return s, nil
}
func (s *Session) newTransport() (*transport, error) {
	if s.conn != nil {
		return &transport{conn: s.conn}, nil
	}
	conn, err := s.dialer(context.Background(), s.network, s.addr)
	if err != nil {
		return nil, err
	}
	t := &transport{
		conn: conn,
	}
	return t, nil
}
func (s *Session) Close() error {
	if err := s.el.Close(); err != nil {
		return err
	}
	s.mu.Lock()
	if s.ctr != nil {
		if err := s.ctr.conn.Close(); err != nil {
			return err
		}
		s.ctr = nil
	}
	s.mu.Unlock()
	return nil
}
type SessionOption interface {
	apply(*sessionOpts)
}
type sessionOpts struct {
	network string
	addr    string
	dialer func(ctx context.Context, network, addr string) (net.Conn, error)
	conn net.Conn
}
type funcSessionOption struct {
	f func(*sessionOpts)
}
func (fso *funcSessionOption) apply(s *sessionOpts) {
	fso.f(s)
}
func newFuncSessionOption(f func(*sessionOpts)) *funcSessionOption {
	return &funcSessionOption{f}
}
func WithSocketPath(path string) SessionOption {
	return newFuncSessionOption(func(so *sessionOpts) {
		so.network = "unix"
		so.addr = path
	})
}
func WithAddr(network, addr string) SessionOption {
	return newFuncSessionOption(func(so *sessionOpts) {
		so.network = network
		so.addr = addr
	})
}
func WithDialContext(dialer func(ctx context.Context, network, addr string) (net.Conn, error)) SessionOption {
	return newFuncSessionOption(func(so *sessionOpts) {
		so.dialer = dialer
	})
}
func withTestConn(conn net.Conn) SessionOption {
	return newFuncSessionOption(func(so *sessionOpts) {
		so.conn = conn
	})
}
func (s *Session) CommandRequest(cmd string, msg *Message) (*Message, error) {
	resp, err := s.sendRequest(cmd, msg)
	if err != nil {
		return nil, err
	}
	return resp, resp.Err()
}
func (s *Session) StreamedCommandRequest(cmd string, event string, msg *Message) (*MessageStream, error) {
	return s.sendStreamedRequest(cmd, event, msg)
}