blob: b78847ff872011546b529890aa60db977527132a [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"strings"
"v.io/v23"
"v.io/v23/context"
"v.io/v23/glob"
"v.io/v23/naming"
"v.io/v23/rpc"
"v.io/v23/security"
"v.io/x/lib/cmdline"
"v.io/x/lib/vlog"
"v.io/x/ref/lib/signals"
"v.io/x/ref/lib/v23cmd"
"v.io/x/ref/lib/xrpc"
_ "v.io/x/ref/runtime/factories/roaming"
"v.io/x/ref/services/mounttable/mounttablelib"
"v.io/x/ref/test/discovery/a"
"v.io/x/ref/test/discovery/b"
)
var (
mtPort int
nhName string
)
func init() {
cmdRun.Flags.IntVar(&mtPort, "mtport", 9000, "port number of mounttable to run")
cmdRun.Flags.StringVar(&nhName, "nhname", "", "neighborhood mt name")
}
var cmdRun = &cmdline.Command{
Runner: v23cmd.RunnerFunc(runServer),
Name: "run",
Short: "Run a server for testing discovery",
}
func runServer(ctx *context.T, env *cmdline.Env, args []string) error {
mtName, stopMT, err := startMounttable(ctx)
if err != nil {
return err
}
defer stopMT()
ctx, _, err = v23.WithNewNamespace(ctx, mtName)
if err != nil {
return err
}
server, err := xrpc.NewDispatchingServer(ctx, "test2", disp2{})
if err != nil {
ctx.Fatalf("NewServer failed: %v", err)
}
ctx.Infof("Listening on %s", server.Status().Endpoints[0].Name())
<-signals.ShutdownOnSignals(ctx)
return nil
}
func startMounttable(ctx *context.T) (string, func(), error) {
listenSpec := rpc.ListenSpec{Addrs: rpc.ListenAddrs{{"wsh", fmt.Sprintf(":%d", mtPort)}}}
mtName, stopMT, err := mounttablelib.StartServers(ctx, listenSpec, "", nhName, "", "", "mounttable")
if err != nil {
vlog.Errorf("mounttablelib.StartServers failed: %v", err)
return "", nil, err
}
vlog.Infof("Started local mounttable at: %v", mtName)
return mtName, stopMT, nil
}
var services2 map[string]rpc.Invoker
func init() {
services2 = make(map[string]rpc.Invoker)
services2["a"] = rpc.ReflectInvokerOrDie(a.AServiceServer(&impl{}))
services2["b"] = rpc.ReflectInvokerOrDie(b.AnotherServiceServer(&impl{}))
services2["c"] = rpc.ReflectInvokerOrDie(b.AnotherServiceServer(&impl{}))
services2["d/e"] = rpc.ReflectInvokerOrDie(a.AServiceServer(&impl{}))
}
type disp2 struct{}
func (_ disp2) Lookup(_ *context.T, suffix string) (interface{}, security.Authorizer, error) {
suffix = strings.TrimLeft(suffix, "/")
if suffix == "" {
return rpc.ReflectInvokerOrDie(&root{}), security.AllowEveryone(), nil
}
invoker, ok := services2[suffix]
if ok {
return invoker, security.AllowEveryone(), nil
}
return nil, nil, nil
}
type root struct{}
func (r *root) Glob__(ctx *context.T, call rpc.ServerCall, pattern string) (<-chan naming.GlobReply, error) {
return r.GlobWithPredicate__(ctx, call, pattern, "")
}
func (r *root) GlobWithPredicate__(ctx *context.T, call rpc.ServerCall, pattern, predicate string) (<-chan naming.GlobReply, error) {
p, err := glob.ParsePredicate(predicate)
if err != nil {
return nil, err
}
ch := make(chan naming.GlobReply)
go func() {
defer close(ch)
for suffix, invoker := range services2 {
sigs, err := invoker.Signature(ctx, nil)
if err != nil {
ch <- naming.GlobReplyError{naming.GlobError{Error: err}}
continue
}
interfaces := make([]string, len(sigs))
for i, sig := range sigs {
interfaces[i] = sig.PkgPath
}
if p == nil || p.Match(naming.Properties{naming.PropInterface: interfaces}) {
ch <- naming.GlobReplyEntry{naming.MountEntry{Name: suffix, IsLeaf: true}}
}
}
}()
return ch, nil
}
type impl struct{}
func (i *impl) AMethod(_ *context.T, _ rpc.ServerCall) error { return nil }
func (i *impl) AnotherMethod(_ *context.T, _ rpc.ServerCall) error { return nil }
func main() {
cmdline.HideGlobalFlagsExcept()
cmdline.Main(cmdRun)
}