wspr: Treat WSPR as an RPC service, part 3.

Transitioning security related calls to the controller interface.

MultiPart: 2/2
Change-Id: Id0a2572c8937a2af80597d9645abd8f61d42e73b
diff --git a/services/wsprd/app/app.go b/services/wsprd/app/app.go
index e2d784c..fc6b964 100644
--- a/services/wsprd/app/app.go
+++ b/services/wsprd/app/app.go
@@ -646,93 +646,66 @@
 	}
 }
 
-// HandleUnlinkJSBlessings removes the specified blessings from the JS blessings
-// store.  'data' should be a JSON encoded number (representing the blessings handle).
-func (c *Controller) HandleUnlinkJSBlessings(data string, w lib.ClientWriter) {
-	var handle int32
-	if err := json.Unmarshal([]byte(data), &handle); err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
-	}
+// UnlinkJSBlessings removes the given blessings from the blessings store.
+func (c *Controller) UnlinkJSBlessings(_ ipc.ServerContext, handle int32) error {
 	c.blessingsStore.Remove(handle)
+	return nil
 }
 
-func (c *Controller) getBlessingsHandle(handle int32) (*principal.BlessingsHandle, error) {
-	id := c.blessingsStore.Get(handle)
-	if id == nil {
-		return nil, verror.New(unknownBlessings, nil)
-	}
-	return principal.ConvertBlessingsToHandle(id, handle), nil
-}
-
-func (c *Controller) blessPublicKey(request BlessingRequest) (*principal.BlessingsHandle, error) {
+// BlessPublicKey creates a new blessing.
+func (c *Controller) BlessPublicKey(_ ipc.ServerContext,
+	handle int32,
+	caveats []security.Caveat,
+	duration time.Duration,
+	extension string) (int32, string, error) {
 	var blessee security.Blessings
-	if blessee = c.blessingsStore.Get(request.Handle); blessee == nil {
-		return nil, verror.New(invalidBlessingsHandle, nil)
+	if blessee = c.blessingsStore.Get(handle); blessee == nil {
+		return 0, "", verror.New(invalidBlessingsHandle, nil)
 	}
 
-	expiryCav, err := security.ExpiryCaveat(time.Now().Add(time.Duration(request.DurationMs) * time.Millisecond))
+	expiryCav, err := security.ExpiryCaveat(time.Now().Add(duration))
 	if err != nil {
-		return nil, err
+		return 0, "", err
 	}
-	caveats := append(request.Caveats, expiryCav)
+	caveats = append(caveats, expiryCav)
 
 	// TODO(ataly, ashankar, bjornick): Currently the Bless operation is carried
 	// out using the Default blessing in this principal's blessings store. We
 	// should change this so that the JS blessing request can also specify the
 	// blessing to be used for the Bless operation.
 	p := veyron2.GetPrincipal(c.ctx)
-	blessings, err := p.Bless(blessee.PublicKey(), p.BlessingStore().Default(), request.Extension, caveats[0], caveats[1:]...)
+	key := blessee.PublicKey()
+	blessing := p.BlessingStore().Default()
+	blessings, err := p.Bless(key, blessing, extension, caveats[0], caveats[1:]...)
 	if err != nil {
-		return nil, err
+		return 0, "", err
 	}
-
-	return principal.ConvertBlessingsToHandle(blessings, c.blessingsStore.Add(blessings)), nil
+	handle = c.blessingsStore.Add(blessings)
+	encodedKey, err := principal.EncodePublicKey(blessings.PublicKey())
+	if err != nil {
+		return 0, "", err
+	}
+	return handle, encodedKey, nil
 }
 
-// HandleBlessPublicKey handles a blessing request from JS.
-func (c *Controller) HandleBlessPublicKey(data string, w lib.ClientWriter) {
-	var request BlessingRequest
-	if err := lib.VomDecode(data, &request); err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
-	}
-
-	handle, err := c.blessPublicKey(request)
-	if err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
-	}
-
-	// Send the id back.
-	if err := w.Send(lib.ResponseFinal, handle); err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
-	}
-}
-
-func (c *Controller) HandleCreateBlessings(data string, w lib.ClientWriter) {
-	var extension string
-	if err := json.Unmarshal([]byte(data), &extension); err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
-	}
+// CreateBlessings creates a new principal self-blessed with the given extension.
+func (c *Controller) CreateBlessings(_ ipc.ServerContext,
+	extension string) (int32, string, error) {
 	p, err := vsecurity.NewPrincipal()
 	if err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
+		return 0, "", verror.Convert(verror.ErrInternal, nil, err)
 	}
