ref/services/device: Introduce a DispatcherWrapper and use it to convert
the device manager to xrpc.
Change-Id: I57bc5778c07dd95c766d6b5a7b1a1b25df10a85a
diff --git a/lib/dispatcher/wrapped.go b/lib/dispatcher/wrapped.go
new file mode 100644
index 0000000..b8aaf19
--- /dev/null
+++ b/lib/dispatcher/wrapped.go
@@ -0,0 +1,42 @@
+// 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 dispatcher
+
+import (
+ "v.io/v23/context"
+ "v.io/v23/rpc"
+ "v.io/v23/security"
+)
+
+// DispatcherWrapper is used when a dispatcher can't be constructed at server
+// creation time. The most common use for this is when the dispatcher needs
+// to know some information about the server to be constructed. For example
+// it is sometimes helpful to know the server's endpoints.
+// In such cases you can construct a DispatcherWrapper which will simply block
+// all lookups until the real dispatcher is set with SetDispatcher.
+type DispatcherWrapper struct {
+ wrapped rpc.Dispatcher
+ wrappedIsSet chan struct{}
+}
+
+// Lookup will wait until SetDispatcher is called and then simply forward requests
+// to the underlying dispatcher.
+func (w *DispatcherWrapper) Lookup(ctx *context.T, suffix string) (interface{}, security.Authorizer, error) {
+ <-w.wrappedIsSet
+ return w.wrapped.Lookup(ctx, suffix)
+}
+
+// SetDispatcher sets the underlying dispatcher and allows Lookups to proceed.
+func (w *DispatcherWrapper) SetDispatcher(d rpc.Dispatcher) {
+ w.wrapped = d
+ close(w.wrappedIsSet)
+}
+
+// NewDispatcherWrapper creates a new DispatcherWrapper.
+func NewDispatcherWrapper() *DispatcherWrapper {
+ return &DispatcherWrapper{
+ wrappedIsSet: make(chan struct{}),
+ }
+}
diff --git a/services/device/claimable/main.go b/services/device/claimable/main.go
index 0fd53e4..1c92bbf 100644
--- a/services/device/claimable/main.go
+++ b/services/device/claimable/main.go
@@ -20,6 +20,7 @@
"v.io/x/ref/lib/security/securityflag"
"v.io/x/ref/lib/signals"
"v.io/x/ref/lib/v23cmd"
+ "v.io/x/ref/lib/xrpc"
_ "v.io/x/ref/runtime/factories/roaming"
"v.io/x/ref/services/device/internal/claim"
"v.io/x/ref/services/identity"
@@ -41,16 +42,10 @@
return errors.New("device is already claimed")
}
- server, err := v23.NewServer(ctx)
+ server, err := xrpc.NewDispatchingServer(ctx, "", claimable)
if err != nil {
return err
}
- if _, err := server.Listen(v23.GetListenSpec(ctx)); err != nil {
- return err
- }
- if err := server.ServeDispatcher("", claimable); err != nil {
- return err
- }
status := server.Status()
ctx.Infof("Listening on: %v", status.Endpoints)
diff --git a/services/device/deviced/internal/starter/starter.go b/services/device/deviced/internal/starter/starter.go
index afd6e1e..f6cdcbf 100644
--- a/services/device/deviced/internal/starter/starter.go
+++ b/services/device/deviced/internal/starter/starter.go
@@ -20,6 +20,7 @@
"v.io/v23/rpc"
"v.io/v23/security"
"v.io/v23/verror"
+ displib "v.io/x/ref/lib/dispatcher"
"v.io/x/ref/lib/xrpc"
"v.io/x/ref/runtime/factories/roaming"
"v.io/x/ref/services/debug/debuglib"
@@ -331,21 +332,17 @@
// (1) Function to be called to force the service to shutdown
// (2) Any errors in starting the service (in which case, (1) will be nil)
func startDeviceServer(ctx *context.T, args DeviceArgs, mt string, permStore *pathperms.PathStore) (shutdown func(), err error) {
- server, err := v23.NewServer(ctx)
+ ctx = v23.WithListenSpec(ctx, args.ListenSpec)
+ wrapper := displib.NewDispatcherWrapper()
+ server, err := xrpc.NewDispatchingServer(ctx, args.name(mt), wrapper)
if err != nil {
return nil, err
}
- shutdown = func() { server.Stop() }
- endpoints, err := server.Listen(args.ListenSpec)
- if err != nil {
- shutdown()
- return nil, err
- }
- args.ConfigState.Name = endpoints[0].Name()
+ args.ConfigState.Name = server.Status().Endpoints[0].Name()
dispatcher, dShutdown, err := impl.NewDispatcher(ctx, args.ConfigState, mt, args.TestMode, args.RestartCallback, permStore)
if err != nil {
- shutdown()
+ server.Stop()
return nil, err
}
@@ -357,10 +354,7 @@
dShutdown()
ctx.Infof("Stopped device.")
}
- if err := server.ServeDispatcher(args.name(mt), dispatcher); err != nil {
- shutdown()
- return nil, err
- }
+ wrapper.SetDispatcher(dispatcher)
ctx.Infof("Device manager (%v) published as %v", args.ConfigState.Name, args.name(mt))
return shutdown, nil
}