// 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 conn

import (
	"crypto/rand"
	"log"
	"reflect"
	"runtime/debug"
	"sync"
	"time"

	"golang.org/x/crypto/nacl/box"
	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/flow"
	"v.io/v23/flow/message"
	"v.io/v23/naming"
	"v.io/v23/rpc/version"
	"v.io/v23/security"
	"v.io/v23/verror"
	"v.io/v23/vom"
	iflow "v.io/x/ref/runtime/internal/flow"
)

var (
	authDialerTag   = []byte("AuthDial\x00")
	authAcceptorTag = []byte("AuthAcpt\x00")
)

func (c *Conn) DialHandshake(
	ctx *context.T,
	versions version.RPCVersionRange,
	auth flow.PeerAuthorizer) (names []string, rejected []security.RejectedBlessing, rtt time.Duration, err error) {
	debug.PrintStack()

	log.Printf("\n\nctx:%v\nversions:%v\nauth:%v\n\n", ctx, versions, auth)

	binding, remoteEndpoint, rttstart, err := c.setup(ctx, versions, true)
	if err != nil {
		return nil, nil, 0, err
	}
	dialedEP := c.remote
	c.remote.RoutingID = remoteEndpoint.RoutingID
	bflow := c.newFlowLocked(
		ctx,
		blessingsFlowID,
		security.Blessings{},
		security.Blessings{},
		nil,
		nil,
		naming.Endpoint{},
		true,
		true,
		0,
		true)
	bflow.releaseLocked(DefaultBytesBufferedPerFlow)
	c.blessingsFlow = newBlessingsFlow(ctx, bflow)

	// 2nd line back from server
	rBlessings, rDischarges, rttend, err := c.readRemoteAuth(ctx, binding, true)
	if err != nil {
		return nil, nil, 0, err
	}
	rtt = rttend.Sub(rttstart)
	if rBlessings.IsZero() {
		err = NewErrAcceptorBlessingsMissing(ctx)
		return nil, nil, rtt, err
	}
	// : are RoutingIDs (RIDs) just there to detect proxies?
	// : what prevents two endpoints from having the same routing IDs?
	// : what does it mean to reach an endpoint we didn't expect?
	if c.MatchesRID(dialedEP) {
		// If we hadn't reached the endpoint we expected we would have treated this connection as
		// a proxy, and proxies aren't authorized.  In this case we didn't find a proxy, so go ahead
		// and authorize the connection.
		names, rejected, err = auth.AuthorizePeer(ctx, c.local, c.remote, rBlessings, rDischarges)
		if err != nil {
			return names, rejected, rtt, iflow.MaybeWrapError(verror.ErrNotTrusted, ctx, err)
		}
	}
	signedBinding, err := v23.GetPrincipal(ctx).Sign(append(authDialerTag, binding...))
	if err != nil {
		return names, rejected, rtt, err
	}
	lAuth := &message.Auth{ChannelBinding: signedBinding}
	// The client sends its blessings without any blessing-pattern encryption to the
	// server as it has already authorized the server. Thus the 'peers' argument to
	// blessingsFlow.send is nil.
	if lAuth.BlessingsKey, _, err = c.blessingsFlow.send(ctx, c.localBlessings, nil, nil); err != nil {
		return names, rejected, rtt, err
	}
	c.mu.Lock()
	err = c.sendMessageLocked(ctx, true, expressPriority, lAuth)
	c.mu.Unlock()
	return names, rejected, rtt, err
}

// MatchesRID returns true if the given endpoint matches the routing
// ID of the remote server.  Also returns true if the given ep has
// the null routing id (in which case it is assumed that any connected
// server must be the target since nothing has been specified).
func (c *Conn) MatchesRID(ep naming.Endpoint) bool {
	return ep.RoutingID == naming.NullRoutingID ||
		c.remote.RoutingID == ep.RoutingID
}