-
 	blessings, err := p.BlessSelf(extension)
 	if err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
+		return 0, "", verror.Convert(verror.ErrInternal, nil, err)
 	}
-	handle := principal.ConvertBlessingsToHandle(blessings, c.blessingsStore.Add(blessings))
-	if err := w.Send(lib.ResponseFinal, handle); err != nil {
-		w.Error(verror.Convert(verror.ErrInternal, nil, err))
-		return
+
+	handle := c.blessingsStore.Add(blessings)
+	encodedKey, err := principal.EncodePublicKey(blessings.PublicKey())
+	if err != nil {
+		return 0, "", err
 	}
+	return handle, encodedKey, nil
 }
 
 type remoteBlessingsRequest struct {
diff --git a/services/wsprd/app/app.vdl b/services/wsprd/app/app.vdl
index f83c7ca..a36178e 100644
--- a/services/wsprd/app/app.vdl
+++ b/services/wsprd/app/app.vdl
@@ -3,7 +3,6 @@
 package app
 
 import (
-	"v.io/core/veyron2/security"
 	"v.io/core/veyron2/vtrace"
 )
 
@@ -21,10 +20,3 @@
 	OutArgs       []any
 	TraceResponse vtrace.Response
 }
-
-type BlessingRequest struct {
-	Handle     int32
-	Caveats    []security.Caveat
-	DurationMs int32
-	Extension  string
-}
diff --git a/services/wsprd/app/app.vdl.go b/services/wsprd/app/app.vdl.go
index 0140423..adf9666 100644
--- a/services/wsprd/app/app.vdl.go
+++ b/services/wsprd/app/app.vdl.go
@@ -10,7 +10,6 @@
 	"v.io/core/veyron2/vdl"
 
 	// VDL user imports
-	"v.io/core/veyron2/security"
 	"v.io/core/veyron2/vtrace"
 )
 
@@ -39,20 +38,7 @@
 }) {
 }
 
-type BlessingRequest struct {
-	Handle     int32
-	Caveats    []security.Caveat
-	DurationMs int32
-	Extension  string
-}
-
-func (BlessingRequest) __VDLReflect(struct {
-	Name string "v.io/wspr/veyron/services/wsprd/app.BlessingRequest"
-}) {
-}
-
 func init() {
 	vdl.Register((*VeyronRPCRequest)(nil))
 	vdl.Register((*VeyronRPCResponse)(nil))
-	vdl.Register((*BlessingRequest)(nil))
 }
diff --git a/services/wsprd/app/controller.vdl b/services/wsprd/app/controller.vdl
index b79ade9..60616b9 100644
--- a/services/wsprd/app/controller.vdl
+++ b/services/wsprd/app/controller.vdl
@@ -1,14 +1,27 @@
 package app
 
+import (
+	"time"
+
+	"v.io/core/veyron2/security"
+)
+
 type Controller interface {
-     // Serve instructs WSPR to start listening for calls on behalf
-     // of a javascript server.
-     Serve(name string, serverId uint32) error
-     // Stop instructs WSPR to stop listening for calls for the
-     // given javascript server.
-     Stop(serverId uint32) error
-     // AddName adds a published name to an existing server.
-     AddName(serverId uint32, name string) error
-     // RemoveName removes a published name from an existing server.
-     RemoveName(serverId uint32, name string) error
+	// Serve instructs WSPR to start listening for calls on behalf
+	// of a javascript server.
+	Serve(name string, serverId uint32) error
+	// Stop instructs WSPR to stop listening for calls for the
+	// given javascript server.
+	Stop(serverId uint32) error
+	// AddName adds a published name to an existing server.
+	AddName(serverId uint32, name string) error
+	// RemoveName removes a published name from an existing server.
+	RemoveName(serverId uint32, name string) error
+
+	// UnlinkJSBlessings removes the given blessings from the blessings store.
+	UnlinkJSBlessings(handle int32) error
+	// BlessPublicKey creates a new blessing.
+	BlessPublicKey(fromHandle int32, caveats []security.Caveat, durationMs time.Duration, extension string) (handle int32, publicKey string | error)
+	// CreateBlessings creates a new principal self-blessed with the given extension.
+	CreateBlessings(extension string) (handle int32, publicKey string | error)
 }
