// Package transport defines a common interface for // network connections that have an associated client identity. package transport import ( "context" "net" "syscall" "github.com/pkg/errors" "github.com/zrepl/zrepl/daemon/logging" "github.com/zrepl/zrepl/logger" "github.com/zrepl/zrepl/rpc/dataconn/timeoutconn" "github.com/zrepl/zrepl/zfs" ) type AuthConn struct { Wire clientIdentity string } var _ timeoutconn.SyscallConner = AuthConn{} func (a AuthConn) SyscallConn() (rawConn syscall.RawConn, err error) { scc, ok := a.Wire.(timeoutconn.SyscallConner) if !ok { return nil, timeoutconn.SyscallConnNotSupported } return scc.SyscallConn() } func NewAuthConn(conn Wire, clientIdentity string) *AuthConn { return &AuthConn{conn, clientIdentity} } func (c *AuthConn) ClientIdentity() string { if err := ValidateClientIdentity(c.clientIdentity); err != nil { panic(err) } return c.clientIdentity } // like net.Listener, but with an AuthenticatedConn instead of net.Conn type AuthenticatedListener interface { Addr() net.Addr Accept(ctx context.Context) (*AuthConn, error) Close() error } type AuthenticatedListenerFactory func() (AuthenticatedListener, error) type Wire = timeoutconn.Wire type Connecter interface { Connect(ctx context.Context) (Wire, error) } // A client identity must be a single component in a ZFS filesystem path func ValidateClientIdentity(in string) error { err := zfs.ComponentNamecheck(in) if err != nil { return errors.Wrap(err, "client identity must be usable as a single dataset path component") } return nil } type Logger = logger.Logger func GetLogger(ctx context.Context) Logger { return logging.GetLogger(ctx, logging.SubsysTransport) }