// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package keymgr implements a client for deviced to manage keys in the agentd
// process.
package keymgr

import (
	"net"
	"os"
	"strconv"
	"sync"

	"v.io/v23/context"
	"v.io/v23/verror"
	"v.io/x/ref/services/agent/internal/server"
	"v.io/x/ref/services/agent/internal/unixfd"
)

const pkgPath = "v.io/x/ref/services/agent/keymgr"

// Errors
var (
	errInvalidResponse = verror.Register(pkgPath+".errInvalidResponse",
		verror.NoRetry, "{1:}{2:} invalid response from agent. (expected {3} bytes, got {4})")
	errInvalidKeyHandle = verror.Register(pkgPath+".errInvalidKeyHandle",
		verror.NoRetry, "{1:}{2:} Invalid key handle")
)

const defaultManagerSocket = 4

type Agent struct {
	conn *net.UnixConn // Guarded by mu
	mu   sync.Mutex
}

// NewAgent returns a client connected to the agent on the default file descriptors.
func NewAgent() (*Agent, error) {
	return newAgent(defaultManagerSocket)
}

func NewLocalAgent(ctx *context.T, path string, passphrase []byte) (*Agent, error) {
	file, err := server.RunKeyManager(ctx, path, passphrase)
	if err != nil {
		return nil, err
	}
	conn, err := net.FileConn(file)
	if err != nil {
		return nil, err
	}
	return &Agent{conn: conn.(*net.UnixConn)}, nil
}

func newAgent(fd int) (a *Agent, err error) {
	file := os.NewFile(uintptr(fd), "fd")
	defer file.Close()
	conn, err := net.FileConn(file)
	if err != nil {
		return nil, err
	}

	return &Agent{conn: conn.(*net.UnixConn)}, nil
}

// TODO(caprita): Get rid of *context.T arg.  Doesn't seem to be used.

// NewPrincipal creates a new principal and returns the handle and a socket serving
// the principal.
// Typically the socket will be passed to a child process using cmd.ExtraFiles.
func (a *Agent) NewPrincipal(ctx *context.T, inMemory bool) (handle []byte, conn *os.File, err error) {
	req := make([]byte, 1)
	if inMemory {
		req[0] = 1
	}
	a.mu.Lock()
	defer a.mu.Unlock()
	conn, err = a.connect(req)
	if err != nil {
		return nil, nil, err
	}
	buf := make([]byte, server.PrincipalHandleByteSize)
	n, err := a.conn.Read(buf)
	if err != nil {
		conn.Close()
		return nil, nil, err
	}
	if n != server.PrincipalHandleByteSize {
		conn.Close()
		return nil, nil, verror.New(errInvalidResponse, ctx, server.PrincipalHandleByteSize, n)
	}
	return buf, conn, nil
}

func (a *Agent) connect(req []byte) (*os.File, error) {
	addr, err := unixfd.SendConnection(a.conn, req)
	if err != nil {
		return nil, err
	}
	fd, err := strconv.ParseInt(addr.String(), 10, 32)
	if err != nil {
		return nil, err
	}
	return os.NewFile(uintptr(fd), "client"), nil
}

// NewConnection creates a connection to an agent which exports a principal
// previously created with NewPrincipal.
// Typically this will be passed to a child process using cmd.ExtraFiles.
func (a *Agent) NewConnection(handle []byte) (*os.File, error) {
	if len(handle) != server.PrincipalHandleByteSize {
		return nil, verror.New(errInvalidKeyHandle, nil)
	}
	a.mu.Lock()
	defer a.mu.Unlock()
	return a.connect(handle)
}
