services/wsprd: WSPR component of go/vcl/7026
MultiPart: 2/2
Change-Id: Ie4b2d99ce50cd9733191710ac9df61daff88b0d8
diff --git a/services/wsprd/app/app.go b/services/wsprd/app/app.go
index 323303d..6caddf9 100644
--- a/services/wsprd/app/app.go
+++ b/services/wsprd/app/app.go
@@ -99,8 +99,6 @@
// the default implementation.
writerCreator func(id int32) lib.ClientWriter
- veyronProxyEP string
-
// Store for all the Blessings that javascript has a handle to.
blessingsStore *principal.JSBlessingsHandles
@@ -111,16 +109,20 @@
}
// NewController creates a new Controller. writerCreator will be used to create a new flow for rpcs to
-// javascript server. veyronProxyEP is an endpoint for the veyron proxy to serve through. It can't be empty.
+// javascript server.
func NewController(ctx *context.T, writerCreator func(id int32) lib.ClientWriter, listenSpec *ipc.ListenSpec, namespaceRoots []string, p security.Principal) (*Controller, error) {
ctx, cancel := context.WithCancel(ctx)
- ctx, _ = vtrace.SetNewTrace(ctx)
-
if namespaceRoots != nil {
- v23.GetNamespace(ctx).SetRoots(namespaceRoots...)
+ var err error
+ ctx, _, err = v23.SetNewNamespace(ctx, namespaceRoots...)
+ if err != nil {
+ return nil, err
+ }
}
+ ctx, _ = vtrace.SetNewTrace(ctx)
+
ctx, err := v23.SetPrincipal(ctx, p)
if err != nil {
return nil, err
diff --git a/services/wsprd/browspr/browspr.go b/services/wsprd/browspr/browspr.go
index 08144eb..bec1889 100644
--- a/services/wsprd/browspr/browspr.go
+++ b/services/wsprd/browspr/browspr.go
@@ -64,26 +64,44 @@
return browspr
}
-func (browspr *Browspr) Shutdown() {
+func (b *Browspr) Shutdown() {
// TODO(ataly, bprosnitz): Get rid of this method if possible.
}
+// CreateInstance creates a new pipe and stores it in activeInstances map.
+func (b *Browspr) createInstance(instanceId int32, origin string, namespaceRoots []string, proxy string) (*pipe, error) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ // Make sure we don't already have an instance.
+ p, ok := b.activeInstances[instanceId]
+ if ok {
+ return nil, fmt.Errorf("InstanceId %v already has an open instance.", instanceId)
+ }
+
+ p = newPipe(b, instanceId, origin, namespaceRoots, proxy)
+ if p == nil {
+ return nil, fmt.Errorf("Could not create pipe for instanceId %v and origin %v", instanceId, origin)
+ }
+ b.activeInstances[instanceId] = p
+ return p, nil
+}
+
// HandleMessage handles most messages from javascript and forwards them to a
// Controller.
func (b *Browspr) HandleMessage(instanceId int32, origin, msg string) error {
b.mu.Lock()
- instance, ok := b.activeInstances[instanceId]
- if !ok {
- instance = newPipe(b, instanceId, origin)
- if instance == nil {
- b.mu.Unlock()
- return fmt.Errorf("Could not create pipe for origin %v: origin")
- }
- b.activeInstances[instanceId] = instance
- }
+ p, ok := b.activeInstances[instanceId]
b.mu.Unlock()
+ if !ok {
+ return fmt.Errorf("No pipe found for instanceId %v. Must send CreateInstance message first.", instanceId)
+ }
- return instance.handleMessage(msg)
+ if origin != p.origin {
+ return fmt.Errorf("Invalid message origin. InstanceId %v has origin %v, but message is from %v.", instanceId, p.origin, origin)
+ }
+
+ return p.handleMessage(msg)
}
// HandleCleanupRpc cleans up the specified instance state. (For instance,
@@ -96,11 +114,11 @@
b.mu.Lock()
- if instance, ok := b.activeInstances[msg.InstanceId]; ok {
+ if pipe, ok := b.activeInstances[msg.InstanceId]; ok {
// We must unlock the mutex before calling cleanunp, otherwise
// browspr deadlocks.
b.mu.Unlock()
- instance.cleanup()
+ pipe.cleanup()
b.mu.Lock()
delete(b.activeInstances, msg.InstanceId)
@@ -160,3 +178,19 @@
res := b.accountManager.OriginHasAccount(msg.Origin)
return vdl.ValueFromReflect(reflect.ValueOf(res))
}
+
+// HandleCreateInstanceRpc sets the namespace root and proxy on the pipe, if
+// any are provided.
+func (b *Browspr) HandleCreateInstanceRpc(val *vdl.Value) (*vdl.Value, error) {
+ var msg CreateInstanceMessage
+ if err := vdl.Convert(&msg, val); err != nil {
+ return nil, fmt.Errorf("HandleCreateInstanceMessage did not receive CreateInstanceMessage, received: %v, %v", val, err)
+ }
+
+ _, err := b.createInstance(msg.InstanceId, msg.Origin, msg.NamespaceRoots, msg.Proxy)
+ if err != nil {
+ return nil, err
+ }
+
+ return nil, nil
+}
diff --git a/services/wsprd/browspr/browspr.vdl b/services/wsprd/browspr/browspr.vdl
index 263b601..66eae99 100644
--- a/services/wsprd/browspr/browspr.vdl
+++ b/services/wsprd/browspr/browspr.vdl
@@ -40,3 +40,10 @@
}
type GetAccountsMessage struct {}
+
+type CreateInstanceMessage struct {
+ InstanceId int32
+ Origin string
+ NamespaceRoots []string
+ Proxy string
+}
diff --git a/services/wsprd/browspr/browspr.vdl.go b/services/wsprd/browspr/browspr.vdl.go
index c0eeeee..efc80f7 100644
--- a/services/wsprd/browspr/browspr.vdl.go
+++ b/services/wsprd/browspr/browspr.vdl.go
@@ -84,6 +84,18 @@
}) {
}
+type CreateInstanceMessage struct {
+ InstanceId int32
+ Origin string
+ NamespaceRoots []string
+ Proxy string
+}
+
+func (CreateInstanceMessage) __VDLReflect(struct {
+ Name string "v.io/x/ref/services/wsprd/browspr.CreateInstanceMessage"
+}) {
+}
+
func init() {
vdl.Register((*StartMessage)(nil))
vdl.Register((*blessingRoot)(nil))
@@ -92,4 +104,5 @@
vdl.Register((*CleanupMessage)(nil))
vdl.Register((*OriginHasAccountMessage)(nil))
vdl.Register((*GetAccountsMessage)(nil))
+ vdl.Register((*CreateInstanceMessage)(nil))
}
diff --git a/services/wsprd/browspr/browspr_test.go b/services/wsprd/browspr/browspr_test.go
index 55f278b..90b130c 100644
--- a/services/wsprd/browspr/browspr_test.go
+++ b/services/wsprd/browspr/browspr_test.go
@@ -199,6 +199,14 @@
t.Fatalf("Failed to marshall app message to json: %v", err)
}
+ createInstanceMessage := CreateInstanceMessage{
+ InstanceId: msgInstanceId,
+ Origin: msgOrigin,
+ NamespaceRoots: nil,
+ Proxy: "",
+ }
+ _, err = browspr.HandleCreateInstanceRpc(vdl.ValueOf(createInstanceMessage))
+
err = browspr.HandleMessage(msgInstanceId, msgOrigin, string(msg))
if err != nil {
t.Fatalf("Error while handling message: %v", err)
diff --git a/services/wsprd/browspr/main/main_nacl.go b/services/wsprd/browspr/main/main_nacl.go
index b75b5f4..a492cd5 100644
--- a/services/wsprd/browspr/main/main_nacl.go
+++ b/services/wsprd/browspr/main/main_nacl.go
@@ -262,6 +262,7 @@
inst.channel.RegisterRequestHandler("auth:associate-account", inst.browspr.HandleAuthAssociateAccountRpc)
inst.channel.RegisterRequestHandler("auth:get-accounts", inst.browspr.HandleAuthGetAccountsRpc)
inst.channel.RegisterRequestHandler("auth:origin-has-account", inst.browspr.HandleAuthOriginHasAccountRpc)
+ inst.channel.RegisterRequestHandler("create-instance", inst.browspr.HandleCreateInstanceRpc)
inst.channel.RegisterRequestHandler("cleanup", inst.browspr.HandleCleanupRpc)
return nil, nil
diff --git a/services/wsprd/browspr/pipe.go b/services/wsprd/browspr/pipe.go
index 6061380..7fa9bdc 100644
--- a/services/wsprd/browspr/pipe.go
+++ b/services/wsprd/browspr/pipe.go
@@ -17,7 +17,7 @@
instanceId int32
}
-func newPipe(b *Browspr, instanceId int32, origin string) *pipe {
+func newPipe(b *Browspr, instanceId int32, origin string, namespaceRoots []string, proxy string) *pipe {
pipe := &pipe{
browspr: b,
origin: origin,
@@ -48,7 +48,19 @@
}
}
- pipe.controller, err = app.NewController(b.ctx, pipe.createWriter, b.listenSpec, b.namespaceRoots, p)
+ // Shallow copy browspr's default listenSpec. If we have passed in a
+ // proxy, set listenSpec.proxy.
+ listenSpec := *b.listenSpec
+ if proxy != "" {
+ listenSpec.Proxy = proxy
+ }
+
+ // If we have been passed in namespace roots, pass them to NewController, otherwise pass browspr's default.
+ if namespaceRoots == nil {
+ namespaceRoots = b.namespaceRoots
+ }
+
+ pipe.controller, err = app.NewController(b.ctx, pipe.createWriter, &listenSpec, namespaceRoots, p)
if err != nil {
vlog.Errorf("Could not create controller: %v", err)
return nil