func (c *Conn) AcceptHandshake(
	ctx *context.T,
	versions version.RPCVersionRange,
	authorizedPeers []security.BlessingPattern) (rtt time.Duration, err error) {
	binding, remoteEndpoint, _, err := c.setup(ctx, versions, false)

	log.Printf("==============AcceptHandshake===========")
	log.Printf("\n\nctx:%v\nversions:%v\nauthorizedPeers:%v\n\n", ctx, versions, authorizedPeers)
	log.Printf("========================================")

	if err != nil {
		return rtt, err
	}
	c.remote = remoteEndpoint
	bflw := c.newFlowLocked(
		ctx,
		blessingsFlowID,
		security.Blessings{},
		security.Blessings{},
		nil,
		nil,
		naming.Endpoint{},
		true,
		true,
		0,
		true)
	c.blessingsFlow = newBlessingsFlow(ctx, bflw)
	signedBinding, err := v23.GetPrincipal(ctx).Sign(append(authAcceptorTag, binding...))
	if err != nil {
		return rtt, err
	}
	lAuth := &message.Auth{
		ChannelBinding: signedBinding,
	}

	// : We're sending {ServerBlessings, C1 signed by server private key} all signed by shared secret.
	// : is this actually sending, or is the call to sendMessageLocked sending?
	lAuth.BlessingsKey, lAuth.DischargeKey, err = c.blessingsFlow.send(
		ctx, c.localBlessings, c.localDischarges, authorizedPeers)
	if err != nil {
		return rtt, err
	}

	c.mu.Lock()
	rttstart := time.Now()
	// : is this method synchronous?
	err = c.sendMessageLocked(ctx, true, expressPriority, lAuth)
	c.mu.Unlock()
	if err != nil {
		return rtt, err
	}
	// : why are we throwing away the blessings information?
	_, _, rttend, err := c.readRemoteAuth(ctx, binding, false)
	rtt = rttend.Sub(rttstart)
	return rtt, err
}

// : The NaCl/box handshake that determines shared secret key and channel bindings (what are these?)
func (c *Conn) setup(ctx *context.T, versions version.RPCVersionRange, dialer bool) ([]byte, naming.Endpoint, time.Time, error) {
	var rttstart time.Time
	pk, sk, err := box.GenerateKey(rand.Reader)
	if err != nil {
		return nil, naming.Endpoint{}, rttstart, err
	}
	lSetup := &message.Setup{
		Versions:          versions,
		PeerLocalEndpoint: c.local,
		PeerNaClPublicKey: pk,
		Mtu:               defaultMtu,
		SharedTokens:      DefaultBytesBufferedPerFlow,
	}
	// TODO: what's this doing?
	if !c.remote.IsZero() {
		lSetup.PeerRemoteEndpoint = c.remote
	}
	ch := make(chan error, 1)
	go func() {
		c.mu.Lock()
		rttstart = time.Now()
		// : Is this both the client->server request and server->client response? If yes, doesn't the server
		// not get a response to check below?
		ch <- c.sendMessageLocked(ctx, true, expressPriority, lSetup)
		c.mu.Unlock()
	}()
	// TODO: receive the response from peer
	msg, err := c.mp.readMsg(ctx)
	if err != nil {
		<-ch
		return nil, naming.Endpoint{}, rttstart, NewErrRecv(ctx, "unknown", err)
	}
	rSetup, valid := msg.(*message.Setup)
	if !valid {
		<-ch
		return nil, naming.Endpoint{}, rttstart, NewErrUnexpectedMsg(ctx, reflect.TypeOf(msg).String())
	}
	if err := <-ch; err != nil {
		remoteStr := ""
		if !c.remote.IsZero() {
			remoteStr = c.remote.String()
		}
		return nil, naming.Endpoint{}, rttstart, NewErrSend(ctx, "setup", remoteStr, err)
	}
	if c.version, err = version.CommonVersion(ctx, lSetup.Versions, rSetup.Versions); err != nil {
		return nil, naming.Endpoint{}, rttstart, err
	}
	if c.local.IsZero() {
		c.local = rSetup.PeerRemoteEndpoint
	}
	if rSetup.Mtu != 0 {
		c.mtu = rSetup.Mtu
	} else {
		c.mtu = defaultMtu
	}
	c.lshared = lSetup.SharedTokens
	if rSetup.SharedTokens != 0 && rSetup.SharedTokens < c.lshared {
		c.lshared = rSetup.SharedTokens
	}
	if rSetup.PeerNaClPublicKey == nil {
		return nil, naming.Endpoint{}, rttstart, NewErrMissingSetupOption(ctx, "peerNaClPublicKey")
	}
	c.mu.Lock()
	binding := c.mp.setupEncryption(ctx, pk, sk, rSetup.PeerNaClPublicKey)
	c.mu.Unlock()
	if c.version >= version.RPCVersion14 {
		// We include the setup messages in the channel binding to prevent attacks
		// where a man in the middle changes fields in the Setup message (e.g. a
		// downgrade attack wherein a MITM attacker changes the Version field of
		// the Setup message to a lower-security version.)
		// We always put the dialer first in the binding.
		if dialer {
			if binding, err = message.Append(ctx, lSetup, nil); err != nil {
				return nil, naming.Endpoint{}, rttstart, err
			}
			if binding, err = message.Append(ctx, rSetup, binding); err != nil {
				return nil, naming.Endpoint{}, rttstart, err
			}
		} else {
			if binding, err = message.Append(ctx, rSetup, nil); err != nil {
				return nil, naming.Endpoint{}, rttstart, err
			}
			if binding, err = message.Append(ctx, lSetup, binding); err != nil {
				return nil, naming.Endpoint{}, rttstart, err
			}
		}
	}
	// if we're encapsulated in another flow, tell that flow to stop
	// encrypting now that we've started.
	if f, ok := c.mp.rw.(*flw); ok {
		f.disableEncryption()
	}
	return binding, rSetup.PeerLocalEndpoint, rttstart, nil
}

