func (s *Session) NextEvent(ctx context.Context) (Event, error) {
	return s.el.nextEvent(ctx)
}
NextEvent returns the next event received by the session event listener.  NextEvent will block
until an Event (or error) is received, or until the supplied context is closed.
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)
}
func (s *Session) Subscribe(events ...string) error {
	return s.el.registerEvents(events)
}
func (s *Session) Unsubscribe(events ...string) error {
	return s.el.unregisterEvents(events, false)
}
func (s *Session) UnsubscribeAll() error {
	return s.el.unregisterEvents(nil, true)
}