diff --git a/services/wsprd/app/controller.vdl.go b/services/wsprd/app/controller.vdl.go
index d75b029..7971a9b 100644
--- a/services/wsprd/app/controller.vdl.go
+++ b/services/wsprd/app/controller.vdl.go
@@ -8,6 +8,11 @@
 	"v.io/core/veyron2"
 	"v.io/core/veyron2/context"
 	"v.io/core/veyron2/ipc"
+
+	// VDL user imports
+	"time"
+	"v.io/core/veyron2/security"
+	_ "v.io/core/veyron2/vdl/vdlroot/src/time"
 )
 
 // ControllerClientMethods is the client interface
@@ -23,6 +28,12 @@
 	AddName(ctx *context.T, serverId uint32, name string, opts ...ipc.CallOpt) error
 	// RemoveName removes a published name from an existing server.
 	RemoveName(ctx *context.T, serverId uint32, name string, opts ...ipc.CallOpt) error
+	// UnlinkJSBlessings removes the given blessings from the blessings store.
+	UnlinkJSBlessings(ctx *context.T, handle int32, opts ...ipc.CallOpt) error
+	// BlessPublicKey creates a new blessing.
+	BlessPublicKey(ctx *context.T, fromHandle int32, caveats []security.Caveat, durationMs time.Duration, extension string, opts ...ipc.CallOpt) (handle int32, publicKey string, err error)
+	// CreateBlessings creates a new principal self-blessed with the given extension.
+	CreateBlessings(ctx *context.T, extension string, opts ...ipc.CallOpt) (handle int32, publicKey string, err error)
 }
 
 // ControllerClientStub adds universal methods to ControllerClientMethods.
@@ -90,6 +101,33 @@
 	return
 }
 
+func (c implControllerClientStub) UnlinkJSBlessings(ctx *context.T, i0 int32, opts ...ipc.CallOpt) (err error) {
+	var call ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "UnlinkJSBlessings", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish()
+	return
+}
+
+func (c implControllerClientStub) BlessPublicKey(ctx *context.T, i0 int32, i1 []security.Caveat, i2 time.Duration, i3 string, opts ...ipc.CallOpt) (o0 int32, o1 string, err error) {
+	var call ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "BlessPublicKey", []interface{}{i0, i1, i2, i3}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0, &o1)
+	return
+}
+
+func (c implControllerClientStub) CreateBlessings(ctx *context.T, i0 string, opts ...ipc.CallOpt) (o0 int32, o1 string, err error) {
+	var call ipc.Call
+	if call, err = c.c(ctx).StartCall(ctx, c.name, "CreateBlessings", []interface{}{i0}, opts...); err != nil {
+		return
+	}
+	err = call.Finish(&o0, &o1)
+	return
+}
+
 // ControllerServerMethods is the interface a server writer
 // implements for Controller.
 type ControllerServerMethods interface {
@@ -103,6 +141,12 @@
 	AddName(ctx ipc.ServerContext, serverId uint32, name string) error
 	// RemoveName removes a published name from an existing server.
 	RemoveName(ctx ipc.ServerContext, serverId uint32, name string) error
+	// UnlinkJSBlessings removes the given blessings from the blessings store.
+	UnlinkJSBlessings(ctx ipc.ServerContext, handle int32) error
+	// BlessPublicKey creates a new blessing.
+	BlessPublicKey(ctx ipc.ServerContext, fromHandle int32, caveats []security.Caveat, durationMs time.Duration, extension string) (handle int32, publicKey string, err error)
+	// CreateBlessings creates a new principal self-blessed with the given extension.
+	CreateBlessings(ctx ipc.ServerContext, extension string) (handle int32, publicKey string, err error)
 }
 
 // ControllerServerStubMethods is the server interface containing
@@ -156,6 +200,18 @@
 	return s.impl.RemoveName(ctx, i0, i1)
 }
 