// : Gets blessings from a message?
func (c *Conn) readRemoteAuth(ctx *context.T, binding []byte, dialer bool) (security.Blessings, map[string]security.Discharge, time.Time, error) {
	tag := authDialerTag
	if dialer {
		tag = authAcceptorTag
	}
	var (
		rauth       *message.Auth
		err         error
		rttend      time.Time
		rBlessings  security.Blessings
		rDischarges map[string]security.Discharge
	)
	for {
		msg, err := c.mp.readMsg(ctx)
		if err != nil {
			remote := ""
			if !c.remote.IsZero() {
				remote = c.remote.String()
			}
			return security.Blessings{}, nil, rttend, NewErrRecv(ctx, remote, err)
		}
		if rauth, _ = msg.(*message.Auth); rauth != nil {
			rttend = time.Now()
			break
		}
		if err = c.handleMessage(ctx, msg); err != nil {
			return security.Blessings{}, nil, rttend, err
		}
	}
	// Only read the blessings if we were the dialer. Any blessings from the dialer
	// will be sent later.
	if rauth.BlessingsKey != 0 {
		rBlessings, rDischarges, err = c.blessingsFlow.getRemote(
			ctx, rauth.BlessingsKey, rauth.DischargeKey)
		if err != nil {
			return security.Blessings{}, nil, rttend, err
		}
		c.mu.Lock()
		c.rPublicKey = rBlessings.PublicKey()
		c.remoteBlessings = rBlessings
		c.remoteDischarges = rDischarges
		c.remoteValid = make(chan struct{})
		c.mu.Unlock()
	}
	if c.rPublicKey == nil {
		return security.Blessings{}, nil, rttend, NewErrNoPublicKey(ctx)
	}
	if !rauth.ChannelBinding.Verify(c.rPublicKey, append(tag, binding...)) {
		return security.Blessings{}, nil, rttend, NewErrInvalidChannelBinding(ctx)
	}
	return rBlessings, rDischarges, rttend, nil
}

type blessingsFlow struct {
	enc *vom.Encoder
	dec *vom.Decoder
	f   *flw

	mu       sync.Mutex
	nextKey  uint64
	incoming *inCache
	outgoing *outCache
}

// inCache keeps track of incoming blessings, discharges, and keys.
type inCache struct {
	dkeys      map[uint64]uint64               // bkey -> dkey of the latest discharges.
	blessings  map[uint64]security.Blessings   // keyed by bkey
	discharges map[uint64][]security.Discharge // keyed by dkey
}

// outCache keeps track of outgoing blessings, discharges, and keys.
type outCache struct {
	bkeys map[string]uint64 // blessings uid -> bkey

	dkeys      map[uint64]uint64               // blessings bkey -> dkey of latest discharges
	blessings  map[uint64]security.Blessings   // keyed by bkey
	discharges map[uint64][]security.Discharge // keyed by dkey
}

