ref: Change the API of validators to accept *context.T
instead of security.Call.

Also we remove the Context() accessor from the security.Call and
add it back to rpc.ServerCall.  This is in preparation to split
the ServerCall and security.Call interfaces.

MultiPart: 2/3

Change-Id: Ia41e4a60a3b995ddf349db39fc154cf25d5241bc
diff --git a/profiles/internal/rpc/client.go b/profiles/internal/rpc/client.go
index 61eaaab..3c070cd 100644
--- a/profiles/internal/rpc/client.go
+++ b/profiles/internal/rpc/client.go
@@ -349,9 +349,6 @@
 		return
 	}
 
-	// TODO(ataly, bprosnitx, ashankar): Add 'ctx' to the security.Call created below
-	// otherwise any custom caveat validators (defined in ctx) cannot be used while validating
-	// caveats in this context. Also see: https://github.com/veyron/release-issues/issues/1230
 	seccall := security.NewCall(&security.CallParams{
 		LocalPrincipal:   status.flow.LocalPrincipal(),
 		LocalBlessings:   status.flow.LocalBlessings(),
diff --git a/profiles/internal/rpc/full_test.go b/profiles/internal/rpc/full_test.go
index 4a86966..8bf421c 100644
--- a/profiles/internal/rpc/full_test.go
+++ b/profiles/internal/rpc/full_test.go
@@ -206,7 +206,7 @@
 	if tp == nil {
 		return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
 	}
-	if err := tp.Dischargeable(call); err != nil {
+	if err := tp.Dischargeable(call.Context()); err != nil {
 		return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", cav, err)
 	}
 	// Add a fakeTimeCaveat to be able to control discharge expiration via 'clock'.
@@ -1966,7 +1966,7 @@
 	if tp == nil {
 		return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
 	}
-	if err := tp.Dischargeable(call); err != nil {
+	if err := tp.Dischargeable(call.Context()); err != nil {
 		return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", cav, err)
 	}
 	expDur := 10 * time.Millisecond
@@ -2050,7 +2050,7 @@
 
 func init() {
 	rpc.RegisterUnknownProtocol("wsh", websocket.HybridDial, websocket.HybridListener)
-	security.RegisterCaveatValidator(fakeTimeCaveat, func(_ security.Call, t int64) error {
+	security.RegisterCaveatValidator(fakeTimeCaveat, func(_ *context.T, t int64) error {
 		if now := clock.Now(); now > t {
 			return fmt.Errorf("fakeTimeCaveat expired: now=%d > then=%d", now, t)
 		}
diff --git a/profiles/internal/rt/ipc_test.go b/profiles/internal/rt/ipc_test.go
index e836c55..1ad062d 100644
--- a/profiles/internal/rt/ipc_test.go
+++ b/profiles/internal/rt/ipc_test.go
@@ -252,7 +252,7 @@
 	if tp == nil {
 		return security.Discharge{}, fmt.Errorf("discharger: not a third party caveat (%v)", cav)
 	}
-	if err := tp.Dischargeable(call); err != nil {
+	if err := tp.Dischargeable(call.Context()); err != nil {
 		return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", tp, err)
 	}
 	// If its the first time being called, add an expiry caveat and a MethodCaveat for "EchoBlessings".
diff --git a/services/identity/internal/revocation/revocation_manager.go b/services/identity/internal/revocation/revocation_manager.go
index 9cd28e1..de4ab73 100644
--- a/services/identity/internal/revocation/revocation_manager.go
+++ b/services/identity/internal/revocation/revocation_manager.go
@@ -8,6 +8,7 @@
 	"sync"
 	"time"
 
+	"v.io/v23/context"
 	"v.io/v23/security"
 )
 
@@ -78,7 +79,7 @@
 	return timestamp
 }
 
-func isRevoked(_ security.Call, key []byte) error {
+func isRevoked(_ *context.T, key []byte) error {
 	revocationLock.RLock()
 	if revocationDB == nil {
 		revocationLock.RUnlock()
diff --git a/services/security/discharger/discharger.go b/services/security/discharger/discharger.go
index 9738c23..3d42000 100644
--- a/services/security/discharger/discharger.go
+++ b/services/security/discharger/discharger.go
@@ -18,7 +18,7 @@
 	if tp == nil {
 		return security.Discharge{}, fmt.Errorf("Caveat %v does not represent a third party caveat", caveat)
 	}
-	if err := tp.Dischargeable(call); err != nil {
+	if err := tp.Dischargeable(call.Context()); err != nil {
 		return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", tp, err)
 	}
 	expiry, err := security.ExpiryCaveat(time.Now().Add(15 * time.Minute))
diff --git a/services/wsprd/rpc/server/authorizer.go b/services/wsprd/rpc/server/authorizer.go
index 2646f87..495b2cf 100644
--- a/services/wsprd/rpc/server/authorizer.go
+++ b/services/wsprd/rpc/server/authorizer.go
@@ -2,7 +2,6 @@
 
 import (
 	"v.io/v23/context"
-	"v.io/v23/security"
 )
 
 type authorizer struct {
@@ -10,5 +9,5 @@
 }
 
 func (a *authorizer) Authorize(ctx *context.T) error {
-	return a.authFunc(security.GetCall(ctx))
+	return a.authFunc(ctx)
 }
diff --git a/services/wsprd/rpc/server/server.go b/services/wsprd/rpc/server/server.go
index 01f7df4..6f90383 100644
--- a/services/wsprd/rpc/server/server.go
+++ b/services/wsprd/rpc/server/server.go
@@ -132,7 +132,7 @@
 
 func (s *Server) createRemoteInvokerFunc(handle int32) remoteInvokeFunc {
 	return func(methodName string, args []interface{}, call rpc.StreamServerCall) <-chan *lib.ServerRpcReply {
-		securityCall := s.convertSecurityCall(call, true)
+		securityCall := s.convertSecurityCall(call.Context(), true)
 
 		flow := s.helper.CreateNewFlow(s, call)
 		replyChan := make(chan *lib.ServerRpcReply, 1)
@@ -231,7 +231,7 @@
 		// Until the tests get fixed, we need to create a security context before creating the flow
 		// because creating the security context creates a flow and flow ids will be off.
 		// See https://github.com/veyron/release-issues/issues/1181
-		securityCall := s.convertSecurityCall(call, true)
+		securityCall := s.convertSecurityCall(call.Context(), true)
 
 		globChan := make(chan naming.GlobReply, 1)
 		flow := s.helper.CreateNewFlow(s, &globStream{
@@ -331,10 +331,10 @@
 
 // wsprCaveatValidator validates caveats in javascript.
 // It resolves each []security.Caveat in cavs to an error (or nil) and collects them in a slice.
-func (s *Server) validateCavsInJavascript(call security.Call, cavs [][]security.Caveat) []error {
+func (s *Server) validateCavsInJavascript(ctx *context.T, cavs [][]security.Caveat) []error {
 	flow := s.helper.CreateNewFlow(s, nil)
 	req := CaveatValidationRequest{
-		Call: s.convertSecurityCall(call, false),
+		Call: s.convertSecurityCall(ctx, false),
 		Cavs: cavs,
 	}
 
@@ -357,17 +357,17 @@
 
 	// TODO(bprosnitz) Consider using a different timeout than the standard rpc timeout.
 	var timeoutChan <-chan time.Time
-	if deadline, ok := call.Context().Deadline(); ok {
+	if deadline, ok := ctx.Deadline(); ok {
 		timeoutChan = time.After(deadline.Sub(time.Now()))
 	}
 
 	select {
 	case <-timeoutChan:
-		return makeListOfErrors(len(cavs), NewErrCaveatValidationTimeout(call.Context()))
+		return makeListOfErrors(len(cavs), NewErrCaveatValidationTimeout(ctx))
 	case reply := <-replyChan:
 		if len(reply) != len(cavs) {
 			vlog.VI(2).Infof("Wspr caveat validator received %d results from javascript but expected %d", len(reply), len(cavs))
-			return makeListOfErrors(len(cavs), NewErrInvalidValidationResponseFromJavascript(call.Context()))
+			return makeListOfErrors(len(cavs), NewErrInvalidValidationResponseFromJavascript(ctx))
 		}
 
 		return reply
@@ -377,7 +377,7 @@
 // wsprCaveatValidator validates caveats for javascript.
 // Certain caveats (PublicKeyThirdPartyCaveatX) are intercepted and handled in go.
 // This call validateCavsInJavascript to process the remaining caveats in javascript.
-func (s *Server) wsprCaveatValidator(call security.Call, cavs [][]security.Caveat) []error {
+func (s *Server) wsprCaveatValidator(ctx *context.T, cavs [][]security.Caveat) []error {
 	type validationStatus struct {
 		err   error
 		isSet bool
@@ -391,7 +391,7 @@
 		for _, cav := range chainCavs {
 			switch cav.Id {
 			case security.PublicKeyThirdPartyCaveatX.Id:
-				res := cav.Validate(call)
+				res := cav.Validate(ctx)
 				if res != nil {
 					valStatus[i] = validationStatus{
 						err:   res,
@@ -413,7 +413,7 @@
 		}
 	}
 
-	jsRes := s.validateCavsInJavascript(call, caveatChainsToValidate)
+	jsRes := s.validateCavsInJavascript(ctx, caveatChainsToValidate)
 
 	outResults := make([]error, len(cavs))
 	jsIndex := 0
@@ -429,7 +429,8 @@
 	return outResults
 }
 
-func (s *Server) convertSecurityCall(call security.Call, includeBlessingStrings bool) SecurityCall {
+func (s *Server) convertSecurityCall(ctx *context.T, includeBlessingStrings bool) SecurityCall {
+	call := security.GetCall(ctx)
 	// TODO(bprosnitz) Local/Remote Endpoint should always be non-nil, but isn't
 	// due to a TODO in vc/auth.go
 	var localEndpoint string
@@ -457,7 +458,6 @@
 		LocalBlessings:  localBlessings,
 		RemoteBlessings: s.convertBlessingsToHandle(call.RemoteBlessings()),
 	}
-	ctx := call.Context()
 	if includeBlessingStrings {
 		secCall.LocalBlessingStrings = security.LocalBlessingNames(ctx)
 		secCall.RemoteBlessingStrings, _ = security.RemoteBlessingNames(ctx)
@@ -465,13 +465,13 @@
 	return secCall
 }
 
-type remoteAuthFunc func(call security.Call) error
+type remoteAuthFunc func(ctx *context.T) error
 
 func (s *Server) createRemoteAuthFunc(handle int32) remoteAuthFunc {
-	return func(call security.Call) error {
+	return func(ctx *context.T) error {
 		// Until the tests get fixed, we need to create a security context before creating the flow
 		// because creating the security context creates a flow and flow ids will be off.
-		securityCall := s.convertSecurityCall(call, true)
+		securityCall := s.convertSecurityCall(ctx, true)
 
 		flow := s.helper.CreateNewFlow(s, nil)
 		replyChan := make(chan error, 1)
@@ -658,10 +658,19 @@
 	s.outstandingRequestLock.Lock()
 	s.outstandingAuthRequests = make(map[int32]chan error)
 	s.outstandingServerRequests = make(map[int32]chan *lib.ServerRpcReply)
-	s.outstandingValidationRequests = make(map[int32]chan []error)
 	s.outstandingRequestLock.Unlock()
 	s.serverStateLock.Unlock()
 	s.server.Stop()
+
+	// Only clear the validation requests map after stopping.  clearing
+	// it can cause the publisher to get stuck waiting for a caveat validtion
+	// that will never be answered, which in turn causes it to not be
+	// able to stop which prevents the server from stopping.
+	s.serverStateLock.Lock()
+	s.outstandingRequestLock.Lock()
+	s.outstandingValidationRequests = make(map[int32]chan []error)
+	s.outstandingRequestLock.Unlock()
+	s.serverStateLock.Unlock()
 }
 
 func (s *Server) AddName(name string) error {