+func (s implControllerServerStub) UnlinkJSBlessings(ctx ipc.ServerContext, i0 int32) error {
+	return s.impl.UnlinkJSBlessings(ctx, i0)
+}
+
+func (s implControllerServerStub) BlessPublicKey(ctx ipc.ServerContext, i0 int32, i1 []security.Caveat, i2 time.Duration, i3 string) (int32, string, error) {
+	return s.impl.BlessPublicKey(ctx, i0, i1, i2, i3)
+}
+
+func (s implControllerServerStub) CreateBlessings(ctx ipc.ServerContext, i0 string) (int32, string, error) {
+	return s.impl.CreateBlessings(ctx, i0)
+}
+
 func (s implControllerServerStub) Globber() *ipc.GlobState {
 	return s.gs
 }
@@ -203,5 +259,37 @@
 				{"name", ``},     // string
 			},
 		},
+		{
+			Name: "UnlinkJSBlessings",
+			Doc:  "// UnlinkJSBlessings removes the given blessings from the blessings store.",
+			InArgs: []ipc.ArgDesc{
+				{"handle", ``}, // int32
+			},
+		},
+		{
+			Name: "BlessPublicKey",
+			Doc:  "// BlessPublicKey creates a new blessing.",
+			InArgs: []ipc.ArgDesc{
+				{"fromHandle", ``}, // int32
+				{"caveats", ``},    // []security.Caveat
+				{"durationMs", ``}, // time.Duration
+				{"extension", ``},  // string
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"handle", ``},    // int32
+				{"publicKey", ``}, // string
+			},
+		},
+		{
+			Name: "CreateBlessings",
+			Doc:  "// CreateBlessings creates a new principal self-blessed with the given extension.",
+			InArgs: []ipc.ArgDesc{
+				{"extension", ``}, // string
+			},
+			OutArgs: []ipc.ArgDesc{
+				{"handle", ``},    // int32
+				{"publicKey", ``}, // string
+			},
+		},
 	},
 }
diff --git a/services/wsprd/app/messaging.go b/services/wsprd/app/messaging.go
index f605426..7de31b4 100644
--- a/services/wsprd/app/messaging.go
+++ b/services/wsprd/app/messaging.go
@@ -108,24 +108,22 @@
 		c.SendOnStream(msg.Id, msg.Data, w)
 	case StreamCloseMessage:
 		c.CloseStream(msg.Id)
+
 	case ServerResponseMessage:
 		go c.HandleServerResponse(msg.Id, msg.Data)
-	case SignatureRequestMessage:
-		go c.HandleSignatureRequest(ctx, msg.Data, w)
 	case LookupResponseMessage:
 		go c.HandleLookupResponse(msg.Id, msg.Data)
-	case BlessPublicKeyMessage:
-		go c.HandleBlessPublicKey(msg.Data, w)
-	case CreateBlessingsMessage:
-		go c.HandleCreateBlessings(msg.Data, w)
-	case UnlinkBlessingsMessage:
-		go c.HandleUnlinkJSBlessings(msg.Data, w)
 	case AuthResponseMessage:
 		go c.HandleAuthResponse(msg.Id, msg.Data)
-	case NamespaceRequestMessage:
-		go c.HandleNamespaceRequest(ctx, msg.Data, w)
+
 	case RemoteBlessings:
 		go c.HandleRemoteBlessingsRequest(ctx, msg.Data, w)
+	case SignatureRequestMessage:
+		go c.HandleSignatureRequest(ctx, msg.Data, w)
+
+	case NamespaceRequestMessage:
+		go c.HandleNamespaceRequest(ctx, msg.Data, w)
+
 	default:
 		w.Error(verror.New(errUnknownMessageType, ctx, msg.Type))
 	}
diff --git a/services/wsprd/principal/blessings.go b/services/wsprd/principal/blessings.go
index 97ea583..cdcad83 100644
--- a/services/wsprd/principal/blessings.go
+++ b/services/wsprd/principal/blessings.go
@@ -11,12 +11,20 @@
 }
 
 func ConvertBlessingsToHandle(blessings security.Blessings, handle int32) *BlessingsHandle {
-	bytes, err := blessings.PublicKey().MarshalBinary()
+	encoded, err := EncodePublicKey(blessings.PublicKey())
 	if err != nil {
 		panic(err)
 	}
 	return &BlessingsHandle{
 		Handle:    handle,
-		PublicKey: base64.StdEncoding.EncodeToString(bytes),
+		PublicKey: encoded,
 	}
 }
+
+func EncodePublicKey(key security.PublicKey) (string, error) {
+	bytes, err := key.MarshalBinary()
+	if err != nil {
+		return "", err
+	}
+	return base64.StdEncoding.EncodeToString(bytes), nil
+}