Merge "veyron/lib/modules: adding an option to pass Config to a child process"
diff --git a/lib/flags/flags.go b/lib/flags/flags.go
index b8a1473..cb9dde9 100644
--- a/lib/flags/flags.go
+++ b/lib/flags/flags.go
@@ -25,12 +25,12 @@
// --veyron.proxy
Listen
// --veyron.acl (which may be repeated to supply multiple values)
+ // ACL files are named - i.e. --veyron.acl=<name>:<file> with the
+ // name <runtime> reserved for use by the runtime.
ACL
)
const defaultNamespaceRoot = "/proxy.envyor.com:8101"
-const defaultACLName = "veyron"
-const defaultACLFile = "acl.json"
// Flags represents the set of flag groups created by a call to
// CreateAndRegister.
@@ -132,7 +132,6 @@
func createAndRegisterACLFlags(fs *flag.FlagSet) *ACLFlags {
f := &ACLFlags{}
- f.flag.files = map[string]string{defaultACLName: defaultACLFile}
fs.Var(&f.flag, "veyron.acl", "specify an acl file as <name>:<aclfile>")
return f
}
diff --git a/lib/flags/flags_test.go b/lib/flags/flags_test.go
index ee9c32a..3514776 100644
--- a/lib/flags/flags_test.go
+++ b/lib/flags/flags_test.go
@@ -45,10 +45,10 @@
func TestACLFlags(t *testing.T) {
fs := flag.NewFlagSet("test", flag.ContinueOnError)
fl := flags.CreateAndRegister(fs, flags.Runtime, flags.ACL)
- args := []string{"--veyron.acl=veyron:foo.json", "--veyron.acl=bar:bar.json", "--veyron.acl=baz:bar:baz.json"}
+ args := []string{"--veyron.acl=runtime:foo.json", "--veyron.acl=bar:bar.json", "--veyron.acl=baz:bar:baz.json"}
fl.Parse(args)
aclf := fl.ACLFlags()
- if got, want := aclf.ACLFile("veyron"), "foo.json"; got != want {
+ if got, want := aclf.ACLFile("runtime"), "foo.json"; got != want {
t.Errorf("got %t, want %t", got, want)
}
if got, want := aclf.ACLFile("bar"), "bar.json"; got != want {
@@ -77,7 +77,7 @@
}
fs = flag.NewFlagSet("test", flag.ContinueOnError)
- fs.SetOutput(ioutil.Discard)
+ //fs.SetOutput(ioutil.Discard)
fl = flags.CreateAndRegister(fs, flags.ACL)
args = []string{"--veyron.acl=noname"}
err = fl.Parse(args)
@@ -176,7 +176,7 @@
t.Errorf("got %q, want %q", got, want)
}
aclf := fl.ACLFlags()
- if got, want := aclf.ACLFile("veyron"), "acl.json"; got != want {
+ if got, want := aclf.ACLFile(""), ""; got != want {
t.Errorf("got %q, want %q", got, want)
}
}
diff --git a/lib/modules/core/core_test.go b/lib/modules/core/core_test.go
index 23037c0..d8a2a1d 100644
--- a/lib/modules/core/core_test.go
+++ b/lib/modules/core/core_test.go
@@ -241,7 +241,7 @@
srvSession := expect.NewSession(t, srv.Stdout(), time.Minute)
srvSession.ExpectVar("NAME")
addr := srvSession.ExpectVar("ADDR")
- addr = naming.JoinAddressName(addr, "//")
+ addr = naming.JoinAddressName(addr, "")
// Resolve an object
resolver, err := sh.Start(core.ResolveCommand, nil, rootName+"/"+echoName)
@@ -260,7 +260,7 @@
}
// Resolve to a mount table using a rooted name.
- addr = naming.JoinAddressName(mountAddrs[mtName], "//echo")
+ addr = naming.JoinAddressName(mountAddrs[mtName], "echo")
resolver, err = sh.Start(core.ResolveMTCommand, nil, rootName+"/"+echoName)
if err != nil {
t.Fatalf("unexpected error: %s", err)
diff --git a/lib/modules/core/echo.go b/lib/modules/core/echo.go
index 8cc7b33..b1b8877 100644
--- a/lib/modules/core/echo.go
+++ b/lib/modules/core/echo.go
@@ -56,10 +56,10 @@
if err != nil {
return err
}
- if err := server.Serve(mp, disp); err != nil {
+ if err := server.ServeDispatcher(mp, disp); err != nil {
return err
}
- fmt.Fprintf(stdout, "NAME=%s\n", naming.MakeTerminal(naming.JoinAddressName(ep.String(), "")))
+ fmt.Fprintf(stdout, "NAME=%s\n", naming.JoinAddressName(ep.String(), ""))
fmt.Fprintf(stdout, "ADDR=%s\n", ep.String())
fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
modules.WaitForEOF(stdin)
diff --git a/lib/modules/core/mounttable.go b/lib/modules/core/mounttable.go
index b0104d5..7d5d7f8 100644
--- a/lib/modules/core/mounttable.go
+++ b/lib/modules/core/mounttable.go
@@ -58,7 +58,7 @@
if err != nil {
return fmt.Errorf("server.Listen failed: %s", err)
}
- if err := server.Serve(mp, mt); err != nil {
+ if err := server.ServeDispatcher(mp, mt); err != nil {
return fmt.Errorf("root failed: %s", err)
}
name := naming.JoinAddressName(ep.String(), "")
diff --git a/lib/netstate/netstate.go b/lib/netstate/netstate.go
index 68ee679..ff276b8 100644
--- a/lib/netstate/netstate.go
+++ b/lib/netstate/netstate.go
@@ -10,7 +10,7 @@
// A simple usage would be:
//
// state, _ := netstate.GetAccessibleIPs()
-// ipv4 := state.Filter(netstate.IsPublicIPv4)
+// ipv4 := state.Filter(netstate.IsPublicUnicastIPv4)
// // ipv4 will contain all of the public IPv4 addresses, if any.
//
// The example policy described above would be implemented using a
diff --git a/lib/signals/signals_test.go b/lib/signals/signals_test.go
index a34c0db..cfe3f16 100644
--- a/lib/signals/signals_test.go
+++ b/lib/signals/signals_test.go
@@ -317,7 +317,7 @@
if ep, err = server.Listen(profiles.LocalListenSpec); err != nil {
t.Fatalf("Got error: %v", err)
}
- if err := server.Serve("", ipc.LeafDispatcher(node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie())); err != nil {
+ if err := server.Serve("", node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie()); err != nil {
t.Fatalf("Got error: %v", err)
}
return server, naming.JoinAddressName(ep.String(), ""), ch
diff --git a/profiles/roaming/roaming.go b/profiles/roaming/roaming.go
index a28feea..4aa190f 100644
--- a/profiles/roaming/roaming.go
+++ b/profiles/roaming/roaming.go
@@ -72,7 +72,7 @@
func (p *profile) Init(rt veyron2.Runtime, publisher *config.Publisher) error {
log := rt.Logger()
- rt.ConfigureReservedName("__debug", debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
+ rt.ConfigureReservedName(debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
lf := commonFlags.ListenFlags()
ListenSpec = ipc.ListenSpec{
diff --git a/profiles/static/static.go b/profiles/static/static.go
index 18b7625..87b1780 100644
--- a/profiles/static/static.go
+++ b/profiles/static/static.go
@@ -58,7 +58,7 @@
func (p *static) Init(rt veyron2.Runtime, _ *config.Publisher) error {
log := rt.Logger()
- rt.ConfigureReservedName("debug", debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
+ rt.ConfigureReservedName(debug.NewDispatcher(log.LogDir(), sflag.NewAuthorizerOrDie()))
lf := commonFlags.ListenFlags()
ListenSpec = ipc.ListenSpec{
diff --git a/runtimes/google/ipc/benchmarks/server.go b/runtimes/google/ipc/benchmarks/server.go
index aca9f60..0c41a9b 100644
--- a/runtimes/google/ipc/benchmarks/server.go
+++ b/runtimes/google/ipc/benchmarks/server.go
@@ -1,6 +1,8 @@
package benchmarks
import (
+ "io"
+
sflag "veyron.io/veyron/veyron/security/flag"
"veyron.io/veyron/veyron2"
@@ -12,21 +14,24 @@
type impl struct {
}
-func (i *impl) Echo(ctx ipc.ServerContext, payload []byte) ([]byte, error) {
+func (i *impl) Echo(ctx ipc.ServerCall, payload []byte) ([]byte, error) {
return payload, nil
}
-func (i *impl) EchoStream(ctx ipc.ServerContext, stream BenchmarkServiceEchoStreamStream) error {
- rStream := stream.RecvStream()
- sender := stream.SendStream()
- for rStream.Advance() {
- chunk := rStream.Value()
- if err := sender.Send(chunk); err != nil {
+func (i *impl) EchoStream(ctx ipc.ServerCall) error {
+ for {
+ var chunk []byte
+ if err := ctx.Recv(&chunk); err != nil {
+ if err == io.EOF {
+ break
+ }
+ return err
+ }
+ if err := ctx.Send(chunk); err != nil {
return err
}
}
-
- return rStream.Err()
+ return nil
}
// StartServer starts a server that implements the Benchmark service. The
@@ -41,7 +46,7 @@
if err != nil {
vlog.Fatalf("Listen failed: %v", err)
}
- if err := server.Serve("", ipc.LeafDispatcher(NewServerBenchmark(&impl{}), sflag.NewAuthorizerOrDie())); err != nil {
+ if err := server.Serve("", &impl{}, sflag.NewAuthorizerOrDie()); err != nil {
vlog.Fatalf("Serve failed: %v", err)
}
return naming.JoinAddressName(ep.String(), ""), func() {
diff --git a/runtimes/google/ipc/benchmarks/service.vdl.go b/runtimes/google/ipc/benchmarks/service.vdl.go
index 806dd55..646f0b0 100644
--- a/runtimes/google/ipc/benchmarks/service.vdl.go
+++ b/runtimes/google/ipc/benchmarks/service.vdl.go
@@ -294,9 +294,27 @@
// It takes a regular server implementing the BenchmarkService
// interface, and returns a new server stub.
func NewServerBenchmark(server BenchmarkService) interface{} {
- return &ServerStubBenchmark{
+ stub := &ServerStubBenchmark{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubBenchmark implements Benchmark.
@@ -370,6 +388,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubBenchmark struct {
service BenchmarkService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubBenchmark) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -430,6 +449,10 @@
return
}
+func (__gen_s *ServerStubBenchmark) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubBenchmark) Echo(call _gen_ipc.ServerCall, Payload []byte) (reply []byte, err error) {
reply, err = __gen_s.service.Echo(call, Payload)
return
diff --git a/runtimes/google/ipc/cancel_test.go b/runtimes/google/ipc/cancel_test.go
index cc30a2f..0ad572c 100644
--- a/runtimes/google/ipc/cancel_test.go
+++ b/runtimes/google/ipc/cancel_test.go
@@ -73,7 +73,7 @@
stop: s.Stop,
}
- if err := s.Serve(name, ipc.LeafDispatcher(c, fakeAuthorizer(0))); err != nil {
+ if err := s.Serve(name, c, fakeAuthorizer(0)); err != nil {
return nil, err
}
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index 4e12fb9..e828b51 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -233,7 +233,7 @@
// tryCall makes a single attempt at a call.
func (c *client) tryCall(ctx context.T, name, method string, args []interface{}, opts []ipc.CallOpt) (ipc.Call, verror.E) {
- ctx, _ = vtrace.WithNewSpan(ctx, fmt.Sprintf("Client Call: %s.%s", name, method))
+ ctx, _ = vtrace.WithNewSpan(ctx, fmt.Sprintf("<client>\"%s\".%s", name, method))
_, serverPattern, name := splitObjectName(name)
diff --git a/runtimes/google/ipc/debug_test.go b/runtimes/google/ipc/debug_test.go
index e05c185..8286463 100644
--- a/runtimes/google/ipc/debug_test.go
+++ b/runtimes/google/ipc/debug_test.go
@@ -36,12 +36,12 @@
defer sm.Shutdown()
ns := tnaming.NewSimpleNamespace()
- server, err := InternalNewServer(testContext(), sm, ns, options.ReservedNameDispatcher{"__debug", debugDisp}, vc.LocalPrincipal{pserver})
+ server, err := InternalNewServer(testContext(), sm, ns, options.ReservedNameDispatcher{debugDisp}, vc.LocalPrincipal{pserver})
if err != nil {
t.Fatalf("InternalNewServer failed: %v", err)
}
defer server.Stop()
- server.Serve("", ipc.LeafDispatcher(&testObject{}, nil))
+ server.Serve("", &testObject{}, nil)
ep, err := server.Listen(listenSpec)
if err != nil {
t.Fatalf("server.Listen failed: %v", err)
diff --git a/runtimes/google/ipc/flow_test.go b/runtimes/google/ipc/flow_test.go
index f121968..0d608bb 100644
--- a/runtimes/google/ipc/flow_test.go
+++ b/runtimes/google/ipc/flow_test.go
@@ -82,6 +82,10 @@
return nil, errors.New(inv.suffix)
}
+func (inv closureInvoker) VGlob() *ipc.GlobState {
+ return nil
+}
+
// echoInvoker serves a method that takes a string and echoes it:
// func(_ ServerCall, arg string) (string, error)
type echoInvoker struct{ suffix string }
@@ -100,6 +104,10 @@
return []interface{}{result}, nil
}
+func (inv echoInvoker) VGlob() *ipc.GlobState {
+ return nil
+}
+
func TestFlowClientServer(t *testing.T) {
type v []interface{}
type testcase struct {
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index cd83055..2c721d9 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -180,10 +180,10 @@
}
vlog.VI(1).Info("server.Serve")
disp := testServerDisp{ts}
- if err := server.Serve("mountpoint/server", disp); err != nil {
+ if err := server.ServeDispatcher("mountpoint/server", disp); err != nil {
t.Errorf("server.Publish failed: %v", err)
}
- if err := server.Serve("mountpoint/discharger", disp); err != nil {
+ if err := server.AddName("mountpoint/discharger"); err != nil {
t.Errorf("server.Publish for discharger failed: %v", err)
}
return ep, server
@@ -208,7 +208,7 @@
verifyMount(t, ns, n1)
// publish a second name
- if err := server.Serve(n2, nil); err != nil {
+ if err := server.AddName(n2); err != nil {
t.Errorf("server.Serve failed: %v", err)
}
verifyMount(t, ns, n2)
@@ -221,7 +221,7 @@
verifyMountMissing(t, ns, n2)
// Check that we can no longer serve after Stop.
- err := server.Serve("name doesn't matter", nil)
+ err := server.AddName("name doesn't matter")
if err == nil || err.Error() != "ipc: server is stopped" {
t.Errorf("either no error, or a wrong error was returned: %v", err)
}
@@ -267,7 +267,7 @@
return err == nil || strings.Index(err.Error(), pattern) >= 0
}
-func TestMultipleCallsToServe(t *testing.T) {
+func TestMultipleCallsToServeAndName(t *testing.T) {
sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
ns := tnaming.NewSimpleNamespace()
server, err := InternalNewServer(testContext(), sm, ns, vc.LocalPrincipal{sectest.NewPrincipal()})
@@ -280,8 +280,8 @@
}
disp := &testServerDisp{&testServer{}}
- if err := server.Serve("mountpoint/server", disp); err != nil {
- t.Errorf("server.Publish failed: %v", err)
+ if err := server.ServeDispatcher("mountpoint/server", disp); err != nil {
+ t.Errorf("server.ServeDispatcher failed: %v", err)
}
n1 := "mountpoint/server"
@@ -291,17 +291,35 @@
verifyMount(t, ns, n1)
- if err := server.Serve(n2, disp); err != nil {
- t.Errorf("server.Serve failed: %v", err)
+ if server.ServeDispatcher(n2, disp) == nil {
+ t.Errorf("server.ServeDispatcher should have failed")
}
- if err := server.Serve(n3, nil); err != nil {
- t.Errorf("server.Serve failed: %v", err)
+
+ if err := server.Serve(n2, &testServer{}, nil); err == nil {
+ t.Errorf("server.Serve should have failed")
+ }
+
+ if err := server.AddName(n3); err != nil {
+ t.Errorf("server.AddName failed: %v", err)
+ }
+
+ if err := server.AddName(n3); err != nil {
+ t.Errorf("server.AddName failed: %v", err)
}
verifyMount(t, ns, n2)
verifyMount(t, ns, n3)
- if err := server.Serve(n4, &testServerDisp{&testServer{}}); err == nil {
- t.Errorf("server.Serve should have failed")
+ if err := server.RemoveName(n1); err != nil {
+ t.Errorf("server.RemoveName failed: %v", err)
+ }
+ verifyMountMissing(t, ns, n1)
+
+ if err := server.RemoveName("some randome name"); err == nil {
+ t.Errorf("server.RemoveName should have failed")
+ }
+
+ if err := server.ServeDispatcher(n4, &testServerDisp{&testServer{}}); err == nil {
+ t.Errorf("server.ServeDispatcher should have failed")
}
verifyMountMissing(t, ns, n4)
@@ -602,7 +620,7 @@
}
var tester dischargeImpetusTester
- if err := server.Serve("mountpoint", &tester); err != nil {
+ if err := server.ServeDispatcher("mountpoint", &tester); err != nil {
t.Fatal(err)
}
@@ -1048,7 +1066,7 @@
t.Fatalf("server.Listen failed: %v", err)
}
disp := &testServerDisp{&testServer{}}
- if err := server.Serve("mp/server", disp); err != nil {
+ if err := server.ServeDispatcher("mp/server", disp); err != nil {
t.Fatalf("server.Serve failed: %v", err)
}
client, err := InternalNewClient(sm, ns, options.VCSecurityNone)
@@ -1094,8 +1112,6 @@
}{
{"[foo/bar]", "", "foo/bar", ""},
{"[x/y/...]/", "x/y/...", "", "/"},
- {"[foo/...]//", "", "foo/...", "//"},
- {"[foo]//abc@@/foo", "", "foo", "//abc@@/foo"},
{"[foo]a", "", "foo", "a"},
{"[foo]/a", "foo", "", "/a"},
{"[foo]/a/[bar]", "foo", "bar", "/a"},
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 44ae7ab..18d8684 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -9,7 +9,6 @@
"sync"
"time"
- "veyron.io/veyron/veyron2"
"veyron.io/veyron/veyron2/config"
"veyron.io/veyron/veyron2/context"
"veyron.io/veyron/veyron2/ipc"
@@ -47,7 +46,11 @@
stoppedChan chan struct{} // closed when the server has been stopped.
ns naming.Namespace
servesMountTable bool
- reservedOpt options.ReservedNameDispatcher
+ // TODO(cnicolaou): remove this when the publisher tracks published names
+ // and can return an appropriate error for RemoveName on a name that
+ // wasn't 'Added' for this server.
+ names map[string]struct{}
+ reservedOpt options.ReservedNameDispatcher
// TODO(cnicolaou): add roaming stats to ipcStats
stats *ipcStats // stats for this server.
}
@@ -388,13 +391,9 @@
return ep, nil
}
+// TODO(cnicolaou): Take this out or make the ServesMountTable bit work in the endpoint.
func (s *server) publishEP(ep *inaming.Endpoint, servesMountTable bool) string {
var name string
- if !s.servesMountTable {
- // Make sure that client MountTable code doesn't try and
- // ResolveStep past this final address.
- name = "//"
- }
ep.IsMountTable = servesMountTable
return naming.JoinAddressName(ep.String(), name)
}
@@ -533,51 +532,66 @@
}
}
-func (s *server) Serve(name string, obj interface{}) error {
+func (s *server) Serve(name string, obj interface{}, authorizer security.Authorizer) error {
if obj == nil {
- // nil is an allowed value for obj.
- return s.ServeDispatcher(name, ipc.Dispatcher(nil))
+ // The ReflectInvoker inside the LeafDispatcher will panic
+ // if called for a nil value.
+ return fmt.Errorf("A nil object is not allowed")
}
- // TRANSITION: this will be disallowed when the transition is complete.
- if disp, ok := obj.(ipc.Dispatcher); ok {
- return s.ServeDispatcher(name, disp)
- }
- // TRANSITION: We may fail the dispatcher type test, but still be a
- // dispatcher becase our Lookup method returns ipc.Invoker and not a
- // raw object. This code here will detect that case and panic as an aid
- // to catching these cases early.
- typ := reflect.TypeOf(obj)
- if lookup, found := typ.MethodByName("Lookup"); found {
- if lookup.Type.NumIn() == 3 && lookup.Type.NumOut() == 3 {
- inv := lookup.Type.Out(0)
- if inv.Name() == "Invoker" {
- panic(fmt.Sprintf("%q has a Lookup that returns an Invoker", lookup.Name))
- }
- }
- }
- // TRANSITION: this will go away in the transition.
- panic("should never get here")
+ return s.ServeDispatcher(name, ipc.LeafDispatcher(obj, authorizer))
}
func (s *server) ServeDispatcher(name string, disp ipc.Dispatcher) error {
- defer vlog.LogCall()()
s.Lock()
defer s.Unlock()
if s.stopped {
return errServerStopped
}
- if s.disp != nil && disp != nil && s.disp != disp {
- return fmt.Errorf("attempt to change dispatcher")
+ if disp == nil {
+ return fmt.Errorf("A nil dispacther is not allowed")
}
- if disp != nil {
- s.disp = disp
+ if s.disp != nil {
+ return fmt.Errorf("Serve or ServeDispatcher has already been called")
}
+ s.disp = disp
+ s.names = make(map[string]struct{})
if len(name) > 0 {
s.publisher.AddName(name)
+ s.names[name] = struct{}{}
}
return nil
}
+func (s *server) AddName(name string) error {
+ s.Lock()
+ defer s.Unlock()
+ if s.stopped {
+ return errServerStopped
+ }
+ if len(name) == 0 {
+ return fmt.Errorf("empty name")
+ }
+ s.publisher.AddName(name)
+ // TODO(cnicolaou): remove this map when the publisher's RemoveName
+ // method returns an error.
+ s.names[name] = struct{}{}
+ return nil
+}
+
+func (s *server) RemoveName(name string) error {
+ s.Lock()
+ defer s.Unlock()
+ if s.stopped {
+ return errServerStopped
+ }
+ if _, present := s.names[name]; !present {
+ return fmt.Errorf("%q has not been previously used for this server", name)
+ }
+ s.publisher.RemoveName(name)
+ delete(s.names, name)
+ return nil
+}
+
func (s *server) Stop() error {
defer vlog.LogCall()()
s.Lock()
@@ -667,11 +681,10 @@
func newFlowServer(flow stream.Flow, server *server) *flowServer {
server.Lock()
disp := server.disp
- runtime := veyron2.RuntimeFromContext(server.ctx)
server.Unlock()
return &flowServer{
- T: InternalNewContext(runtime),
+ T: server.ctx,
server: server,
disp: disp,
// TODO(toddw): Support different codecs
@@ -792,15 +805,15 @@
if verr != nil {
// We don't know what the ipc call was supposed to be, but we'll create
// a placeholder span so we can capture annotations.
- fs.T, _ = ivtrace.WithNewSpan(fs, "Failed IPC Call")
+ fs.T, _ = ivtrace.WithNewSpan(fs, fmt.Sprintf("\"%s\".UNKNOWN", fs.Name()))
return nil, verr
}
fs.method = req.Method
// TODO(mattr): Currently this allows users to trigger trace collection
// on the server even if they will not be allowed to collect the
- // results later. This might be consider a DOS vector.
- spanName := fmt.Sprintf("Server Call: %s.%s", fs.Name(), fs.Method())
+ // results later. This might be considered a DOS vector.
+ spanName := fmt.Sprintf("\"%s\".%s", fs.Name(), fs.Method())
fs.T, _ = ivtrace.WithContinuedSpan(fs, spanName, req.TraceRequest)
var cancel context.CancelFunc
@@ -890,17 +903,19 @@
// with ipc.DebugKeyword, we use the internal debug dispatcher to look up the
// invoker. Otherwise, and we use the server's dispatcher. The (stripped) name
// and dispatch suffix are also returned.
-// TODO(cnicolaou): change this back returning in ipc.Invoker in the pt2 CL.
func (fs *flowServer) lookup(name, method string) (ipc.Invoker, security.Authorizer, string, verror.E) {
name = strings.TrimLeft(name, "/")
if method == "Glob" && len(name) == 0 {
- return ipc.ReflectInvoker(&globInvoker{fs.reservedOpt.Prefix, fs}), &acceptAllAuthorizer{}, name, nil
+ return ipc.ReflectInvoker(&globInvoker{"__debug", fs}), &acceptAllAuthorizer{}, name, nil
}
disp := fs.disp
- prefix := fs.reservedOpt.Prefix
- if len(prefix) > 0 && (name == prefix || strings.HasPrefix(name, prefix+"/")) {
- name = strings.TrimPrefix(name, prefix)
- name = strings.TrimLeft(name, "/")
+ if strings.HasPrefix(name, naming.ReservedNamePrefix) {
+ parts := strings.SplitN(name, "/", 2)
+ if len(parts) > 1 {
+ name = parts[1]
+ } else {
+ name = ""
+ }
disp = fs.reservedOpt.Dispatcher
}
diff --git a/runtimes/google/ipc/server_test.go b/runtimes/google/ipc/server_test.go
index 8a8020f..11959f0 100644
--- a/runtimes/google/ipc/server_test.go
+++ b/runtimes/google/ipc/server_test.go
@@ -153,7 +153,7 @@
if _, err := server.Listen(spec); err != nil {
t.Fatal(err)
}
- if err := server.Serve("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
+ if err := server.ServeDispatcher("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
t.Fatal(err)
}
verifyMount(t, ns, name)
@@ -200,7 +200,7 @@
return fmt.Errorf("InternalNewServer failed: %v", err)
}
disp := testServerDisp{new(testServer)}
- if err := server.Serve("server", disp); err != nil {
+ if err := server.ServeDispatcher("server", disp); err != nil {
return fmt.Errorf("server.Register failed: %v", err)
}
spec := listenSpec
diff --git a/runtimes/google/lib/publisher/publisher.go b/runtimes/google/lib/publisher/publisher.go
index 63fad95..eece0f7 100644
--- a/runtimes/google/lib/publisher/publisher.go
+++ b/runtimes/google/lib/publisher/publisher.go
@@ -13,6 +13,9 @@
"veyron.io/veyron/veyron2/vlog"
)
+// TODO(cnicolaou): have the done channel return an error so
+// that the publisher calls can return errors also.
+
// Publisher manages the publishing of servers in mounttable.
type Publisher interface {
// AddServer adds a new server to be mounted.
@@ -21,6 +24,8 @@
RemoveServer(server string)
// AddName adds a new name for all servers to be mounted as.
AddName(name string)
+ // RemoveName removes a name.
+ RemoveName(name string)
// Published returns the published names rooted at the mounttable.
Published() []string
// DebugString returns a string representation of the publisher
@@ -58,11 +63,16 @@
done chan struct{} // closed when the cmd is done
}
-type nameCmd struct {
+type addNameCmd struct {
name string // name to add
done chan struct{} // closed when the cmd is done
}
+type removeNameCmd struct {
+ name string // name to remove
+ done chan struct{} // closed when the cmd is done
+}
+
type debugCmd chan string // debug string is sent when the cmd is done
type publishedCmd chan []string // published names are sent when cmd is done
@@ -104,7 +114,14 @@
func (p *publisher) AddName(name string) {
done := make(chan struct{})
- if p.sendCmd(nameCmd{name, done}) {
+ if p.sendCmd(addNameCmd{name, done}) {
+ <-done
+ }
+}
+
+func (p *publisher) RemoveName(name string) {
+ done := make(chan struct{})
+ if p.sendCmd(removeNameCmd{name, done}) {
<-done
}
}
@@ -167,9 +184,12 @@
case removeServerCmd:
state.removeServer(tcmd.server)
close(tcmd.done)
- case nameCmd:
+ case addNameCmd:
state.addName(tcmd.name)
close(tcmd.done)
+ case removeNameCmd:
+ state.removeName(tcmd.name)
+ close(tcmd.done)
case publishedCmd:
tcmd <- state.published()
close(tcmd)
@@ -190,11 +210,11 @@
ctx context.T
ns naming.Namespace
period time.Duration
- deadline time.Time // deadline for the next sync call
- names []string // names that have been added
- servers map[string]bool // servers that have been added, true
+ deadline time.Time // deadline for the next sync call
+ names map[string]bool // names that have been added
+ servers map[string]bool // servers that have been added, true
+ mounts map[mountKey]*mountStatus // map each (name,server) to its status
// if server is a mount table server
- mounts map[mountKey]*mountStatus // map each (name,server) to its status
}
type mountKey struct {
@@ -215,6 +235,7 @@
ns: ns,
period: period,
deadline: time.Now().Add(period),
+ names: make(map[string]bool),
servers: make(map[string]bool),
mounts: make(map[mountKey]*mountStatus),
}
@@ -227,12 +248,10 @@
func (ps *pubState) addName(name string) {
// Each non-dup name that is added causes new mounts to be created for all
// existing servers.
- for _, n := range ps.names {
- if n == name {
- return
- }
+ if ps.names[name] {
+ return
}
- ps.names = append(ps.names, name)
+ ps.names[name] = true
for server, servesMT := range ps.servers {
status := new(mountStatus)
ps.mounts[mountKey{name, server}] = status
@@ -240,12 +259,24 @@
}
}
+func (ps *pubState) removeName(name string) {
+ if !ps.names[name] {
+ return
+ }
+ for server, _ := range ps.servers {
+ if status, exists := ps.mounts[mountKey{name, server}]; exists {
+ ps.unmount(name, server, status)
+ }
+ }
+ delete(ps.names, name)
+}
+
func (ps *pubState) addServer(server string, servesMT bool) {
// Each non-dup server that is added causes new mounts to be created for all
// existing names.
- if _, exists := ps.servers[server]; !exists {
+ if !ps.servers[server] {
ps.servers[server] = servesMT
- for _, name := range ps.names {
+ for name, _ := range ps.names {
status := new(mountStatus)
ps.mounts[mountKey{name, server}] = status
ps.mount(name, server, status, servesMT)
@@ -258,7 +289,7 @@
return
}
delete(ps.servers, server)
- for _, name := range ps.names {
+ for name, _ := range ps.names {
if status, exists := ps.mounts[mountKey{name, server}]; exists {
ps.unmount(name, server, status)
}
@@ -310,7 +341,7 @@
func (ps *pubState) published() []string {
var ret []string
- for _, name := range ps.names {
+ for name, _ := range ps.names {
e, err := ps.ns.ResolveToMountTableX(ps.ctx, name)
if err != nil {
vlog.Errorf("ipc pub: couldn't resolve %v to mount table: %v", name, err)
@@ -327,6 +358,7 @@
return ret
}
+// TODO(toddw): sort the names/servers so that the output order is stable.
func (ps *pubState) debugString() string {
l := make([]string, 2+len(ps.mounts))
l = append(l, fmt.Sprintf("Publisher period:%v deadline:%v", ps.period, ps.deadline))
diff --git a/runtimes/google/lib/publisher/publisher_test.go b/runtimes/google/lib/publisher/publisher_test.go
new file mode 100644
index 0000000..720f16f
--- /dev/null
+++ b/runtimes/google/lib/publisher/publisher_test.go
@@ -0,0 +1,58 @@
+package publisher_test
+
+import (
+ "reflect"
+ "sort"
+ "testing"
+ "time"
+
+ "veyron.io/veyron/veyron2/context"
+ "veyron.io/veyron/veyron2/naming"
+
+ iipc "veyron.io/veyron/veyron/runtimes/google/ipc"
+ "veyron.io/veyron/veyron/runtimes/google/lib/publisher"
+ tnaming "veyron.io/veyron/veyron/runtimes/google/testing/mocks/naming"
+ "veyron.io/veyron/veyron/runtimes/google/testing/mocks/runtime"
+ "veyron.io/veyron/veyron/runtimes/google/vtrace"
+)
+
+func testContext() context.T {
+ ctx := iipc.InternalNewContext(&runtime.PanicRuntime{})
+ ctx, _ = vtrace.WithNewSpan(ctx, "")
+ ctx, _ = ctx.WithDeadline(time.Now().Add(20 * time.Second))
+ return ctx
+}
+
+func resolve(t *testing.T, ns naming.Namespace, name string) []string {
+ servers, err := ns.Resolve(testContext(), name)
+ if err != nil {
+ t.Fatalf("failed to resolve %q", name)
+ }
+ return servers
+}
+
+func TestAddAndRemove(t *testing.T) {
+ ns := tnaming.NewSimpleNamespace()
+ pub := publisher.New(testContext(), ns, time.Second)
+ pub.AddName("foo")
+ pub.AddServer("foo-addr", false)
+ if got, want := resolve(t, ns, "foo"), []string{"foo-addr"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("got %q, want %q", got, want)
+ }
+ pub.AddServer("bar-addr", false)
+ got, want := resolve(t, ns, "foo"), []string{"bar-addr", "foo-addr"}
+ sort.Strings(got)
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("got %q, want %q", got, want)
+ }
+ pub.AddName("baz")
+ got = resolve(t, ns, "baz")
+ sort.Strings(got)
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("got %q, want %q", got, want)
+ }
+ pub.RemoveName("foo")
+ if _, err := ns.Resolve(testContext(), "foo"); err == nil {
+ t.Errorf("expected an error")
+ }
+}
diff --git a/runtimes/google/naming/namespace/all_test.go b/runtimes/google/naming/namespace/all_test.go
index b803577..da85431 100644
--- a/runtimes/google/naming/namespace/all_test.go
+++ b/runtimes/google/naming/namespace/all_test.go
@@ -193,13 +193,10 @@
if err != nil {
boom(t, "Failed to Listen: %s", err)
}
- if err := s.Serve(mountPoint, disp); err != nil {
+ if err := s.ServeDispatcher(mountPoint, disp); err != nil {
boom(t, "Failed to serve mount table at %s: %s", mountPoint, err)
}
name := naming.JoinAddressName(ep.String(), "")
- if !mt {
- name = name + "//"
- }
return &serverEntry{mountPoint: mountPoint, server: s, endpoint: ep, name: name}
}
@@ -291,21 +288,17 @@
// as the address portion of the terminal name for those mounttables.
testResolveToMountTable(t, r, ns, "", root.name)
for _, m := range []string{mt2MP, mt3MP, mt5MP} {
- rootMT := naming.MakeTerminal(naming.Join(root.name, m))
+ rootMT := naming.Join(root.name, m)
// All of these mount tables are hosted by the root mount table
testResolveToMountTable(t, r, ns, m, rootMT)
- testResolveToMountTable(t, r, ns, "//"+m, rootMT)
// The server registered for each mount point is a mount table
testResolve(t, r, ns, m, mts[m].name)
// ResolveToMountTable will walk through to the sub MountTables
mtbar := naming.Join(m, "bar")
- subMT := naming.MakeTerminal(naming.Join(mts[m].name, "bar"))
+ subMT := naming.Join(mts[m].name, "bar")
testResolveToMountTable(t, r, ns, mtbar, subMT)
-
- // ResolveToMountTable will not walk through if the name is terminal
- testResolveToMountTable(t, r, ns, "//"+mtbar, naming.Join(rootMT, "bar"))
}
for _, j := range []string{j1MP, j2MP, j3MP} {
@@ -343,7 +336,7 @@
boom(t, "Failed to Mount %s: %s", mt2a, err)
}
- mt2mt := naming.MakeTerminal(naming.Join(mts[mt2MP].name, "a"))
+ mt2mt := naming.Join(mts[mt2MP].name, "a")
// The mt2/a is served by the mt2 mount table
testResolveToMountTable(t, r, ns, mt2a, mt2mt)
// The server for mt2a is mt3server from the second mount above.
@@ -365,9 +358,9 @@
// We now have 3 mount tables prepared to serve mt2/a
testResolveToMountTable(t, r, ns, "mt2/a",
- mts[mt2MP].name+"//a",
- mts[mt4MP].name+"//a",
- mts[mt5MP].name+"//a")
+ naming.JoinAddressName(mts[mt2MP].name, "a"),
+ naming.JoinAddressName(mts[mt4MP].name, "a"),
+ naming.JoinAddressName(mts[mt5MP].name, "a"))
testResolve(t, r, ns, "mt2", mts[mt2MP].name, mts[mt4MP].name, mts[mt5MP].name)
}
@@ -388,10 +381,11 @@
}
testResolveToMountTable(t, r, ns, "mt4/foo",
- mts[mt4MP].name+"//foo")
+ naming.JoinAddressName(mts[mt4MP].name, "foo"))
testResolveToMountTable(t, r, ns, "mt4/foo/bar",
- mts["mt4/foo"].name+"//bar")
- testResolveToMountTable(t, r, ns, "mt4/foo/baz", mts["mt4/foo"].name+"//baz")
+ naming.JoinAddressName(mts["mt4/foo"].name, "bar"))
+ testResolveToMountTable(t, r, ns, "mt4/foo/baz",
+ naming.JoinAddressName(mts["mt4/foo"].name, "baz"))
}
// TestServers tests invoking RPCs on simple servers
@@ -413,8 +407,8 @@
jokes[gj] = runServer(t, r, disp, globalName)
testResolve(t, r, ns, "mt4/"+j, jokes[gj].name)
knockKnock(t, r, "mt4/"+j)
- testResolveToMountTable(t, r, ns, "mt4/"+j, naming.MakeTerminal(globalName))
- testResolveToMountTable(t, r, ns, "mt4/"+j+"/garbage", naming.MakeTerminal(globalName+"/garbage"))
+ testResolveToMountTable(t, r, ns, "mt4/"+j, globalName)
+ testResolveToMountTable(t, r, ns, "mt4/"+j+"/garbage", globalName+"/garbage")
}
}
diff --git a/runtimes/google/naming/namespace/cache.go b/runtimes/google/naming/namespace/cache.go
index be7b469..8d5293f 100644
--- a/runtimes/google/naming/namespace/cache.go
+++ b/runtimes/google/naming/namespace/cache.go
@@ -45,15 +45,6 @@
return false
}
-// normalize removes any single trailing slash. Added for idiots who seem to
-// like adding trailing slashes.
-func normalize(name string) string {
- if strings.HasSuffix(name, "//") {
- return name
- }
- return strings.TrimSuffix(name, "/")
-}
-
// randomDrop randomly removes one cache entry. Assumes we've already locked the cache.
func (c *ttlCache) randomDrop() {
n := rand.Intn(len(c.entries))
@@ -90,6 +81,7 @@
// Remove suffix. We only care about the name that gets us
// to the mounttable from the last mounttable.
prefix = normalize(prefix)
+ entry.Name = normalize(entry.Name)
prefix = naming.TrimSuffix(prefix, entry.Name)
// Copy the entry.
var ce naming.MountEntry
@@ -97,8 +89,6 @@
ce.Servers = append(ce.Servers, s)
}
ce.SetServesMountTable(entry.ServesMountTable())
- // All keys must be terminal.
- prefix = naming.MakeTerminal(prefix)
c.Lock()
// Enforce an upper limit on the cache size.
if len(c.entries) >= maxCacheEntries {
diff --git a/runtimes/google/naming/namespace/cache_test.go b/runtimes/google/naming/namespace/cache_test.go
index 0f4cffd..e12cd69 100644
--- a/runtimes/google/naming/namespace/cache_test.go
+++ b/runtimes/google/naming/namespace/cache_test.go
@@ -46,8 +46,8 @@
{"/h2//c/d", "d", "/h3", true},
{"/h3//d", "", "/h4:1234", true},
{"/notintcache", "", "", false},
- {"/h1//a/b/f//g", "f//g", "/h2", true},
- {"/h3//d//e", "//e", "/h4:1234", true},
+ {"/h1//a/b/f//g", "f/g", "/h2", true},
+ {"/h3//d//e", "e", "/h4:1234", true},
}
for _, p := range tests {
e, err := c.lookup(p.name)
diff --git a/runtimes/google/naming/namespace/namespace.go b/runtimes/google/naming/namespace/namespace.go
index 1b966d7..7458858 100644
--- a/runtimes/google/naming/namespace/namespace.go
+++ b/runtimes/google/naming/namespace/namespace.go
@@ -1,6 +1,7 @@
package namespace
import (
+ "strings"
"sync"
"time"
@@ -96,6 +97,7 @@
// rootName 'roots' a name: if name is not a rooted name, it prepends the root
// mounttable's OA.
func (ns *namespace) rootName(name string) []string {
+ name = normalize(name)
if address, _ := naming.SplitAddressName(name); len(address) == 0 {
var ret []string
ns.RLock()
@@ -110,6 +112,7 @@
// rootMountEntry 'roots' a name creating a mount entry for the name.
func (ns *namespace) rootMountEntry(name string) (*naming.MountEntry, bool) {
+ name = normalize(name)
e := new(naming.MountEntry)
expiration := time.Now().Add(time.Hour) // plenty of time for a call
address, suffix := naming.SplitAddressName(name)
@@ -178,3 +181,21 @@
}
return nil
}
+
+// normalize removes any single trailing slash and compresses
+// multiple consecutive slashes to one.
+// TODO(p): Transitionally it also removes a leading double
+// slash that used to mean something but doesn't any more.
+// I should remove that in a week or so when we've killed off
+// all code inserting this double slash.
+func normalize(name string) string {
+ // Eradicate leading double slash (for now). Eventually we
+ // should get ris of this.
+ name = strings.TrimPrefix(name, "//")
+ // Eradicate duplicate slashes and trailing slashes. We
+ // could use path.Clean but it has other side effects.
+ for strings.Contains(name, "//") {
+ name = strings.Replace(name, "//", "/", -1)
+ }
+ return strings.TrimSuffix(name, "/")
+}
diff --git a/runtimes/google/naming/namespace/resolve.go b/runtimes/google/naming/namespace/resolve.go
index 5943b6a..1d6e572 100644
--- a/runtimes/google/naming/namespace/resolve.go
+++ b/runtimes/google/naming/namespace/resolve.go
@@ -58,12 +58,7 @@
}
func terminal(e *naming.MountEntry) bool {
- for _, s := range e.Servers {
- if !naming.Terminal(naming.JoinAddressName(s.Server, e.Name)) {
- return false
- }
- }
- return true
+ return len(e.Name) == 0
}
// ResolveX implements veyron2/naming.Namespace.
@@ -130,7 +125,7 @@
}
last := e
for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
- vlog.VI(2).Infof("ResolveToMountTable(%s) loop %v", name, e)
+ vlog.VI(2).Infof("ResolveToMountTableX(%s) loop %v", name, e)
var err error
curr := e
// If the next name to resolve doesn't point to a mount table, we're done.
@@ -245,7 +240,6 @@
// Walk the cache as we would in a resolution. Unlike a resolution, we have to follow
// all branches since we want to flush all entries at which we might end up whereas in a resolution,
// we stop with the first branch that works.
- n := naming.MakeTerminal(n)
if e, err := ns.resolutionCache.lookup(n); err == nil {
// Recurse.
for _, s := range e.Servers {
diff --git a/runtimes/google/rt/ipc.go b/runtimes/google/rt/ipc.go
index 4923176..5c115f8 100644
--- a/runtimes/google/rt/ipc.go
+++ b/runtimes/google/rt/ipc.go
@@ -94,7 +94,7 @@
// Add the option that provides the principal to the server.
otherOpts = append(otherOpts, vc.LocalPrincipal{rt.principal})
if rt.reservedDisp != nil {
- ropts := options.ReservedNameDispatcher{rt.reservedPrefix, rt.reservedDisp}
+ ropts := options.ReservedNameDispatcher{rt.reservedDisp}
otherOpts = append(otherOpts, ropts)
otherOpts = append(otherOpts, rt.reservedOpts...)
}
diff --git a/runtimes/google/rt/ipc_test.go b/runtimes/google/rt/ipc_test.go
index 4c6cc6c..a29098b 100644
--- a/runtimes/google/rt/ipc_test.go
+++ b/runtimes/google/rt/ipc_test.go
@@ -131,7 +131,7 @@
} else {
serverObjectName = naming.JoinAddressName(endpoint.String(), "")
}
- if err := server.Serve("", ipc.LeafDispatcher(testService{}, vsecurity.NewACLAuthorizer(vsecurity.OpenACL()))); err != nil {
+ if err := server.Serve("", testService{}, vsecurity.NewACLAuthorizer(vsecurity.OpenACL())); err != nil {
t.Fatal(err)
}
// Let it rip!
diff --git a/runtimes/google/rt/mgmt.go b/runtimes/google/rt/mgmt.go
index 772fdfa..a6cac2a 100644
--- a/runtimes/google/rt/mgmt.go
+++ b/runtimes/google/rt/mgmt.go
@@ -69,7 +69,7 @@
if err != nil {
return err
}
- if err := m.server.Serve("", ipc.LeafDispatcher(appcycle.NewServerAppCycle(m), nil)); err != nil {
+ if err := m.server.Serve("", appcycle.NewServerAppCycle(m), nil); err != nil {
return err
}
return m.callbackToParent(parentName, naming.JoinAddressName(ep.String(), ""))
diff --git a/runtimes/google/rt/mgmt_test.go b/runtimes/google/rt/mgmt_test.go
index 866585e..002cc2e 100644
--- a/runtimes/google/rt/mgmt_test.go
+++ b/runtimes/google/rt/mgmt_test.go
@@ -273,7 +273,7 @@
if ep, err = server.Listen(profiles.LocalListenSpec); err != nil {
t.Fatalf("Got error: %v", err)
}
- if err := server.Serve("", ipc.LeafDispatcher(node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie())); err != nil {
+ if err := server.Serve("", node.NewServerConfig(&configServer{ch}), vflag.NewAuthorizerOrDie()); err != nil {
t.Fatalf("Got error: %v", err)
}
return server, naming.JoinAddressName(ep.String(), ""), ch
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index b8ff3d0..8e199b5 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -5,7 +5,6 @@
"fmt"
"os"
"path/filepath"
- "strings"
"sync"
"veyron.io/veyron/veyron2"
@@ -31,20 +30,19 @@
type vrt struct {
mu sync.Mutex
- profile veyron2.Profile
- publisher *config.Publisher
- sm []stream.Manager // GUARDED_BY(mu)
- ns naming.Namespace
- signals chan os.Signal
- principal security.Principal
- client ipc.Client
- mgmt *mgmtImpl
- flags flags.RuntimeFlags
- reservedDisp ipc.Dispatcher
- reservedPrefix string
- reservedOpts []ipc.ServerOpt
- nServers int // GUARDED_BY(mu)
- cleaningUp bool // GUARDED_BY(mu)
+ profile veyron2.Profile
+ publisher *config.Publisher
+ sm []stream.Manager // GUARDED_BY(mu)
+ ns naming.Namespace
+ signals chan os.Signal
+ principal security.Principal
+ client ipc.Client
+ mgmt *mgmtImpl
+ flags flags.RuntimeFlags
+ reservedDisp ipc.Dispatcher
+ reservedOpts []ipc.ServerOpt
+ nServers int // GUARDED_BY(mu)
+ cleaningUp bool // GUARDED_BY(mu)
lang i18n.LangID // Language, from environment variables.
program string // Program name, from os.Args[0].
@@ -142,12 +140,10 @@
return rt.profile
}
-func (rt *vrt) ConfigureReservedName(prefix string, server ipc.Dispatcher, opts ...ipc.ServerOpt) {
+func (rt *vrt) ConfigureReservedName(server ipc.Dispatcher, opts ...ipc.ServerOpt) {
rt.mu.Lock()
defer rt.mu.Unlock()
rt.reservedDisp = server
- prefix = strings.TrimLeft(prefix, "_")
- rt.reservedPrefix = naming.ReservedNamePrefix + prefix
rt.reservedOpts = make([]ipc.ServerOpt, 0, len(opts))
copy(rt.reservedOpts, opts)
}
diff --git a/runtimes/google/testing/mocks/runtime/panic_runtime.go b/runtimes/google/testing/mocks/runtime/panic_runtime.go
index cccc4d7..f5c7c2c 100644
--- a/runtimes/google/testing/mocks/runtime/panic_runtime.go
+++ b/runtimes/google/testing/mocks/runtime/panic_runtime.go
@@ -45,7 +45,7 @@
func (*PanicRuntime) AdvanceGoal(delta int) { panic(badRuntime) }
func (*PanicRuntime) AdvanceProgress(delta int) { panic(badRuntime) }
func (*PanicRuntime) TrackTask(chan<- veyron2.Task) { panic(badRuntime) }
-func (*PanicRuntime) ConfigureReservedName(string, ipc.Dispatcher, ...ipc.ServerOpt) {
+func (*PanicRuntime) ConfigureReservedName(ipc.Dispatcher, ...ipc.ServerOpt) {
panic(badRuntime)
}
func (*PanicRuntime) Cleanup() { panic(badRuntime) }
diff --git a/runtimes/google/vtrace/vtrace_test.go b/runtimes/google/vtrace/vtrace_test.go
index 66c8bd7..f8af7f9 100644
--- a/runtimes/google/vtrace/vtrace_test.go
+++ b/runtimes/google/vtrace/vtrace_test.go
@@ -114,7 +114,7 @@
forceCollect: forceCollect,
}
- if err := s.Serve(name, ipc.LeafDispatcher(c, fakeAuthorizer(0))); err != nil {
+ if err := s.Serve(name, c, fakeAuthorizer(0)); err != nil {
return nil, err
}
@@ -227,10 +227,10 @@
expectedSpans := []string{
": c0-begin, c0-end",
- "Client Call: c1.Run",
- "Server Call: .Run: c1-begin, c1-end",
- "Client Call: c2.Run",
- "Server Call: .Run: c2-begin, c2-end",
+ "<client>\"c1\".Run",
+ "\"\".Run: c1-begin, c1-end",
+ "<client>\"c2\".Run",
+ "\"\".Run: c2-begin, c2-end",
}
expectSequence(t, span.Trace().Record(), expectedSpans)
}
@@ -247,10 +247,10 @@
expectedSpans := []string{
": c0-end",
- "Client Call: c1.Run",
- "Server Call: .Run: c1-end",
- "Client Call: c2.Run",
- "Server Call: .Run: c2-begin, c2-end",
+ "<client>\"c1\".Run",
+ "\"\".Run: c1-end",
+ "<client>\"c2\".Run",
+ "\"\".Run: c2-begin, c2-end",
}
expectSequence(t, span.Trace().Record(), expectedSpans)
}
diff --git a/security/acl/acl.go b/security/acl/acl.go
new file mode 100644
index 0000000..3971530
--- /dev/null
+++ b/security/acl/acl.go
@@ -0,0 +1,44 @@
+package acl
+
+import (
+ "encoding/json"
+ "io"
+
+ "veyron.io/veyron/veyron2/security"
+)
+
+// Includes returns true iff the ACL grants access to a principal
+// that presents blessings.
+func (acl ACL) Includes(blessings ...string) bool {
+ blessings = pruneBlacklisted(acl.NotIn, blessings)
+ for _, pattern := range acl.In {
+ if pattern.MatchedBy(blessings...) {
+ return true
+ }
+ }
+ return false
+}
+
+// WriteTo writes the JSON-encoded representation of a TaggedACLMap to w.
+func (m TaggedACLMap) WriteTo(w io.Writer) error {
+ return json.NewEncoder(w).Encode(m)
+}
+
+// ReadTaggedACLMap reads the JSON-encoded representation of a TaggedACLMap from r.
+func ReadTaggedACLMap(r io.Reader) (m TaggedACLMap, err error) {
+ err = json.NewDecoder(r).Decode(&m)
+ return
+}
+
+func pruneBlacklisted(blacklist, blessings []string) []string {
+ if len(blacklist) == 0 {
+ return blessings
+ }
+ var filtered []string
+ for _, b := range blessings {
+ if !security.BlessingPattern(b).MatchedBy(blacklist...) {
+ filtered = append(filtered, b)
+ }
+ }
+ return filtered
+}
diff --git a/security/acl/acl.vdl b/security/acl/acl.vdl
new file mode 100644
index 0000000..51bc01c
--- /dev/null
+++ b/security/acl/acl.vdl
@@ -0,0 +1,38 @@
+// Package acl defines types and methods to represent Access Control Lists and enforce authorization policies based on them.
+package acl
+
+import "veyron.io/veyron/veyron2/security"
+
+// ACL represents an Access Control List - a set of blessings that should be
+// granted access.
+type ACL struct {
+ // In denotes the set of blessings (represented as BlessingPatterns) that
+ // should be granted access, unless blacklisted by an entry in NotIn.
+ //
+ // For example:
+ // In: {"alice/family/..."}
+ // grants access to a principal that presents at least one of "alice",
+ // "alice/family", "alice/family/friend" etc. as a blessing.
+ In []security.BlessingPattern
+
+ // NotIn denotes the set of blessings (and their delegates) that
+ // have been explicitly blacklisted from the In set.
+ //
+ // For example:
+ // In: {"alice/friend/..."}, NotIn: {"alice/friend/bob"}
+ // grants access to principals that present "alice", "alice/friend",
+ // "alice/friend/carol" etc. but NOT to a principal that presents
+ // "alice/friend/bob" or "alice/friend/bob/spouse" etc.
+ NotIn []string
+
+ // TODO(ashankar,ataly): At some point, introduce group identifiers here?
+}
+
+// TaggedACLMap maps string tags to access control lists specifying the
+// blessings required to invoke methods with that tag.
+//
+// These tags are meant to add a layer of interposition between set of users
+// (blessings, specifically) and the set of methods, much like "Roles" do in
+// Role Based Access Control (RBAC).
+// (http://en.wikipedia.org/wiki/Role-based_access_control)
+type TaggedACLMap map[string]ACL
diff --git a/security/acl/acl.vdl.go b/security/acl/acl.vdl.go
new file mode 100644
index 0000000..4a658de
--- /dev/null
+++ b/security/acl/acl.vdl.go
@@ -0,0 +1,40 @@
+// This file was auto-generated by the veyron vdl tool.
+// Source: acl.vdl
+
+// Package acl defines types and methods to represent Access Control Lists and enforce authorization policies based on them.
+package acl
+
+import (
+ "veyron.io/veyron/veyron2/security"
+)
+
+// ACL represents an Access Control List - a set of blessings that should be
+// granted access.
+type ACL struct {
+ // In denotes the set of blessings (represented as BlessingPatterns) that
+ // should be granted access, unless blacklisted by an entry in NotIn.
+ //
+ // For example:
+ // In: {"alice/family/..."}
+ // grants access to a principal that presents at least one of "alice",
+ // "alice/family", "alice/family/friend" etc. as a blessing.
+ In []security.BlessingPattern
+ // NotIn denotes the set of blessings (and their delegates) that
+ // have been explicitly blacklisted from the In set.
+ //
+ // For example:
+ // In: {"alice/friend/..."}, NotIn: {"alice/friend/bob"}
+ // grants access to principals that present "alice", "alice/friend",
+ // "alice/friend/carol" etc. but NOT to a principal that presents
+ // "alice/friend/bob" or "alice/friend/bob/spouse" etc.
+ NotIn []string
+}
+
+// TaggedACLMap maps string tags to access control lists specifying the
+// blessings required to invoke methods with that tag.
+//
+// These tags are meant to add a layer of interposition between set of users
+// (blessings, specifically) and the set of methods, much like "Roles" do in
+// Role Based Access Control (RBAC).
+// (http://en.wikipedia.org/wiki/Role-based_access_control)
+type TaggedACLMap map[string]ACL
diff --git a/security/acl/acl_test.go b/security/acl/acl_test.go
new file mode 100644
index 0000000..4187b18
--- /dev/null
+++ b/security/acl/acl_test.go
@@ -0,0 +1,86 @@
+package acl
+
+import (
+ "bytes"
+ "reflect"
+ "testing"
+
+ "veyron.io/veyron/veyron2/security"
+)
+
+func TestInclude(t *testing.T) {
+ acl := ACL{
+ In: []security.BlessingPattern{"alice", "alice/friend/...", "bob/family/..."},
+ NotIn: []string{"alice/friend/carol", "bob/family/mallory"},
+ }
+ type V []string // shorthand
+ tests := []struct {
+ Blessings []string
+ Want bool
+ }{
+ {nil, false}, // No blessings presented, cannot access
+ {V{}, false},
+ {V{"alice"}, true},
+ {V{"bob"}, true},
+ {V{"carol"}, false},
+ {V{"alice/colleague"}, false},
+ {V{"alice", "carol/friend"}, true}, // Presenting one blessing that grants access is sufficient
+ {V{"alice/friend/bob"}, true},
+ {V{"alice/friend/carol"}, false}, // alice/friend/carol is blacklisted
+ {V{"alice/friend/carol/family"}, false}, // alice/friend/carol is blacklisted, thus her delegates must be too.
+ {V{"alice/friend/bob", "alice/friend/carol"}, true},
+ {V{"bob/family/eve", "bob/family/mallory"}, true},
+ {V{"bob/family/mallory", "alice/friend/carol"}, false},
+ }
+ for _, test := range tests {
+ if got, want := acl.Includes(test.Blessings...), test.Want; got != want {
+ t.Errorf("Includes(%v): Got %v, want %v", test.Blessings, got, want)
+ }
+ }
+}
+
+func TestOpenACL(t *testing.T) {
+ acl := ACL{In: []security.BlessingPattern{security.AllPrincipals}}
+ if !acl.Includes() {
+ t.Errorf("OpenACL should allow principals that present no blessings")
+ }
+ if !acl.Includes("frank") {
+ t.Errorf("OpenACL should allow principals that present any blessings")
+ }
+}
+
+func TestTaggedACLMapSerialization(t *testing.T) {
+ obj := TaggedACLMap{
+ "R": ACL{
+ In: []security.BlessingPattern{"foo/...", "bar/..."},
+ NotIn: []string{"bar/baz"},
+ },
+ "W": ACL{
+ In: []security.BlessingPattern{"foo/...", "bar"},
+ NotIn: []string{"foo/bar", "foo/baz/boz"},
+ },
+ }
+ txt := `
+{
+ "R": {
+ "In":["foo/...","bar/..."],
+ "NotIn":["bar/baz"]
+ },
+ "W": {
+ "In":["foo/...","bar"],
+ "NotIn":["foo/bar","foo/baz/boz"]
+ }
+}
+`
+ if got, err := ReadTaggedACLMap(bytes.NewBufferString(txt)); err != nil || !reflect.DeepEqual(got, obj) {
+ t.Errorf("Got error %v, TaggedACLMap: %v, want %v", err, got, obj)
+ }
+ // And round-trip (don't compare with 'txt' because indentation/spacing might differ).
+ var buf bytes.Buffer
+ if err := obj.WriteTo(&buf); err != nil {
+ t.Fatal(err)
+ }
+ if got, err := ReadTaggedACLMap(&buf); err != nil || !reflect.DeepEqual(got, obj) {
+ t.Errorf("Got error %v, TaggedACLMap: %v, want %v", err, got, obj)
+ }
+}
diff --git a/security/acl/authorizer.go b/security/acl/authorizer.go
new file mode 100644
index 0000000..f4d60c9
--- /dev/null
+++ b/security/acl/authorizer.go
@@ -0,0 +1,150 @@
+package acl
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+
+ "veyron.io/veyron/veyron2/security"
+)
+
+// TaggedACLAuthorizer implements an authorization policy where access is
+// granted if the remote end presents blessings included in the Access Control
+// Lists (ACLs) associated with the set of relevant tags.
+//
+// The set of relevant tags is the subset of tags associated with the
+// method (security.Context.MethodTags) that have the same type as tagType.
+// Currently, tagType.Kind must be reflect.String, i.e., only tags that are
+// named string types are supported.
+//
+// If multiple tags of tagType are associated with the method, then access is
+// granted if the peer presents blessings that match the ACLs of each one of
+// those tags. If no tags of tagType are associated with the method, then
+// access is denied.
+//
+// If the TaggedACLMap provided is nil, then a nil authorizer is returned.
+//
+// Sample usage:
+//
+// (1) Attach tags to methods in the VDL (eg. myservice.vdl)
+// package myservice
+//
+// type MyTag string
+// const (
+// ReadAccess = MyTag("R")
+// WriteAccess = MyTag("W")
+// )
+//
+// type MyService interface {
+// Get() ([]string, error) {ReadAccess}
+// GetIndex(int) (string, error) {ReadAccess}
+//
+// Set([]string) error {WriteAccess}
+// SetIndex(int, string) error {WriteAccess}
+//
+// GetAndSet([]string) ([]string, error) {ReadAccess, WriteAccess}
+// }
+//
+// (2) Setup the ipc.Dispatcher to use the TaggedACLAuthorizer
+// import (
+// "reflect"
+// "veyron.io/veyron/veyron/security/acl"
+//
+// "veyron.io/veyron/veyron2/ipc"
+// "veyron.io/veyron/veyron2/security"
+// )
+//
+// type dispatcher struct{}
+// func (d dispatcher) Lookup(suffix, method) (ipc.Invoker, security.Authorizer, error) {
+// acl := acl.TaggedACLMap{
+// "R": acl.ACL{In: []security.BlessingPattern{"alice/friends/...", "alice/family/..."} },
+// "W": acl.ACL{In: []security.BlessingPattern{"alice/family/...", "alice/colleagues/..." } },
+// }
+// typ := reflect.TypeOf(ReadAccess) // equivalently, reflect.TypeOf(WriteAccess)
+// return newInvoker(), acl.TaggedACLAuthorizer(acl, typ), nil
+// }
+//
+// With the above dispatcher, the server will grant access to a peer with the blessing
+// "alice/friend/bob" access only to the "Get" and "GetIndex" methods. A peer presenting
+// the blessing "alice/colleague/carol" will get access only to the "Set" and "SetIndex"
+// methods. A peer presenting "alice/family/mom" will get access to all methods, even
+// GetAndSet - which requires that the blessing appear in the ACLs for both the
+// ReadAccess and WriteAccess tags.
+func TaggedACLAuthorizer(acls TaggedACLMap, tagType reflect.Type) (security.Authorizer, error) {
+ if tagType.Kind() != reflect.String {
+ return nil, fmt.Errorf("tag type(%v) must be backed by a string not %v", tagType, tagType.Kind())
+ }
+ return &authorizer{acls, tagType}, nil
+}
+
+// TaggedACLAuthorizerFromFile applies the same authorization policy as
+// TaggedACLAuthorizer, with the TaggedACLMap to be used sourced from a file named
+// filename.
+//
+// Changes to the file are monitored and affect subsequent calls to Authorize.
+// Currently, this is achieved by re-reading the file on every call to
+// Authorize.
+// TODO(ashankar,ataly): Use inotify or a similar mechanism to watch for
+// changes.
+func TaggedACLAuthorizerFromFile(filename string, tagType reflect.Type) (security.Authorizer, error) {
+ if tagType.Kind() != reflect.String {
+ return nil, fmt.Errorf("tag type(%v) must be backed by a string not %v", tagType, tagType.Kind())
+ }
+ return &fileAuthorizer{filename, tagType}, nil
+}
+
+type authorizer struct {
+ acls TaggedACLMap
+ tagType reflect.Type
+}
+
+func (a *authorizer) Authorize(ctx security.Context) error {
+ // "Self-RPCs" are always authorized.
+ if l, r := ctx.LocalBlessings(), ctx.RemoteBlessings(); l != nil && r != nil && reflect.DeepEqual(l.PublicKey(), r.PublicKey()) {
+ return nil
+ }
+ var blessings []string
+ if ctx.RemoteBlessings() != nil {
+ blessings = ctx.RemoteBlessings().ForContext(ctx)
+ }
+ grant := false
+ for _, tag := range ctx.MethodTags() {
+ if v := reflect.ValueOf(tag); v.Type() == a.tagType {
+ if acl, exists := a.acls[v.String()]; !exists || !acl.Includes(blessings...) {
+ return errACLMatch(blessings)
+ }
+ grant = true
+ }
+ }
+ if grant {
+ return nil
+ }
+ return errACLMatch(blessings)
+}
+
+type fileAuthorizer struct {
+ filename string
+ tagType reflect.Type
+}
+
+func (a *fileAuthorizer) Authorize(ctx security.Context) error {
+ acl, err := loadTaggedACLMapFromFile(a.filename)
+ if err != nil {
+ // TODO(ashankar): Information leak?
+ return fmt.Errorf("failed to read ACL from file: %v", err)
+ }
+ return (&authorizer{acl, a.tagType}).Authorize(ctx)
+}
+
+func loadTaggedACLMapFromFile(filename string) (TaggedACLMap, error) {
+ file, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+ return ReadTaggedACLMap(file)
+}
+
+func errACLMatch(blessings []string) error {
+ return fmt.Errorf("%v does not match ACL", blessings)
+}
diff --git a/security/acl/authorizer_test.go b/security/acl/authorizer_test.go
new file mode 100644
index 0000000..59137b5
--- /dev/null
+++ b/security/acl/authorizer_test.go
@@ -0,0 +1,214 @@
+package acl
+
+import (
+ "io/ioutil"
+ "reflect"
+ "testing"
+
+ vsecurity "veyron.io/veyron/veyron/security"
+ "veyron.io/veyron/veyron/security/acl/test"
+ "veyron.io/veyron/veyron2/security"
+)
+
+// TestTaggedACLAuthorizer is both a test and a demonstration of the use of the
+// TaggedACLAuthorizer and interaction with interface specification in VDL.
+func TestTaggedACLAuthorizer(t *testing.T) {
+ type P []security.BlessingPattern
+ type S []string
+ // TaggedACLMap to test against.
+ acl := TaggedACLMap{
+ "R": {
+ In: P{"..."},
+ },
+ "W": {
+ In: P{"ali/family/...", "bob/...", "che"},
+ NotIn: S{"bob/acquaintances"},
+ },
+ "X": {
+ In: P{"ali/family/boss", "superman"},
+ },
+ }
+ type testcase struct {
+ Method string
+ Client security.Blessings
+ }
+ var (
+ authorizer, _ = TaggedACLAuthorizer(acl, reflect.TypeOf(test.Read))
+ // Two principals: The "server" and the "client"
+ pserver, _ = vsecurity.NewPrincipal()
+ pclient, _ = vsecurity.NewPrincipal()
+ server, _ = pserver.BlessSelf("server")
+
+ // B generates the provided blessings for the client and ensures
+ // that the server will recognize them.
+ B = func(names ...string) security.Blessings {
+ var ret security.Blessings
+ for _, name := range names {
+ b, err := pclient.BlessSelf(name)
+ if err != nil {
+ t.Fatalf("%q: %v", name, err)
+ }
+ if err := pserver.AddToRoots(b); err != nil {
+ t.Fatalf("%q: %v", name, err)
+ }
+ if ret, err = security.UnionOfBlessings(ret, b); err != nil {
+ t.Fatal(err)
+ }
+ }
+ return ret
+ }
+
+ run = func(test testcase) error {
+ ctx := security.NewContext(&security.ContextParams{
+ LocalPrincipal: pserver,
+ LocalBlessings: server,
+ RemoteBlessings: test.Client,
+ Method: test.Method,
+ MethodTags: methodTags(test.Method),
+ })
+ return authorizer.Authorize(ctx)
+ }
+ )
+
+ // Test cases where access should be granted to methods with tags on
+ // them.
+ for _, test := range []testcase{
+ {"Get", nil},
+ {"Get", B("ali")},
+ {"Get", B("bob/friend", "che/enemy")},
+
+ {"Put", B("ali")},
+ {"Put", B("ali/family/mom")},
+ {"Put", B("bob/friends")},
+ {"Put", B("bob/acquantainces/carol", "che")}, // Access granted because of "che"
+
+ {"Resolve", B("ali")},
+ {"Resolve", B("ali/family/boss")},
+
+ {"AllTags", B("ali/family/boss")},
+ } {
+ if err := run(test); err != nil {
+ t.Errorf("Access denied to method %q to %v: %v", test.Method, test.Client, err)
+ }
+ }
+ // Test cases where access should be denied.
+ for _, test := range []testcase{
+ // Nobody is denied access to "Get"
+ {"Put", B("bob/acquaintances/dave", "che/friend", "dave")},
+ {"Resolve", B("ali/family/friend")},
+ // Since there are no tags on the NoTags method, it has an
+ // empty ACL. No client will have access.
+ {"NoTags", B("ali", "ali/family/boss", "bob")},
+ // On a method with multiple tags on it, all must be satisfied.
+ {"AllTags", B("superman")}, // Only in the X ACL, not in R or W
+ {"AllTags", B("superman", "clark")}, // In X and in R, but not W
+ } {
+ if err := run(test); err == nil {
+ t.Errorf("Access to %q granted to %v", test.Method, test.Client)
+ }
+ }
+}
+
+func TestTaggedACLAuthorizerSelfRPCs(t *testing.T) {
+ var (
+ // Client and server are the same principal, though have
+ // different blessings.
+ p, _ = vsecurity.NewPrincipal()
+ client, _ = p.BlessSelf("client")
+ server, _ = p.BlessSelf("server")
+ // Authorizer with a TaggedACLMap that grants read access to
+ // anyone, write/execute access to noone.
+ typ test.MyTag
+ authorizer, _ = TaggedACLAuthorizer(TaggedACLMap{"R": {In: []security.BlessingPattern{"nobody"}}}, reflect.TypeOf(typ))
+ )
+ for _, test := range []string{"Put", "Get", "Resolve", "NoTags", "AllTags"} {
+ ctx := security.NewContext(&security.ContextParams{
+ LocalPrincipal: p,
+ LocalBlessings: server,
+ RemoteBlessings: client,
+ Method: test,
+ MethodTags: methodTags(test),
+ })
+ if err := authorizer.Authorize(ctx); err != nil {
+ t.Errorf("Got error %v for method %q", err, test)
+ }
+ }
+}
+
+func TestTaggedACLAuthorizerWithNilACL(t *testing.T) {
+ var (
+ authorizer, _ = TaggedACLAuthorizer(nil, reflect.TypeOf(test.Read))
+ pserver, _ = vsecurity.NewPrincipal()
+ pclient, _ = vsecurity.NewPrincipal()
+ server, _ = pserver.BlessSelf("server")
+ client, _ = pclient.BlessSelf("client")
+ )
+ for _, test := range []string{"Put", "Get", "Resolve", "NoTags", "AllTags"} {
+ ctx := security.NewContext(&security.ContextParams{
+ LocalPrincipal: pserver,
+ LocalBlessings: server,
+ RemoteBlessings: client,
+ Method: test,
+ MethodTags: methodTags(test),
+ })
+ if err := authorizer.Authorize(ctx); err == nil {
+ t.Errorf("nil TaggedACLMap authorized method %q", test)
+ }
+ }
+}
+
+func TestTaggedACLAuthorizerFromFile(t *testing.T) {
+ file, err := ioutil.TempFile("", "TestTaggedACLAuthorizerFromFile")
+ if err != nil {
+ t.Fatal(err)
+ }
+ filename := file.Name()
+ file.Close()
+
+ var (
+ authorizer, _ = TaggedACLAuthorizerFromFile(filename, reflect.TypeOf(test.Read))
+ pserver, _ = vsecurity.NewPrincipal()
+ pclient, _ = vsecurity.NewPrincipal()
+ server, _ = pserver.BlessSelf("alice")
+ alicefriend, _ = pserver.Bless(pclient.PublicKey(), server, "friend/bob", security.UnconstrainedUse())
+ ctx = security.NewContext(&security.ContextParams{
+ LocalPrincipal: pserver,
+ LocalBlessings: server,
+ RemoteBlessings: alicefriend,
+ Method: "Get",
+ MethodTags: methodTags("Get"),
+ })
+ )
+ // Make pserver recognize itself as an authority on "alice/..." blessings.
+ if err := pserver.AddToRoots(server); err != nil {
+ t.Fatal(err)
+ }
+ // "alice/friend/bob" should not have access to test.Read methods like Get.
+ if err := authorizer.Authorize(ctx); err == nil {
+ t.Fatalf("Expected authorization error as %v is not on the ACL for Read operations", ctx.RemoteBlessings())
+ }
+ // Rewrite the file giving access
+ if err := ioutil.WriteFile(filename, []byte(`{"R": { "In":["alice/friend/..."] }}`), 0600); err != nil {
+ t.Fatal(err)
+ }
+ // Now should have access
+ if err := authorizer.Authorize(ctx); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestTagTypeMustBeString(t *testing.T) {
+ type I int
+ if auth, err := TaggedACLAuthorizer(TaggedACLMap{}, reflect.TypeOf(I(0))); err == nil || auth != nil {
+ t.Errorf("Got (%v, %v), wanted error since tag type is not a string", auth, err)
+ }
+ if auth, err := TaggedACLAuthorizerFromFile("does_not_matter", reflect.TypeOf(I(0))); err == nil || auth != nil {
+ t.Errorf("Got (%v, %v), wanted error since tag type is not a string", auth, err)
+ }
+}
+
+func methodTags(method string) []interface{} {
+ server := &test.ServerStubMyObject{}
+ tags, _ := server.GetMethodTags(nil, method)
+ return tags
+}
diff --git a/security/acl/test/vdl.vdl b/security/acl/test/vdl.vdl
new file mode 100644
index 0000000..fd3a73f
--- /dev/null
+++ b/security/acl/test/vdl.vdl
@@ -0,0 +1,23 @@
+// Package test provides a VDL specification for a service used in the unittest of the acl package.
+package test
+
+// Any package can define tags (of arbitrary types) to be attached to methods.
+// This type can be used to index into a TaggedACLMap.
+type MyTag string
+
+const (
+ // For this example/unittest, there are three possible values of MyTag,
+ // each represented by a single-character string.
+ Read = MyTag("R")
+ Write = MyTag("W")
+ Execute = MyTag("X")
+)
+
+// MyObject demonstrates how tags are attached to methods.
+type MyObject interface {
+ Get() error {Read}
+ Put() error {Write}
+ Resolve() error {Execute}
+ NoTags() error // No tags attached to this.
+ AllTags() error {Read, Write, Execute}
+}
diff --git a/security/acl/test/vdl.vdl.go b/security/acl/test/vdl.vdl.go
new file mode 100644
index 0000000..91e5790
--- /dev/null
+++ b/security/acl/test/vdl.vdl.go
@@ -0,0 +1,324 @@
+// This file was auto-generated by the veyron vdl tool.
+// Source: vdl.vdl
+
+// Package test provides a VDL specification for a service used in the unittest of the acl package.
+package test
+
+import (
+ // The non-user imports are prefixed with "_gen_" to prevent collisions.
+ _gen_veyron2 "veyron.io/veyron/veyron2"
+ _gen_context "veyron.io/veyron/veyron2/context"
+ _gen_ipc "veyron.io/veyron/veyron2/ipc"
+ _gen_naming "veyron.io/veyron/veyron2/naming"
+ _gen_vdlutil "veyron.io/veyron/veyron2/vdl/vdlutil"
+ _gen_wiretype "veyron.io/veyron/veyron2/wiretype"
+)
+
+// Any package can define tags (of arbitrary types) to be attached to methods.
+// This type can be used to index into a TaggedACLMap.
+type MyTag string
+
+// For this example/unittest, there are three possible values of MyTag,
+// each represented by a single-character string.
+const Read = MyTag("R")
+
+const Write = MyTag("W")
+
+const Execute = MyTag("X")
+
+// TODO(toddw): Remove this line once the new signature support is done.
+// It corrects a bug where _gen_wiretype is unused in VDL pacakges where only
+// bootstrap types are used on interfaces.
+const _ = _gen_wiretype.TypeIDInvalid
+
+// MyObject demonstrates how tags are attached to methods.
+// MyObject is the interface the client binds and uses.
+// MyObject_ExcludingUniversal is the interface without internal framework-added methods
+// to enable embedding without method collisions. Not to be used directly by clients.
+type MyObject_ExcludingUniversal interface {
+ Get(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+ Put(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+ Resolve(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+ NoTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) // No tags attached to this.
+ AllTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error)
+}
+type MyObject interface {
+ _gen_ipc.UniversalServiceMethods
+ MyObject_ExcludingUniversal
+}
+
+// MyObjectService is the interface the server implements.
+type MyObjectService interface {
+ Get(context _gen_ipc.ServerContext) (err error)
+ Put(context _gen_ipc.ServerContext) (err error)
+ Resolve(context _gen_ipc.ServerContext) (err error)
+ NoTags(context _gen_ipc.ServerContext) (err error) // No tags attached to this.
+ AllTags(context _gen_ipc.ServerContext) (err error)
+}
+
+// BindMyObject returns the client stub implementing the MyObject
+// interface.
+//
+// If no _gen_ipc.Client is specified, the default _gen_ipc.Client in the
+// global Runtime is used.
+func BindMyObject(name string, opts ..._gen_ipc.BindOpt) (MyObject, error) {
+ var client _gen_ipc.Client
+ switch len(opts) {
+ case 0:
+ // Do nothing.
+ case 1:
+ if clientOpt, ok := opts[0].(_gen_ipc.Client); opts[0] == nil || ok {
+ client = clientOpt
+ } else {
+ return nil, _gen_vdlutil.ErrUnrecognizedOption
+ }
+ default:
+ return nil, _gen_vdlutil.ErrTooManyOptionsToBind
+ }
+ stub := &clientStubMyObject{defaultClient: client, name: name}
+
+ return stub, nil
+}
+
+// NewServerMyObject creates a new server stub.
+//
+// It takes a regular server implementing the MyObjectService
+// interface, and returns a new server stub.
+func NewServerMyObject(server MyObjectService) interface{} {
+ stub := &ServerStubMyObject{
+ service: server,
+ }
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
+}
+
+// clientStubMyObject implements MyObject.
+type clientStubMyObject struct {
+ defaultClient _gen_ipc.Client
+ name string
+}
+
+func (__gen_c *clientStubMyObject) client(ctx _gen_context.T) _gen_ipc.Client {
+ if __gen_c.defaultClient != nil {
+ return __gen_c.defaultClient
+ }
+ return _gen_veyron2.RuntimeFromContext(ctx).Client()
+}
+
+func (__gen_c *clientStubMyObject) Get(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Get", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (__gen_c *clientStubMyObject) Put(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Put", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (__gen_c *clientStubMyObject) Resolve(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Resolve", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (__gen_c *clientStubMyObject) NoTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "NoTags", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (__gen_c *clientStubMyObject) AllTags(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "AllTags", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (__gen_c *clientStubMyObject) UnresolveStep(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply []string, err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "UnresolveStep", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&reply, &err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (__gen_c *clientStubMyObject) Signature(ctx _gen_context.T, opts ..._gen_ipc.CallOpt) (reply _gen_ipc.ServiceSignature, err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "Signature", nil, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&reply, &err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+func (__gen_c *clientStubMyObject) GetMethodTags(ctx _gen_context.T, method string, opts ..._gen_ipc.CallOpt) (reply []interface{}, err error) {
+ var call _gen_ipc.Call
+ if call, err = __gen_c.client(ctx).StartCall(ctx, __gen_c.name, "GetMethodTags", []interface{}{method}, opts...); err != nil {
+ return
+ }
+ if ierr := call.Finish(&reply, &err); ierr != nil {
+ err = ierr
+ }
+ return
+}
+
+// ServerStubMyObject wraps a server that implements
+// MyObjectService and provides an object that satisfies
+// the requirements of veyron2/ipc.ReflectInvoker.
+type ServerStubMyObject struct {
+ service MyObjectService
+ gs *_gen_ipc.GlobState
+}
+
+func (__gen_s *ServerStubMyObject) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
+ // TODO(bprosnitz) GetMethodTags() will be replaces with Signature().
+ // Note: This exhibits some weird behavior like returning a nil error if the method isn't found.
+ // This will change when it is replaced with Signature().
+ switch method {
+ case "Get":
+ return []interface{}{MyTag("R")}, nil
+ case "Put":
+ return []interface{}{MyTag("W")}, nil
+ case "Resolve":
+ return []interface{}{MyTag("X")}, nil
+ case "NoTags":
+ return []interface{}{}, nil
+ case "AllTags":
+ return []interface{}{MyTag("R"), MyTag("W"), MyTag("X")}, nil
+ default:
+ return nil, nil
+ }
+}
+
+func (__gen_s *ServerStubMyObject) Signature(call _gen_ipc.ServerCall) (_gen_ipc.ServiceSignature, error) {
+ result := _gen_ipc.ServiceSignature{Methods: make(map[string]_gen_ipc.MethodSignature)}
+ result.Methods["AllTags"] = _gen_ipc.MethodSignature{
+ InArgs: []_gen_ipc.MethodArgument{},
+ OutArgs: []_gen_ipc.MethodArgument{
+ {Name: "", Type: 65},
+ },
+ }
+ result.Methods["Get"] = _gen_ipc.MethodSignature{
+ InArgs: []_gen_ipc.MethodArgument{},
+ OutArgs: []_gen_ipc.MethodArgument{
+ {Name: "", Type: 65},
+ },
+ }
+ result.Methods["NoTags"] = _gen_ipc.MethodSignature{
+ InArgs: []_gen_ipc.MethodArgument{},
+ OutArgs: []_gen_ipc.MethodArgument{
+ {Name: "", Type: 65},
+ },
+ }
+ result.Methods["Put"] = _gen_ipc.MethodSignature{
+ InArgs: []_gen_ipc.MethodArgument{},
+ OutArgs: []_gen_ipc.MethodArgument{
+ {Name: "", Type: 65},
+ },
+ }
+ result.Methods["Resolve"] = _gen_ipc.MethodSignature{
+ InArgs: []_gen_ipc.MethodArgument{},
+ OutArgs: []_gen_ipc.MethodArgument{
+ {Name: "", Type: 65},
+ },
+ }
+
+ result.TypeDefs = []_gen_vdlutil.Any{
+ _gen_wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
+
+ return result, nil
+}
+
+func (__gen_s *ServerStubMyObject) UnresolveStep(call _gen_ipc.ServerCall) (reply []string, err error) {
+ if unresolver, ok := __gen_s.service.(_gen_ipc.Unresolver); ok {
+ return unresolver.UnresolveStep(call)
+ }
+ if call.Server() == nil {
+ return
+ }
+ var published []string
+ if published, err = call.Server().Published(); err != nil || published == nil {
+ return
+ }
+ reply = make([]string, len(published))
+ for i, p := range published {
+ reply[i] = _gen_naming.Join(p, call.Name())
+ }
+ return
+}
+
+func (__gen_s *ServerStubMyObject) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
+func (__gen_s *ServerStubMyObject) Get(call _gen_ipc.ServerCall) (err error) {
+ err = __gen_s.service.Get(call)
+ return
+}
+
+func (__gen_s *ServerStubMyObject) Put(call _gen_ipc.ServerCall) (err error) {
+ err = __gen_s.service.Put(call)
+ return
+}
+
+func (__gen_s *ServerStubMyObject) Resolve(call _gen_ipc.ServerCall) (err error) {
+ err = __gen_s.service.Resolve(call)
+ return
+}
+
+func (__gen_s *ServerStubMyObject) NoTags(call _gen_ipc.ServerCall) (err error) {
+ err = __gen_s.service.NoTags(call)
+ return
+}
+
+func (__gen_s *ServerStubMyObject) AllTags(call _gen_ipc.ServerCall) (err error) {
+ err = __gen_s.service.AllTags(call)
+ return
+}
diff --git a/security/agent/pingpong/main.go b/security/agent/pingpong/main.go
index 08a3aab..1fa34fb 100644
--- a/security/agent/pingpong/main.go
+++ b/security/agent/pingpong/main.go
@@ -58,7 +58,7 @@
auth := vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
security.AllPrincipals: security.AllLabels,
}})
- if err := s.Serve("pingpong", ipc.LeafDispatcher(serverPong, auth)); err != nil {
+ if err := s.Serve("pingpong", serverPong, auth); err != nil {
log.Fatal("error serving service: ", err)
}
diff --git a/security/agent/pingpong/wire.vdl.go b/security/agent/pingpong/wire.vdl.go
index 9bf1574..35862ff 100644
--- a/security/agent/pingpong/wire.vdl.go
+++ b/security/agent/pingpong/wire.vdl.go
@@ -64,9 +64,27 @@
// It takes a regular server implementing the PingPongService
// interface, and returns a new server stub.
func NewServerPingPong(server PingPongService) interface{} {
- return &ServerStubPingPong{
+ stub := &ServerStubPingPong{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubPingPong implements PingPong.
@@ -131,6 +149,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubPingPong struct {
service PingPongService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubPingPong) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -181,6 +200,10 @@
return
}
+func (__gen_s *ServerStubPingPong) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubPingPong) Ping(call _gen_ipc.ServerCall, message string) (reply string, err error) {
reply, err = __gen_s.service.Ping(call, message)
return
diff --git a/security/agent/server/server.go b/security/agent/server/server.go
index a9798ff..9cfb422 100644
--- a/security/agent/server/server.go
+++ b/security/agent/server/server.go
@@ -192,7 +192,7 @@
}
spec := ipc.ListenSpec{Protocol: clientAddr.Network(), Address: clientAddr.String()}
if _, err = s.Listen(spec); err == nil {
- err = s.Serve("", ipc.LeafDispatcher(serverAgent, nil))
+ err = s.Serve("", serverAgent, nil)
}
}
if err != nil {
diff --git a/security/agent/server/wire.vdl.go b/security/agent/server/wire.vdl.go
index d9fcc39..2870d8e 100644
--- a/security/agent/server/wire.vdl.go
+++ b/security/agent/server/wire.vdl.go
@@ -91,9 +91,27 @@
// It takes a regular server implementing the AgentService
// interface, and returns a new server stub.
func NewServerAgent(server AgentService) interface{} {
- return &ServerStubAgent{
+ stub := &ServerStubAgent{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubAgent implements Agent.
@@ -301,6 +319,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubAgent struct {
service AgentService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubAgent) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -518,6 +537,10 @@
return
}
+func (__gen_s *ServerStubAgent) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubAgent) Bless(call _gen_ipc.ServerCall, key []byte, wit security.WireBlessings, extension string, caveat security.Caveat, additionalCaveats []security.Caveat) (reply security.WireBlessings, err error) {
reply, err = __gen_s.service.Bless(call, key, wit, extension, caveat, additionalCaveats)
return
diff --git a/security/blessingroots_test.go b/security/blessingroots_test.go
index 899651c..f129d9e 100644
--- a/security/blessingroots_test.go
+++ b/security/blessingroots_test.go
@@ -15,7 +15,7 @@
var tester rootsTester
var err error
for idx := range tester {
- if tester[idx], _, err = newKey(); err != nil {
+ if tester[idx], _, err = NewPrincipalKey(); err != nil {
panic(err)
}
}
diff --git a/security/principal.go b/security/principal.go
index 4959486..8f4906c 100644
--- a/security/principal.go
+++ b/security/principal.go
@@ -2,8 +2,6 @@
import (
"crypto/ecdsa"
- "crypto/elliptic"
- "crypto/rand"
"fmt"
"os"
"path"
@@ -16,7 +14,7 @@
// NewPrincipal mints a new private key and generates a principal based on
// this key, storing its BlessingRoots and BlessingStore in memory.
func NewPrincipal() (security.Principal, error) {
- pub, priv, err := newKey()
+ pub, priv, err := NewPrincipalKey()
if err != nil {
return nil, err
}
@@ -159,15 +157,6 @@
return key.(*ecdsa.PrivateKey), nil
}
-// newKey generates an ECDSA (public, private) key pair.
-func newKey() (security.PublicKey, *ecdsa.PrivateKey, error) {
- priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
- if err != nil {
- return nil, nil, err
- }
- return security.NewECDSAPublicKey(&priv.PublicKey), priv, nil
-}
-
func initKey(dir string, passphrase []byte) (*ecdsa.PrivateKey, error) {
keyFile := path.Join(dir, privateKeyFile)
f, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
@@ -175,7 +164,7 @@
return nil, fmt.Errorf("failed to open %q for writing: %v", keyFile, err)
}
defer f.Close()
- _, key, err := newKey()
+ _, key, err := NewPrincipalKey()
if err != nil {
return nil, fmt.Errorf("failed to generate private key: %v", err)
}
diff --git a/security/util.go b/security/util.go
index a7bd085..6e1f848 100644
--- a/security/util.go
+++ b/security/util.go
@@ -3,6 +3,7 @@
import (
"bytes"
"crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/json"
@@ -29,6 +30,15 @@
var PassphraseErr = errors.New("passphrase incorrect for decrypting private key")
+// NewPrincipalKey generates an ECDSA (public, private) key pair.
+func NewPrincipalKey() (security.PublicKey, *ecdsa.PrivateKey, error) {
+ priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+ if err != nil {
+ return nil, nil, err
+ }
+ return security.NewECDSAPublicKey(&priv.PublicKey), priv, nil
+}
+
// LoadPEMKey loads a key from 'r'. returns PassphraseErr for incorrect Passphrase.
// If the key held in 'r' is unencrypted, 'passphrase' will be ignored.
func LoadPEMKey(r io.Reader, passphrase []byte) (interface{}, error) {
diff --git a/services/identity/identity.vdl.go b/services/identity/identity.vdl.go
index 85027dc..60a4fc0 100644
--- a/services/identity/identity.vdl.go
+++ b/services/identity/identity.vdl.go
@@ -84,9 +84,27 @@
// It takes a regular server implementing the OAuthBlesserService
// interface, and returns a new server stub.
func NewServerOAuthBlesser(server OAuthBlesserService) interface{} {
- return &ServerStubOAuthBlesser{
+ stub := &ServerStubOAuthBlesser{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubOAuthBlesser implements OAuthBlesser.
@@ -151,6 +169,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubOAuthBlesser struct {
service OAuthBlesserService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubOAuthBlesser) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -228,6 +247,10 @@
return
}
+func (__gen_s *ServerStubOAuthBlesser) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubOAuthBlesser) BlessUsingAccessToken(call _gen_ipc.ServerCall, token string) (blessing security.WireBlessings, email string, err error) {
blessing, email, err = __gen_s.service.BlessUsingAccessToken(call, token)
return
@@ -284,9 +307,27 @@
// It takes a regular server implementing the MacaroonBlesserService
// interface, and returns a new server stub.
func NewServerMacaroonBlesser(server MacaroonBlesserService) interface{} {
- return &ServerStubMacaroonBlesser{
+ stub := &ServerStubMacaroonBlesser{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubMacaroonBlesser implements MacaroonBlesser.
@@ -351,6 +392,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubMacaroonBlesser struct {
service MacaroonBlesserService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubMacaroonBlesser) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -427,6 +469,10 @@
return
}
+func (__gen_s *ServerStubMacaroonBlesser) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubMacaroonBlesser) Bless(call _gen_ipc.ServerCall, macaroon string) (reply security.WireBlessings, err error) {
reply, err = __gen_s.service.Bless(call, macaroon)
return
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 5d4773f..f267b89 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -193,7 +193,7 @@
dispatcher := newDispatcher(googleParams, macaroonKey)
objectname := naming.Join("identity", fmt.Sprintf("%v", r.Principal().BlessingStore().Default()))
- if err := server.Serve(objectname, dispatcher); err != nil {
+ if err := server.ServeDispatcher(objectname, dispatcher); err != nil {
return nil, nil, fmt.Errorf("failed to start Veyron services: %v", err)
}
vlog.Infof("Google blessing and discharger services enabled at %v", naming.JoinAddressName(ep.String(), objectname))
diff --git a/services/identity/revocation/revoker_test.go b/services/identity/revocation/revoker_test.go
index ad4ad7e..6bb2148 100644
--- a/services/identity/revocation/revoker_test.go
+++ b/services/identity/revocation/revoker_test.go
@@ -6,7 +6,6 @@
"testing"
"veyron.io/veyron/veyron2"
- "veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/security"
@@ -33,7 +32,7 @@
t.Fatalf("dischargerServer.Listen failed: %v", err)
}
dischargerServiceStub := services.NewServerDischarger(discharger.NewDischarger())
- if err := dischargerServer.Serve("", ipc.LeafDispatcher(dischargerServiceStub, nil)); err != nil {
+ if err := dischargerServer.Serve("", dischargerServiceStub, nil); err != nil {
t.Fatalf("dischargerServer.Serve revoker: %s", err)
}
return r.Principal().PublicKey(),
diff --git a/services/mgmt/application/applicationd/main.go b/services/mgmt/application/applicationd/main.go
index e815fa4..fa11016 100644
--- a/services/mgmt/application/applicationd/main.go
+++ b/services/mgmt/application/applicationd/main.go
@@ -39,7 +39,7 @@
if err != nil {
vlog.Fatalf("Listen(%s) failed: %v", roaming.ListenSpec, err)
}
- if err := server.Serve(*name, dispatcher); err != nil {
+ if err := server.ServeDispatcher(*name, dispatcher); err != nil {
vlog.Fatalf("Serve(%v) failed: %v", *name, err)
}
vlog.Infof("Application repository running at endpoint=%q", endpoint)
diff --git a/services/mgmt/application/impl/impl_test.go b/services/mgmt/application/impl/impl_test.go
index 672a336..c073c99 100644
--- a/services/mgmt/application/impl/impl_test.go
+++ b/services/mgmt/application/impl/impl_test.go
@@ -45,7 +45,7 @@
if err != nil {
t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
}
- if err := server.Serve("", dispatcher); err != nil {
+ if err := server.ServeDispatcher("", dispatcher); err != nil {
t.Fatalf("Serve(%v) failed: %v", dispatcher, err)
}
diff --git a/services/mgmt/binary/binaryd/main.go b/services/mgmt/binary/binaryd/main.go
index 28bb8ad..d67f1a7 100644
--- a/services/mgmt/binary/binaryd/main.go
+++ b/services/mgmt/binary/binaryd/main.go
@@ -3,6 +3,7 @@
import (
"flag"
"io/ioutil"
+ "net"
"net/http"
"os"
"path/filepath"
@@ -10,6 +11,7 @@
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/vlog"
+ "veyron.io/veyron/veyron/lib/netstate"
"veyron.io/veyron/veyron/lib/signals"
"veyron.io/veyron/veyron/profiles/roaming"
vflag "veyron.io/veyron/veyron/security/flag"
@@ -22,12 +24,35 @@
)
var (
- name = flag.String("name", "", "name to mount the binary repository as")
- root = flag.String("root", "", "root directory for the binary repository")
+ name = flag.String("name", "", "name to mount the binary repository as")
+ root = flag.String("root", "", "root directory for the binary repository")
+ httpAddr = flag.String("http", ":0", "TCP address on which the HTTP server runs")
)
+// toIPPort tries to swap in the 'best' accessible IP for the host part of the
+// address, if the provided address has an unspecified IP.
+func toIPPort(addr string) string {
+ host, port, err := net.SplitHostPort(addr)
+ if err != nil {
+ vlog.Errorf("SplitHostPort(%v) failed: %v", addr, err)
+ os.Exit(1)
+ }
+ ip := net.ParseIP(host)
+ if ip.IsUnspecified() {
+ host = "127.0.0.1"
+ ips, err := netstate.GetAccessibleIPs()
+ if err == nil {
+ if a, err := roaming.ListenSpec.AddressChooser("tcp", ips); err == nil && len(a) > 0 {
+ host = a[0].Address().String()
+ }
+ }
+ }
+ return net.JoinHostPort(host, port)
+}
+
func main() {
- flag.Parse()
+ runtime := rt.Init()
+ defer runtime.Cleanup()
if *root == "" {
var err error
if *root, err = ioutil.TempDir("", defaultRootPrefix); err != nil {
@@ -67,16 +92,19 @@
return
}
- // TODO(caprita): Flagify port.
+ listener, err := net.Listen("tcp", *httpAddr)
+ if err != nil {
+ vlog.Errorf("Listen(%s) failed: %v", *httpAddr, err)
+ os.Exit(1)
+ }
+ vlog.Infof("Binary repository HTTP server at: %q", toIPPort(listener.Addr().String()))
go func() {
- if err := http.ListenAndServe(":8080", http.FileServer(impl.NewHTTPRoot(state))); err != nil {
- vlog.Errorf("ListenAndServe() failed: %v", err)
+ if err := http.Serve(listener, http.FileServer(impl.NewHTTPRoot(state))); err != nil {
+ vlog.Errorf("Serve() failed: %v", err)
os.Exit(1)
}
}()
- runtime := rt.Init()
- defer runtime.Cleanup()
server, err := runtime.NewServer()
if err != nil {
vlog.Errorf("NewServer() failed: %v", err)
@@ -89,8 +117,8 @@
vlog.Errorf("Listen(%s) failed: %v", roaming.ListenSpec, err)
return
}
- if err := server.Serve(*name, impl.NewDispatcher(state, auth)); err != nil {
- vlog.Errorf("Serve(%v) failed: %v", *name, err)
+ if err := server.ServeDispatcher(*name, impl.NewDispatcher(state, auth)); err != nil {
+ vlog.Errorf("ServeDispatcher(%v) failed: %v", *name, err)
return
}
vlog.Infof("Binary repository running at endpoint=%q", endpoint)
diff --git a/services/mgmt/binary/binaryd/test.sh b/services/mgmt/binary/binaryd/test.sh
index e3547e9..2fd1661 100755
--- a/services/mgmt/binary/binaryd/test.sh
+++ b/services/mgmt/binary/binaryd/test.sh
@@ -25,6 +25,7 @@
local -r REPO="binaryd-test-repo"
shell_test::start_server "${BINARYD_BIN}" --name="${REPO}" --veyron.tcp.address=127.0.0.1:0 \
|| shell_test::fail "line ${LINENO} failed to start binaryd"
+ local -r HTTP_ADDR=$(grep 'HTTP server at: "' "${START_SERVER_LOG_FILE}" | sed -e 's/^.*HTTP server at: "//' | sed -e 's/"$//')
# Create a binary file.
local -r BINARY_SUFFIX="test-binary"
@@ -42,7 +43,7 @@
fi
local -r BINARY_FILE3=$(shell::tmp_file)
- curl -f -o "${BINARY_FILE3}" http://localhost:8080/"${BINARY_SUFFIX}" || shell_test::fail "line ${LINENO}: 'HTTP download' failed"
+ curl -f -o "${BINARY_FILE3}" "http://${HTTP_ADDR}/${BINARY_SUFFIX}" || shell_test::fail "line ${LINENO}: 'HTTP download' failed"
if [[ $(cmp "${BINARY_FILE}" "${BINARY_FILE3}" &> /dev/null) ]]; then
shell_test::fail "mismatching binary file downloaded via HTTP"
fi
diff --git a/services/mgmt/binary/impl/http.go b/services/mgmt/binary/impl/http.go
index df6ec69..251ff00 100644
--- a/services/mgmt/binary/impl/http.go
+++ b/services/mgmt/binary/impl/http.go
@@ -8,7 +8,7 @@
"veyron.io/veyron/veyron2/vlog"
- "veyron.io/veyron/veyron/services/mgmt/binary/impl/merge_file"
+ "veyron.io/veyron/veyron/services/mgmt/binary/impl/multipart"
)
// NewHTTPRoot returns an implementation of http.FileSystem that can be used
@@ -24,7 +24,7 @@
// TODO(caprita): Tie this in with DownloadURL, to control which binaries
// are downloadable via url.
-// Open implements http.FileSystem. It uses the merge file implementation
+// Open implements http.FileSystem. It uses the multipart file implementation
// to wrap the content parts into one logical file.
func (r httpRoot) Open(name string) (http.File, error) {
name = strings.TrimPrefix(name, "/")
@@ -45,5 +45,5 @@
return nil, errOperationFailed
}
}
- return merge_file.NewMergeFile(name, partFiles)
+ return multipart.NewFile(name, partFiles)
}
diff --git a/services/mgmt/binary/impl/impl_test.go b/services/mgmt/binary/impl/impl_test.go
index 8212e1e..a38ef40 100644
--- a/services/mgmt/binary/impl/impl_test.go
+++ b/services/mgmt/binary/impl/impl_test.go
@@ -129,7 +129,7 @@
t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
}
dontPublishName := ""
- if err := server.Serve(dontPublishName, dispatcher); err != nil {
+ if err := server.ServeDispatcher(dontPublishName, dispatcher); err != nil {
t.Fatalf("Serve(%q) failed: %v", dontPublishName, err)
}
name := naming.JoinAddressName(endpoint.String(), "//test")
diff --git a/services/mgmt/binary/impl/merge_file/merge_file.go b/services/mgmt/binary/impl/multipart/multipart.go
similarity index 73%
rename from services/mgmt/binary/impl/merge_file/merge_file.go
rename to services/mgmt/binary/impl/multipart/multipart.go
index 06dd1a2..ab43178 100644
--- a/services/mgmt/binary/impl/merge_file/merge_file.go
+++ b/services/mgmt/binary/impl/multipart/multipart.go
@@ -1,9 +1,6 @@
-// merge_file provides an implementation for http.File that merges
-// several files into one logical file.
-package merge_file
-
-// TODO(caprita): rename this package to multipart, and the constructor to
-// NewFile. Usage: f, err := multipart.NewFile(...).
+// multipart provides an implementation for http.File that acts as one logical
+// file backed by several physical files (the 'parts').
+package multipart
import (
"fmt"
@@ -15,11 +12,11 @@
var internalErr = fmt.Errorf("internal error")
-// NewMergeFile creates the "merge" file out of the provided parts.
+// NewFile creates the multipart file out of the provided parts.
// The sizes of the parts are captured at the outset and not updated
-// for the lifetime of the merge file (any subsequent modifications
+// for the lifetime of the multipart file (any subsequent modifications
// in the parts will cause Read and Seek to work incorrectly).
-func NewMergeFile(name string, parts []*os.File) (http.File, error) {
+func NewFile(name string, parts []*os.File) (http.File, error) {
fileParts := make([]filePart, len(parts))
for i, p := range parts {
stat, err := p.Stat()
@@ -33,7 +30,7 @@
}
fileParts[i] = filePart{file: p, size: size}
}
- return &mergeFile{name: name, parts: fileParts}, nil
+ return &multipartFile{name: name, parts: fileParts}, nil
}
type filePart struct {
@@ -41,14 +38,14 @@
size int64
}
-type mergeFile struct {
+type multipartFile struct {
name string
parts []filePart
activePart int
partOffset int64
}
-func (m *mergeFile) currPos() (res int64) {
+func (m *multipartFile) currPos() (res int64) {
for i := 0; i < m.activePart; i++ {
res += m.parts[i].size
}
@@ -56,7 +53,7 @@
return
}
-func (m *mergeFile) totalSize() (res int64) {
+func (m *multipartFile) totalSize() (res int64) {
for _, p := range m.parts {
res += p.size
}
@@ -64,7 +61,7 @@
}
// Readdir is not implemented.
-func (*mergeFile) Readdir(int) ([]os.FileInfo, error) {
+func (*multipartFile) Readdir(int) ([]os.FileInfo, error) {
return nil, fmt.Errorf("Not implemented")
}
@@ -75,12 +72,12 @@
modTime time.Time
}
-// Name returns the name of the merge file.
+// Name returns the name of the multipart file.
func (f *fileInfo) Name() string {
return f.name
}
-// Size returns the size of the merge file (the sum of all parts).
+// Size returns the size of the multipart file (the sum of all parts).
func (f *fileInfo) Size() int64 {
return f.size
}
@@ -105,8 +102,8 @@
return nil
}
-// Stat describes the merge file.
-func (m *mergeFile) Stat() (os.FileInfo, error) {
+// Stat describes the multipart file.
+func (m *multipartFile) Stat() (os.FileInfo, error) {
return &fileInfo{
name: m.name,
size: m.totalSize(),
@@ -116,7 +113,7 @@
}
// Close closes all the parts.
-func (m *mergeFile) Close() error {
+func (m *multipartFile) Close() error {
var lastErr error
for _, p := range m.parts {
if err := p.file.Close(); err != nil {
@@ -127,7 +124,7 @@
}
// Read reads from the parts in sequence.
-func (m *mergeFile) Read(buf []byte) (int, error) {
+func (m *multipartFile) Read(buf []byte) (int, error) {
if m.activePart >= len(m.parts) {
return 0, io.EOF
}
@@ -151,7 +148,7 @@
}
// Seek seeks into the part corresponding to the global offset.
-func (m *mergeFile) Seek(offset int64, whence int) (int64, error) {
+func (m *multipartFile) Seek(offset int64, whence int) (int64, error) {
var target int64
switch whence {
case 0:
diff --git a/services/mgmt/binary/impl/merge_file/merge_file_test.go b/services/mgmt/binary/impl/multipart/multipart_test.go
similarity index 91%
rename from services/mgmt/binary/impl/merge_file/merge_file_test.go
rename to services/mgmt/binary/impl/multipart/multipart_test.go
index 1d903a1..9866697 100644
--- a/services/mgmt/binary/impl/merge_file/merge_file_test.go
+++ b/services/mgmt/binary/impl/multipart/multipart_test.go
@@ -1,4 +1,4 @@
-package merge_file_test
+package multipart_test
import (
"io"
@@ -10,7 +10,7 @@
"strings"
"testing"
- "veyron.io/veyron/veyron/services/mgmt/binary/impl/merge_file"
+ "veyron.io/veyron/veyron/services/mgmt/binary/impl/multipart"
)
func read(t *testing.T, m http.File, thisMuch int) string {
@@ -32,11 +32,11 @@
}
}
-// TestMergeFile verifies the http.File operations on the merge file.
-func TestMergeFile(t *testing.T) {
+// TestFile verifies the http.File operations on the multipart file.
+func TestFile(t *testing.T) {
contents := []string{"v", "is", "for", "vanadium"}
files := make([]*os.File, len(contents))
- d, err := ioutil.TempDir("", "merge_files")
+ d, err := ioutil.TempDir("", "multiparts")
if err != nil {
t.Fatalf("TempDir() failed: %v", err)
}
@@ -53,9 +53,9 @@
t.Fatalf("Open(%v) failed: %v", fPath, err)
}
}
- m, err := merge_file.NewMergeFile("bunnies", files)
+ m, err := multipart.NewFile("bunnies", files)
if err != nil {
- t.Fatalf("newMergeFile failed: %v", err)
+ t.Fatalf("NewFile failed: %v", err)
}
defer func() {
if err := m.Close(); err != nil {
diff --git a/services/mgmt/build/buildd/main.go b/services/mgmt/build/buildd/main.go
index b46e98c..6d05b59 100644
--- a/services/mgmt/build/buildd/main.go
+++ b/services/mgmt/build/buildd/main.go
@@ -4,7 +4,6 @@
"flag"
"os"
- "veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/services/mgmt/build"
"veyron.io/veyron/veyron2/vlog"
@@ -36,7 +35,7 @@
vlog.Errorf("Listen(%s) failed: %v", roaming.ListenSpec, err)
return
}
- if err := server.Serve(*name, ipc.LeafDispatcher(build.NewServerBuilder(impl.NewInvoker(*gobin, *goroot)), vflag.NewAuthorizerOrDie())); err != nil {
+ if err := server.Serve(*name, build.NewServerBuilder(impl.NewInvoker(*gobin, *goroot)), vflag.NewAuthorizerOrDie()); err != nil {
vlog.Errorf("Serve(%v) failed: %v", *name, err)
return
}
diff --git a/services/mgmt/build/impl/impl_test.go b/services/mgmt/build/impl/impl_test.go
index dd4be30..37f0f5a 100644
--- a/services/mgmt/build/impl/impl_test.go
+++ b/services/mgmt/build/impl/impl_test.go
@@ -8,7 +8,6 @@
"strings"
"testing"
- "veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/services/mgmt/build"
@@ -58,7 +57,7 @@
t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
}
unpublished := ""
- if err := server.Serve(unpublished, ipc.LeafDispatcher(build.NewServerBuilder(NewInvoker(gobin, goroot)), nil)); err != nil {
+ if err := server.Serve(unpublished, build.NewServerBuilder(NewInvoker(gobin, goroot)), nil); err != nil {
t.Fatalf("Serve(%q) failed: %v", unpublished, err)
}
name := "/" + endpoint.String()
diff --git a/services/mgmt/debug/debug.vdl.go b/services/mgmt/debug/debug.vdl.go
index 96e09d0..34514b4 100644
--- a/services/mgmt/debug/debug.vdl.go
+++ b/services/mgmt/debug/debug.vdl.go
@@ -97,12 +97,30 @@
// It takes a regular server implementing the DebugService
// interface, and returns a new server stub.
func NewServerDebug(server DebugService) interface{} {
- return &ServerStubDebug{
+ stub := &ServerStubDebug{
ServerStubLogFile: *logreader.NewServerLogFile(server).(*logreader.ServerStubLogFile),
ServerStubStats: *stats.NewServerStats(server).(*stats.ServerStubStats),
ServerStubPProf: *pprof.NewServerPProf(server).(*pprof.ServerStubPProf),
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubDebug implements Debug.
@@ -164,6 +182,7 @@
pprof.ServerStubPProf
service DebugService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubDebug) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -368,3 +387,7 @@
}
return
}
+
+func (__gen_s *ServerStubDebug) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
diff --git a/services/mgmt/debug/server.go b/services/mgmt/debug/server.go
index 95b8c13..4cff33a 100644
--- a/services/mgmt/debug/server.go
+++ b/services/mgmt/debug/server.go
@@ -25,7 +25,7 @@
if err != nil {
return "", nil, fmt.Errorf("failed to listen on %s: %v", listenSpec, err)
}
- if err := server.Serve("", disp); err != nil {
+ if err := server.ServeDispatcher("", disp); err != nil {
return "", nil, err
}
ep := endpoint.String()
diff --git a/services/mgmt/lib/binary/impl_test.go b/services/mgmt/lib/binary/impl_test.go
index 8ec796f..8da8032 100644
--- a/services/mgmt/lib/binary/impl_test.go
+++ b/services/mgmt/lib/binary/impl_test.go
@@ -51,7 +51,7 @@
t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
}
suffix := ""
- if err := server.Serve(suffix, dispatcher); err != nil {
+ if err := server.ServeDispatcher(suffix, dispatcher); err != nil {
t.Fatalf("Serve(%v, %v) failed: %v", suffix, dispatcher, err)
}
von := naming.JoinAddressName(endpoint.String(), "//test")
diff --git a/services/mgmt/logreader/impl/common_test.go b/services/mgmt/logreader/impl/common_test.go
index c81320b..91194ad 100644
--- a/services/mgmt/logreader/impl/common_test.go
+++ b/services/mgmt/logreader/impl/common_test.go
@@ -20,7 +20,7 @@
t.Fatalf("Listen failed: %v", err)
return nil, "", err
}
- if err := server.Serve("", disp); err != nil {
+ if err := server.ServeDispatcher("", disp); err != nil {
t.Fatalf("Serve failed: %v", err)
return nil, "", err
}
diff --git a/services/mgmt/node/config.vdl.go b/services/mgmt/node/config.vdl.go
index 5ef274f..7b9dfbe 100644
--- a/services/mgmt/node/config.vdl.go
+++ b/services/mgmt/node/config.vdl.go
@@ -67,9 +67,27 @@
// It takes a regular server implementing the ConfigService
// interface, and returns a new server stub.
func NewServerConfig(server ConfigService) interface{} {
- return &ServerStubConfig{
+ stub := &ServerStubConfig{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubConfig implements Config.
@@ -134,6 +152,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubConfig struct {
service ConfigService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubConfig) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -184,6 +203,10 @@
return
}
+func (__gen_s *ServerStubConfig) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubConfig) Set(call _gen_ipc.ServerCall, key string, value string) (err error) {
err = __gen_s.service.Set(call, key, value)
return
diff --git a/services/mgmt/node/impl/config_invoker.go b/services/mgmt/node/impl/config_invoker.go
index 7e191ac..97ccc35 100644
--- a/services/mgmt/node/impl/config_invoker.go
+++ b/services/mgmt/node/impl/config_invoker.go
@@ -78,7 +78,7 @@
func (c *callbackState) listenFor(key string) callbackListener {
id := c.generateID()
- callbackName := naming.MakeTerminal(naming.Join(c.name, configSuffix, id))
+ callbackName := naming.Join(c.name, configSuffix, id)
// Make the channel buffered to avoid blocking the Set method when
// nothing is receiving on the channel. This happens e.g. when
// unregisterCallbacks executes before Set is called.
diff --git a/services/mgmt/node/impl/impl_test.go b/services/mgmt/node/impl/impl_test.go
index e412e63..a5670c2 100644
--- a/services/mgmt/node/impl/impl_test.go
+++ b/services/mgmt/node/impl/impl_test.go
@@ -143,7 +143,7 @@
defer rt.R().Cleanup()
server, endpoint := newServer()
defer server.Stop()
- name := naming.MakeTerminal(naming.JoinAddressName(endpoint, ""))
+ name := naming.JoinAddressName(endpoint, "")
vlog.VI(1).Infof("Node manager name: %v", name)
// Satisfy the contract described in doc.go by passing the config state
@@ -167,7 +167,7 @@
if err != nil {
vlog.Fatalf("Failed to create node manager dispatcher: %v", err)
}
- if err := server.Serve(publishName, dispatcher); err != nil {
+ if err := server.ServeDispatcher(publishName, dispatcher); err != nil {
vlog.Fatalf("Serve(%v) failed: %v", publishName, err)
}
impl.InvokeCallback(name)
@@ -239,7 +239,7 @@
defer rt.R().Cleanup()
server, _ := newServer()
defer server.Stop()
- if err := server.Serve(publishName, ipc.LeafDispatcher(new(appService), nil)); err != nil {
+ if err := server.Serve(publishName, new(appService), nil); err != nil {
vlog.Fatalf("Serve(%v) failed: %v", publishName, err)
}
ping()
@@ -497,7 +497,7 @@
func setupPingServer(t *testing.T) (<-chan string, func()) {
server, _ := newServer()
pingCh := make(chan string, 1)
- if err := server.Serve("pingserver", ipc.LeafDispatcher(pingServerDisp(pingCh), nil)); err != nil {
+ if err := server.Serve("pingserver", pingServerDisp(pingCh), nil); err != nil {
t.Fatalf("Serve(%q, <dispatcher>) failed: %v", "pingserver", err)
}
return pingCh, func() {
@@ -1329,7 +1329,7 @@
server, _ := newServer()
defer server.Stop()
pingCh := make(chan string, 1)
- if err := server.Serve("pingserver", ipc.LeafDispatcher(pingServerDisp(pingCh), nil)); err != nil {
+ if err := server.Serve("pingserver", pingServerDisp(pingCh), nil); err != nil {
t.Fatalf("Serve(%q, <dispatcher>) failed: %v", "pingserver", err)
}
diff --git a/services/mgmt/node/impl/mock_repo_test.go b/services/mgmt/node/impl/mock_repo_test.go
index dd90a6a..cc8241f 100644
--- a/services/mgmt/node/impl/mock_repo_test.go
+++ b/services/mgmt/node/impl/mock_repo_test.go
@@ -35,9 +35,8 @@
func startApplicationRepository() (*application.Envelope, func()) {
server, _ := newServer()
invoker := new(arInvoker)
- dispatcher := ipc.LeafDispatcher(repository.NewServerApplication(invoker), nil)
name := mockApplicationRepoName
- if err := server.Serve(name, dispatcher); err != nil {
+ if err := server.Serve(name, repository.NewServerApplication(invoker), nil); err != nil {
vlog.Fatalf("Serve(%v) failed: %v", name, err)
}
return &invoker.envelope, func() {
@@ -68,9 +67,8 @@
// returns a cleanup function.
func startBinaryRepository() func() {
server, _ := newServer()
- dispatcher := ipc.LeafDispatcher(repository.NewServerBinary(new(brInvoker)), nil)
name := mockBinaryRepoName
- if err := server.Serve(name, dispatcher); err != nil {
+ if err := server.Serve(name, repository.NewServerBinary(new(brInvoker)), nil); err != nil {
vlog.Fatalf("Serve(%q) failed: %v", name, err)
}
return func() {
diff --git a/services/mgmt/node/impl/node_invoker.go b/services/mgmt/node/impl/node_invoker.go
index 7374abd..309d867 100644
--- a/services/mgmt/node/impl/node_invoker.go
+++ b/services/mgmt/node/impl/node_invoker.go
@@ -256,7 +256,7 @@
return errOperationFailed
}
// Check that invoking Update() succeeds.
- childName = naming.MakeTerminal(naming.Join(childName, "nm"))
+ childName = naming.Join(childName, "nm")
nmClient, err := node.BindNode(childName)
if err != nil {
vlog.Errorf("BindNode(%v) failed: %v", childName, err)
diff --git a/services/mgmt/node/impl/proxy_invoker.go b/services/mgmt/node/impl/proxy_invoker.go
index b46733c..fb52ef7 100644
--- a/services/mgmt/node/impl/proxy_invoker.go
+++ b/services/mgmt/node/impl/proxy_invoker.go
@@ -121,6 +121,11 @@
return results, err
}
+func (p *proxyInvoker) VGlob() *ipc.GlobState {
+ // TODO(rthellend): Add implementation
+ return nil
+}
+
// numResults returns the number of result values for the given method.
func (p *proxyInvoker) numResults(method string) (int, error) {
sig, err := p.sigStub.Signature(nil)
diff --git a/services/mgmt/node/impl/proxy_invoker_test.go b/services/mgmt/node/impl/proxy_invoker_test.go
index b27c671..b2861f6 100644
--- a/services/mgmt/node/impl/proxy_invoker_test.go
+++ b/services/mgmt/node/impl/proxy_invoker_test.go
@@ -16,7 +16,7 @@
func TestProxyInvoker(t *testing.T) {
r := rt.R()
- // server1 is a normal server with a nil dispatcher.
+ // server1 is a normal server
server1, err := r.NewServer()
if err != nil {
t.Fatalf("NewServer: %v", err)
@@ -27,7 +27,7 @@
if err != nil {
t.Fatalf("Listen: %v", err)
}
- if err := server1.Serve("", nil); err != nil {
+ if err := server1.Serve("", &dummy{}, nil); err != nil {
t.Fatalf("server1.Serve: %v", err)
}
@@ -46,7 +46,7 @@
security.Label(security.AllLabels),
&stats.ServerStubStats{},
}
- if err := server2.Serve("", disp); err != nil {
+ if err := server2.ServeDispatcher("", disp); err != nil {
t.Fatalf("server2.Serve: %v", err)
}
@@ -95,6 +95,10 @@
return results
}
+type dummy struct{}
+
+func (*dummy) Method(_ ipc.ServerCall) error { return nil }
+
type proxyDispatcher struct {
remote string
label security.Label
diff --git a/services/mgmt/node/noded/main.go b/services/mgmt/node/noded/main.go
index cda1286..f1b9a2d 100644
--- a/services/mgmt/node/noded/main.go
+++ b/services/mgmt/node/noded/main.go
@@ -50,7 +50,7 @@
if err != nil {
vlog.Fatalf("Listen(%s) failed: %v", roaming.ListenSpec, err)
}
- name := naming.MakeTerminal(naming.JoinAddressName(endpoint.String(), ""))
+ name := naming.JoinAddressName(endpoint.String(), "")
vlog.VI(0).Infof("Node manager object name: %v", name)
configState, err := config.Load()
if err != nil {
@@ -65,7 +65,7 @@
if err != nil {
vlog.Fatalf("Failed to create dispatcher: %v", err)
}
- if err := server.Serve(*publishAs, dispatcher); err != nil {
+ if err := server.ServeDispatcher(*publishAs, dispatcher); err != nil {
vlog.Fatalf("Serve(%v) failed: %v", *publishAs, err)
}
impl.InvokeCallback(name)
diff --git a/services/mgmt/pprof/client/proxy_test.go b/services/mgmt/pprof/client/proxy_test.go
index a563d9f..9b9c655 100644
--- a/services/mgmt/pprof/client/proxy_test.go
+++ b/services/mgmt/pprof/client/proxy_test.go
@@ -37,7 +37,7 @@
if err != nil {
t.Fatalf("failed to listen: %v", err)
}
- if err := s.Serve("", &dispatcher{impl.NewInvoker()}); err != nil {
+ if err := s.ServeDispatcher("", &dispatcher{impl.NewInvoker()}); err != nil {
t.Fatalf("failed to serve: %v", err)
}
l, err := client.StartProxy(r, naming.JoinAddressName(endpoint.String(), ""))
diff --git a/services/mgmt/profile/impl/impl_test.go b/services/mgmt/profile/impl/impl_test.go
index ec4a864..d869dc1 100644
--- a/services/mgmt/profile/impl/impl_test.go
+++ b/services/mgmt/profile/impl/impl_test.go
@@ -59,7 +59,7 @@
if err != nil {
t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
}
- if err := server.Serve("", dispatcher); err != nil {
+ if err := server.ServeDispatcher("", dispatcher); err != nil {
t.Fatalf("Serve failed: %v", err)
}
t.Logf("Profile repository at %v", endpoint)
diff --git a/services/mgmt/profile/profiled/main.go b/services/mgmt/profile/profiled/main.go
index 3aee540..d01b803 100644
--- a/services/mgmt/profile/profiled/main.go
+++ b/services/mgmt/profile/profiled/main.go
@@ -39,8 +39,8 @@
if err != nil {
vlog.Fatalf("Listen(%s) failed: %v", roaming.ListenSpec, err)
}
- if err := server.Serve(*name, dispatcher); err != nil {
- vlog.Fatalf("Serve(%v) failed: %v", *name, err)
+ if err := server.ServeDispatcher(*name, dispatcher); err != nil {
+ vlog.Fatalf("ServeDispatcher(%v) failed: %v", *name, err)
}
vlog.Infof("Profile repository running at endpoint=%q", endpoint)
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index 57ac530..93dbd1a 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -122,10 +122,28 @@
// It takes a regular server implementing the ApplicationService
// interface, and returns a new server stub.
func NewServerApplication(server ApplicationService) interface{} {
- return &ServerStubApplication{
+ stub := &ServerStubApplication{
ServerStubApplication: *repository.NewServerApplication(server).(*repository.ServerStubApplication),
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubApplication implements Application.
@@ -205,6 +223,7 @@
repository.ServerStubApplication
service ApplicationService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubApplication) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -331,6 +350,10 @@
return
}
+func (__gen_s *ServerStubApplication) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubApplication) Put(call _gen_ipc.ServerCall, Profiles []string, Envelope application.Envelope) (err error) {
err = __gen_s.service.Put(call, Profiles, Envelope)
return
@@ -416,10 +439,28 @@
// It takes a regular server implementing the ProfileService
// interface, and returns a new server stub.
func NewServerProfile(server ProfileService) interface{} {
- return &ServerStubProfile{
+ stub := &ServerStubProfile{
ServerStubProfile: *repository.NewServerProfile(server).(*repository.ServerStubProfile),
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubProfile implements Profile.
@@ -510,6 +551,7 @@
repository.ServerStubProfile
service ProfileService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubProfile) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -651,6 +693,10 @@
return
}
+func (__gen_s *ServerStubProfile) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubProfile) Specification(call _gen_ipc.ServerCall) (reply profile.Specification, err error) {
reply, err = __gen_s.service.Specification(call)
return
diff --git a/services/mgmt/root/root.vdl.go b/services/mgmt/root/root.vdl.go
index 273f77b..452cff5 100644
--- a/services/mgmt/root/root.vdl.go
+++ b/services/mgmt/root/root.vdl.go
@@ -72,9 +72,27 @@
// It takes a regular server implementing the RootService
// interface, and returns a new server stub.
func NewServerRoot(server RootService) interface{} {
- return &ServerStubRoot{
+ stub := &ServerStubRoot{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubRoot implements Root.
@@ -139,6 +157,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubRoot struct {
service RootService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubRoot) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -188,6 +207,10 @@
return
}
+func (__gen_s *ServerStubRoot) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubRoot) Reset(call _gen_ipc.ServerCall, Deadline uint64) (err error) {
err = __gen_s.service.Reset(call, Deadline)
return
diff --git a/services/mgmt/root/rootd/main.go b/services/mgmt/root/rootd/main.go
index 1b93942..ff23fdc 100644
--- a/services/mgmt/root/rootd/main.go
+++ b/services/mgmt/root/rootd/main.go
@@ -26,8 +26,8 @@
}
vlog.VI(0).Infof("Listening on %v", ep)
name := ""
- if err := server.Serve(name, dispatcher); err != nil {
- vlog.Errorf("Serve(%v) failed: %v", name, err)
+ if err := server.ServeDispatcher(name, dispatcher); err != nil {
+ vlog.Errorf("ServeDispatcher(%v) failed: %v", name, err)
return
}
diff --git a/services/mgmt/stats/impl/stats_invoker_test.go b/services/mgmt/stats/impl/stats_invoker_test.go
index d15c915..e830fad 100644
--- a/services/mgmt/stats/impl/stats_invoker_test.go
+++ b/services/mgmt/stats/impl/stats_invoker_test.go
@@ -38,7 +38,7 @@
t.Fatalf("Listen failed: %v", err)
return "", nil
}
- if err := server.Serve("", disp); err != nil {
+ if err := server.ServeDispatcher("", disp); err != nil {
t.Fatalf("Serve failed: %v", err)
return "", nil
}
diff --git a/services/mounttable/lib/collection_test.vdl b/services/mounttable/lib/collection_test_interface.vdl
similarity index 100%
rename from services/mounttable/lib/collection_test.vdl
rename to services/mounttable/lib/collection_test_interface.vdl
diff --git a/services/mounttable/lib/collection_test.vdl.go b/services/mounttable/lib/collection_test_interface.vdl.go
similarity index 90%
rename from services/mounttable/lib/collection_test.vdl.go
rename to services/mounttable/lib/collection_test_interface.vdl.go
index e31a27d..377eeb2 100644
--- a/services/mounttable/lib/collection_test.vdl.go
+++ b/services/mounttable/lib/collection_test_interface.vdl.go
@@ -1,5 +1,5 @@
// This file was auto-generated by the veyron vdl tool.
-// Source: collection_test.vdl
+// Source: collection_test_interface.vdl
package mounttable
@@ -78,9 +78,27 @@
// It takes a regular server implementing the CollectionService
// interface, and returns a new server stub.
func NewServerCollection(server CollectionService) interface{} {
- return &ServerStubCollection{
+ stub := &ServerStubCollection{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubCollection implements Collection.
@@ -156,6 +174,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubCollection struct {
service CollectionService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubCollection) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -215,6 +234,10 @@
return
}
+func (__gen_s *ServerStubCollection) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubCollection) Export(call _gen_ipc.ServerCall, Val string, Overwrite bool) (err error) {
err = __gen_s.service.Export(call, Val, Overwrite)
return
diff --git a/services/mounttable/lib/mounttable_test.go b/services/mounttable/lib/mounttable_test.go
index f4a3bed..5a011f1 100644
--- a/services/mounttable/lib/mounttable_test.go
+++ b/services/mounttable/lib/mounttable_test.go
@@ -176,7 +176,7 @@
if err != nil {
boom(t, "Failed to Listen mount table: %s", err)
}
- if err := server.Serve("", mt); err != nil {
+ if err := server.ServeDispatcher("", mt); err != nil {
boom(t, "Failed to register mock collection: %s", err)
}
estr := e.String()
@@ -197,7 +197,7 @@
// Add a collection service. This is just a service we can mount
// and test against.
cPrefix := "collection"
- if err := server.Serve(cPrefix, newCollectionServer()); err != nil {
+ if err := server.ServeDispatcher(cPrefix, newCollectionServer()); err != nil {
boom(t, "Failed to register mock collection: %s", err)
}
estr := e.String()
diff --git a/services/mounttable/lib/neighborhood_test.go b/services/mounttable/lib/neighborhood_test.go
index 07146da..f4d47c6 100644
--- a/services/mounttable/lib/neighborhood_test.go
+++ b/services/mounttable/lib/neighborhood_test.go
@@ -55,7 +55,7 @@
boom(t, "Failed to create neighborhood server: %s\n", err)
}
defer nhd.Stop()
- if err := server.Serve("", nhd); err != nil {
+ if err := server.ServeDispatcher("", nhd); err != nil {
boom(t, "Failed to register neighborhood server: %s", err)
}
diff --git a/services/mounttable/mounttabled/mounttable.go b/services/mounttable/mounttabled/mounttable.go
index 7a4be80..0ef7b3b 100644
--- a/services/mounttable/mounttabled/mounttable.go
+++ b/services/mounttable/mounttabled/mounttable.go
@@ -43,8 +43,8 @@
os.Exit(1)
}
name := *mountName
- if err := mtServer.Serve(name, mt); err != nil {
- vlog.Errorf("Serve(%v) failed: %v", name, err)
+ if err := mtServer.ServeDispatcher(name, mt); err != nil {
+ vlog.Errorf("ServeDispatcher(%v) failed: %v", name, err)
os.Exit(1)
}
@@ -77,8 +77,8 @@
vlog.Errorf("NewNeighborhoodServer failed: %v", err)
os.Exit(1)
}
- if err := nhServer.Serve(naming.JoinAddressName(myObjectName, "//nh"), nh); err != nil {
- vlog.Errorf("nhServer.Serve failed to register neighborhood: %v", err)
+ if err := nhServer.ServeDispatcher(naming.JoinAddressName(myObjectName, "//nh"), nh); err != nil {
+ vlog.Errorf("nhServer.ServeDispatcher failed to register neighborhood: %v", err)
os.Exit(1)
}
}
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index 6793150..b36f608 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -83,9 +83,27 @@
// It takes a regular server implementing the DischargerService
// interface, and returns a new server stub.
func NewServerDischarger(server DischargerService) interface{} {
- return &ServerStubDischarger{
+ stub := &ServerStubDischarger{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubDischarger implements Discharger.
@@ -150,6 +168,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubDischarger struct {
service DischargerService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubDischarger) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -208,6 +227,10 @@
return
}
+func (__gen_s *ServerStubDischarger) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubDischarger) Discharge(call _gen_ipc.ServerCall, Caveat _gen_vdlutil.Any, Impetus security.DischargeImpetus) (reply _gen_vdlutil.Any, err error) {
reply, err = __gen_s.service.Discharge(call, Caveat, Impetus)
return
diff --git a/tools/application/impl_test.go b/tools/application/impl_test.go
index c55a5e9..bd323c9 100644
--- a/tools/application/impl_test.go
+++ b/tools/application/impl_test.go
@@ -85,7 +85,7 @@
t.Errorf("Listen failed: %v", err)
return nil, nil, err
}
- if err := server.Serve("", dispatcher); err != nil {
+ if err := server.ServeDispatcher("", dispatcher); err != nil {
t.Errorf("Serve failed: %v", err)
return nil, nil, err
}
diff --git a/tools/associate/impl_test.go b/tools/associate/impl_test.go
index fff2ee5..54850d0 100644
--- a/tools/associate/impl_test.go
+++ b/tools/associate/impl_test.go
@@ -109,8 +109,8 @@
stopServer(t, server)
return nil, nil, err
}
- if err := server.Serve("", dispatcher); err != nil {
- t.Errorf("Serve failed: %v", err)
+ if err := server.ServeDispatcher("", dispatcher); err != nil {
+ t.Errorf("ServeDispatcher failed: %v", err)
stopServer(t, server)
return nil, nil, err
}
diff --git a/tools/binary/impl_test.go b/tools/binary/impl_test.go
index a924a93..d2379ec 100644
--- a/tools/binary/impl_test.go
+++ b/tools/binary/impl_test.go
@@ -94,8 +94,8 @@
t.Errorf("Listen failed: %v", err)
return nil, nil, err
}
- if err := server.Serve("", dispatcher); err != nil {
- t.Errorf("Serve failed: %v", err)
+ if err := server.ServeDispatcher("", dispatcher); err != nil {
+ t.Errorf("ServeDispatcher failed: %v", err)
return nil, nil, err
}
return server, endpoint, nil
diff --git a/tools/build/impl_test.go b/tools/build/impl_test.go
index 4ce3e9e..54bab19 100644
--- a/tools/build/impl_test.go
+++ b/tools/build/impl_test.go
@@ -49,7 +49,7 @@
t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
}
unpublished := ""
- if err := server.Serve(unpublished, ipc.LeafDispatcher(build.NewServerBuilder(&mock{}), nil)); err != nil {
+ if err := server.Serve(unpublished, build.NewServerBuilder(&mock{}), nil); err != nil {
t.Fatalf("Serve(%v) failed: %v", unpublished, err)
}
return server, endpoint
diff --git a/tools/mounttable/impl.go b/tools/mounttable/impl.go
index 1c88cc7..b37d5f6 100644
--- a/tools/mounttable/impl.go
+++ b/tools/mounttable/impl.go
@@ -177,11 +177,14 @@
}
ctx, cancel := rt.R().NewContext().WithTimeout(time.Minute)
defer cancel()
- c, err := bindMT(ctx, args[0])
+ call, err := rt.R().Client().StartCall(ctx, args[0], "ResolveStepX", []interface{}{}, options.NoResolve(true))
if err != nil {
- return fmt.Errorf("bind error: %v", err)
+ return err
}
- entry, err := c.ResolveStepX(ctx)
+ var entry types.MountEntry
+ if ierr := call.Finish(&entry, &err); ierr != nil {
+ return ierr
+ }
if err != nil {
return err
}
diff --git a/tools/mounttable/impl_test.go b/tools/mounttable/impl_test.go
index 9dfe601..fdfc5d1 100644
--- a/tools/mounttable/impl_test.go
+++ b/tools/mounttable/impl_test.go
@@ -73,8 +73,8 @@
t.Errorf("Listen failed: %v", err)
return nil, nil, err
}
- if err := server.Serve("", dispatcher); err != nil {
- t.Errorf("Serve failed: %v", err)
+ if err := server.ServeDispatcher("", dispatcher); err != nil {
+ t.Errorf("ServeDispatcher failed: %v", err)
return nil, nil, err
}
return server, endpoint, nil
@@ -126,7 +126,8 @@
stdout.Reset()
// Test the 'resolvestep' command.
- if err := cmd.Execute([]string{"resolvestep", naming.JoinAddressName(endpoint.String(), "//name")}); err != nil {
+ vlog.Infof("resovestep %s", naming.JoinAddressName(endpoint.String(), "name"))
+ if err := cmd.Execute([]string{"resolvestep", naming.JoinAddressName(endpoint.String(), "name")}); err != nil {
t.Fatalf("%v", err)
}
if expected, got := `Servers: [{server1 123}] Suffix: "name" MT: false`, strings.TrimSpace(stdout.String()); got != expected {
diff --git a/tools/profile/impl_test.go b/tools/profile/impl_test.go
index 0bfd27e..dd8a329 100644
--- a/tools/profile/impl_test.go
+++ b/tools/profile/impl_test.go
@@ -85,7 +85,6 @@
}
func startServer(t *testing.T, r veyron2.Runtime) (ipc.Server, naming.Endpoint, error) {
- dispatcher := NewDispatcher()
server, err := r.NewServer()
if err != nil {
t.Errorf("NewServer failed: %v", err)
@@ -96,8 +95,8 @@
t.Errorf("Listen failed: %v", err)
return nil, nil, err
}
- if err := server.Serve("", dispatcher); err != nil {
- t.Errorf("Serve failed: %v", err)
+ if err := server.ServeDispatcher("", NewDispatcher()); err != nil {
+ t.Errorf("ServeDispatcher failed: %v", err)
return nil, nil, err
}
return server, endpoint, nil
diff --git a/tools/vrpc/impl_test.go b/tools/vrpc/impl_test.go
index 83f0e58..bbff9a4 100644
--- a/tools/vrpc/impl_test.go
+++ b/tools/vrpc/impl_test.go
@@ -126,7 +126,7 @@
}
func startServer(t *testing.T, r veyron2.Runtime) (ipc.Server, naming.Endpoint, error) {
- dispatcher := ipc.LeafDispatcher(test_base.NewServerTypeTester(&server{}), nil)
+ obj := test_base.NewServerTypeTester(&server{})
server, err := r.NewServer()
if err != nil {
t.Errorf("NewServer failed: %v", err)
@@ -138,7 +138,7 @@
t.Errorf("Listen failed: %v", err)
return nil, nil, err
}
- if err := server.Serve("", dispatcher); err != nil {
+ if err := server.Serve("", obj, nil); err != nil {
t.Errorf("Serve failed: %v", err)
return nil, nil, err
}
diff --git a/tools/vrpc/test_base/test_base.vdl.go b/tools/vrpc/test_base/test_base.vdl.go
index 92bf836..ef4e9cf 100644
--- a/tools/vrpc/test_base/test_base.vdl.go
+++ b/tools/vrpc/test_base/test_base.vdl.go
@@ -236,9 +236,27 @@
// It takes a regular server implementing the TypeTesterService
// interface, and returns a new server stub.
func NewServerTypeTester(server TypeTesterService) interface{} {
- return &ServerStubTypeTester{
+ stub := &ServerStubTypeTester{
service: server,
}
+ var gs _gen_ipc.GlobState
+ var self interface{} = stub
+ // VAllGlobber is implemented by the server object, which is wrapped in
+ // a VDL generated server stub.
+ if x, ok := self.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VAllGlobber is implemented by the server object without using a VDL
+ // generated stub.
+ if x, ok := server.(_gen_ipc.VAllGlobber); ok {
+ gs.VAllGlobber = x
+ }
+ // VChildrenGlobber is implemented in the server object.
+ if x, ok := server.(_gen_ipc.VChildrenGlobber); ok {
+ gs.VChildrenGlobber = x
+ }
+ stub.gs = &gs
+ return stub
}
// clientStubTypeTester implements TypeTester.
@@ -510,6 +528,7 @@
// the requirements of veyron2/ipc.ReflectInvoker.
type ServerStubTypeTester struct {
service TypeTesterService
+ gs *_gen_ipc.GlobState
}
func (__gen_s *ServerStubTypeTester) GetMethodTags(call _gen_ipc.ServerCall, method string) ([]interface{}, error) {
@@ -764,6 +783,10 @@
return
}
+func (__gen_s *ServerStubTypeTester) VGlob() *_gen_ipc.GlobState {
+ return __gen_s.gs
+}
+
func (__gen_s *ServerStubTypeTester) EchoBool(call _gen_ipc.ServerCall, I1 bool) (reply bool, err error) {
reply, err = __gen_s.service.EchoBool(call, I1)
return