func newBlessingsFlow(ctx *context.T, f *flw) *blessingsFlow {
	b := &blessingsFlow{
		f:       f,
		enc:     vom.NewEncoder(f),
		dec:     vom.NewDecoder(f),
		nextKey: 1,
		incoming: &inCache{
			blessings:  make(map[uint64]security.Blessings),
			dkeys:      make(map[uint64]uint64),
			discharges: make(map[uint64][]security.Discharge),
		},
		outgoing: &outCache{
			bkeys:      make(map[string]uint64),
			dkeys:      make(map[uint64]uint64),
			blessings:  make(map[uint64]security.Blessings),
			discharges: make(map[uint64][]security.Discharge),
		},
	}
	return b
}

func (b *blessingsFlow) receiveBlessingsLocked(ctx *context.T, bkey uint64, blessings security.Blessings) error {
	// When accepting, make sure the blessings received are bound to the conn's
	// remote public key.
	b.f.conn.mu.Lock()
	if pk := b.f.conn.rPublicKey; pk != nil && !reflect.DeepEqual(blessings.PublicKey(), pk) {
		b.f.conn.mu.Unlock()
		return NewErrBlessingsNotBound(ctx)
	}
	b.f.conn.mu.Unlock()
	b.incoming.blessings[bkey] = blessings
	return nil
}

func (b *blessingsFlow) receiveDischargesLocked(ctx *context.T, bkey, dkey uint64, discharges []security.Discharge) {
	b.incoming.discharges[dkey] = discharges
	b.incoming.dkeys[bkey] = dkey
}

func (b *blessingsFlow) receiveLocked(ctx *context.T, bd BlessingsFlowMessage) error {
	switch bd := bd.(type) {
	case BlessingsFlowMessageBlessings:
		bkey, blessings := bd.Value.BKey, bd.Value.Blessings
		if err := b.receiveBlessingsLocked(ctx, bkey, blessings); err != nil {
			return err
		}
	case BlessingsFlowMessageEncryptedBlessings:
		bkey, ciphertexts := bd.Value.BKey, bd.Value.Ciphertexts
		var blessings security.Blessings
		if err := decrypt(ctx, ciphertexts, &blessings); err != nil {
			// TODO(ataly): This error should not be returned if the
			// client has explicitly set the peer authorizer to nil.
			// In that case, the client does not care whether the server's
			// blessings can be decrypted or not. Ideally we should just
			// pass this error to the peer authorizer and handle it there.
			return iflow.MaybeWrapError(verror.ErrNotTrusted, ctx, NewErrCannotDecryptBlessings(ctx, err))
		}
		if err := b.receiveBlessingsLocked(ctx, bkey, blessings); err != nil {
			return err
		}
	case BlessingsFlowMessageDischarges:
		bkey, dkey, discharges := bd.Value.BKey, bd.Value.DKey, bd.Value.Discharges
		b.receiveDischargesLocked(ctx, bkey, dkey, discharges)
	case BlessingsFlowMessageEncryptedDischarges:
		bkey, dkey, ciphertexts := bd.Value.BKey, bd.Value.DKey, bd.Value.Ciphertexts
		var discharges []security.Discharge
		if err := decrypt(ctx, ciphertexts, &discharges); err != nil {
			return iflow.MaybeWrapError(verror.ErrNotTrusted, ctx, NewErrCannotDecryptDischarges(ctx, err))
		}
		b.receiveDischargesLocked(ctx, bkey, dkey, discharges)
	}
	return nil
}

// getRemote gets the remote blessings and discharges associated with the given
// bkey and dkey. We will read messages from the wire until we receive the
// looked for blessings. This method is normally called from the read loop of
// the conn, so all the packets for the desired blessing must have been received
// and buffered before calling this function.  This property is guaranteed since
// we always send blessings and discharges before sending their bkey/dkey
// references in a control message.
func (b *blessingsFlow) getRemote(ctx *context.T, bkey, dkey uint64) (security.Blessings, map[string]security.Discharge, error) {
	defer b.mu.Unlock()
	b.mu.Lock()
	for {
		blessings, hasB := b.incoming.blessings[bkey]
		if hasB {
			if dkey == 0 {
				return blessings, nil, nil
			}
			discharges, hasD := b.incoming.discharges[dkey]
			if hasD {
				return blessings, dischargeMap(discharges), nil
			}
		}

		var received BlessingsFlowMessage
		err := b.dec.Decode(&received)
		if err != nil {
			return security.Blessings{}, nil, err
		}
		if err := b.receiveLocked(ctx, received); err != nil {
			b.f.conn.internalClose(ctx, false, err)
			return security.Blessings{}, nil, err
		}
	}
}

func (b *blessingsFlow) encodeBlessingsLocked(ctx *context.T, blessings security.Blessings, bkey uint64, peers []security.BlessingPattern) error {
	if len(peers) == 0 {
		// blessings can be encoded in plaintext
		return b.enc.Encode(BlessingsFlowMessageBlessings{Blessings{
			BKey:      bkey,
			Blessings: blessings,
		}})
	}
	ciphertexts, err := encrypt(ctx, peers, blessings)
	if err != nil {
		return NewErrCannotEncryptBlessings(ctx, peers, err)
	}
	return b.enc.Encode(BlessingsFlowMessageEncryptedBlessings{EncryptedBlessings{
		BKey:        bkey,
		Ciphertexts: ciphertexts,
	}})
}

func (b *blessingsFlow) encodeDischargesLocked(ctx *context.T, discharges []security.Discharge, bkey, dkey uint64, peers []security.BlessingPattern) error {
	if len(peers) == 0 {
		// discharges can be encoded in plaintext
		return b.enc.Encode(BlessingsFlowMessageDischarges{Discharges{
			Discharges: discharges,
			DKey:       dkey,
			BKey:       bkey,
		}})
	}
	ciphertexts, err := encrypt(ctx, peers, discharges)
	if err != nil {
		return NewErrCannotEncryptDischarges(ctx, peers, err)
	}
	return b.enc.Encode(BlessingsFlowMessageEncryptedDischarges{EncryptedDischarges{
		DKey:        dkey,
		BKey:        bkey,
		Ciphertexts: ciphertexts,
	}})
}

func (b *blessingsFlow) send(
	ctx *context.T,
	blessings security.Blessings,
	discharges map[string]security.Discharge,
	peers []security.BlessingPattern) (bkey, dkey uint64, err error) {
	if blessings.IsZero() {
		return 0, 0, nil
	}
	defer b.mu.Unlock()
	b.mu.Lock()
	buid := string(blessings.UniqueID())
	bkey, hasB := b.outgoing.bkeys[buid]
	if !hasB {
		bkey = b.nextKey
		b.nextKey++
		b.outgoing.bkeys[buid] = bkey
		b.outgoing.blessings[bkey] = blessings
		if err := b.encodeBlessingsLocked(ctx, blessings, bkey, peers); err != nil {
			return 0, 0, err
		}
	}
	if len(discharges) == 0 {
		return bkey, 0, nil
	}
	dkey, hasD := b.outgoing.dkeys[bkey]
	if hasD && equalDischarges(discharges, b.outgoing.discharges[dkey]) {
		return bkey, dkey, nil
	}
	dlist := dischargeList(discharges)
	dkey = b.nextKey
	b.nextKey++
	b.outgoing.dkeys[bkey] = dkey
	b.outgoing.discharges[dkey] = dlist
	return bkey, dkey, b.encodeDischargesLocked(ctx, dlist, bkey, dkey, peers)
}

func (b *blessingsFlow) close(ctx *context.T, err error) {
	b.f.close(ctx, false, err)
}

func dischargeList(in map[string]security.Discharge) []security.Discharge {
	out := make([]security.Discharge, 0, len(in))
	for _, d := range in {
		out = append(out, d)
	}
	return out
}
func dischargeMap(in []security.Discharge) map[string]security.Discharge {
	out := make(map[string]security.Discharge, len(in))
	for _, d := range in {
		out[d.ID()] = d
	}
	return out
}

func equalDischarges(m map[string]security.Discharge, s []security.Discharge) bool {
	if len(m) != len(s) {
		return false
	}
	for _, d := range s {
		inm, ok := m[d.ID()]
		if !ok || !d.Equivalent(inm) {
			return false
		}
	}
	return true
}
