discovery: add global discovery to mojo
Change-Id: I6577af005091079d67674b7a44c0472bd0402856
diff --git a/go/src/v.io/mojo/discovery/apptest/apptest.go b/go/src/v.io/mojo/discovery/apptest/apptest.go
index 6670a7d..7d78079 100644
--- a/go/src/v.io/mojo/discovery/apptest/apptest.go
+++ b/go/src/v.io/mojo/discovery/apptest/apptest.go
@@ -18,14 +18,16 @@
func RunAppTests(mctx application.Context) int {
apptests := []func(*testing.T, application.Context){
- AppTestBasic,
+ AppTestDiscoveryBasic,
+ AppTestGlobalDiscoveryBasic,
}
var tests []testing.InternalTest
for _, apptest := range apptests {
qname := runtime.FuncForPC(reflect.ValueOf(apptest).Pointer()).Name()
name := qname[strings.LastIndex(qname, ".")+1:]
- tests = append(tests, testing.InternalTest{name, func(t *testing.T) { apptest(t, mctx) }})
+ f := apptest // To bind the current value of apptest to each closure.
+ tests = append(tests, testing.InternalTest{name, func(t *testing.T) { f(t, mctx) }})
}
// MainStart is not supposed to be called directly, but there is no other way
diff --git a/go/src/v.io/mojo/discovery/apptest/apptest_util.go b/go/src/v.io/mojo/discovery/apptest/apptest_util.go
new file mode 100644
index 0000000..5f0cfa1
--- /dev/null
+++ b/go/src/v.io/mojo/discovery/apptest/apptest_util.go
@@ -0,0 +1,232 @@
+// Copyright 2016 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.
+
+// +build mojo
+
+package apptest
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "log"
+ "reflect"
+ "strings"
+ "sync"
+ "time"
+
+ "mojo/public/go/bindings"
+ "mojo/public/go/system"
+
+ mojom "mojom/v.io/discovery"
+
+ _ "v.io/x/ref/runtime/factories/generic"
+
+ "v.io/mojo/discovery/internal"
+)
+
+type mockScanHandler struct {
+ ch chan mojom.Update_Pointer
+}
+
+func (h *mockScanHandler) OnUpdate(ptr mojom.Update_Pointer) error {
+ h.ch <- ptr
+ return nil
+}
+
+func scan(d mojom.Discovery, query string) (<-chan mojom.Update_Pointer, func(), error) {
+ ch := make(chan mojom.Update_Pointer)
+ handler := &mockScanHandler{ch}
+ req, ptr := mojom.CreateMessagePipeForScanHandler()
+ stub := mojom.NewScanHandlerStub(req, handler, bindings.GetAsyncWaiter())
+
+ closer, e1, e2 := d.Scan(query, ptr)
+ if e1 != nil {
+ close(ch)
+ return nil, nil, errors.New(e1.Msg)
+ }
+ if e2 != nil {
+ close(ch)
+ return nil, nil, e2
+ }
+
+ wg := new(sync.WaitGroup)
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for {
+ if err := stub.ServeRequest(); err != nil {
+ connErr, ok := err.(*bindings.ConnectionError)
+ if !ok || !connErr.Closed() {
+ log.Println(err)
+ }
+ break
+ }
+ }
+ }()
+
+ stop := func() {
+ p := mojom.NewCloserProxy(*closer, bindings.GetAsyncWaiter())
+ p.Close()
+ p.Close_Proxy()
+ stub.Close()
+ wg.Wait()
+ close(ch)
+ }
+ return ch, stop, nil
+}
+
+func scanAndMatch(d mojom.Discovery, query string, wants ...mojom.Advertisement) error {
+ const timeout = 10 * time.Second
+
+ var err error
+ for now := time.Now(); time.Since(now) < timeout; {
+ var updatePtrs []mojom.Update_Pointer
+ updatePtrs, err = doScan(d, query, len(wants))
+ if err != nil {
+ return err
+ }
+ err = matchFound(updatePtrs, wants...)
+ if err == nil {
+ return nil
+ }
+ }
+ return err
+}
+
+func doScan(d mojom.Discovery, query string, expectedUpdates int) ([]mojom.Update_Pointer, error) {
+ scanCh, stop, err := scan(d, query)
+ if err != nil {
+ return nil, err
+ }
+ defer func() {
+ stop()
+ for range scanCh {
+ }
+ }()
+
+ updatePtrs := make([]mojom.Update_Pointer, 0, expectedUpdates)
+ for {
+ var timer <-chan time.Time
+ if len(updatePtrs) >= expectedUpdates {
+ timer = time.After(5 * time.Millisecond)
+ }
+
+ select {
+ case ptr := <-scanCh:
+ updatePtrs = append(updatePtrs, ptr)
+ case <-timer:
+ return updatePtrs, nil
+ }
+ }
+}
+
+func matchFound(updatePtrs []mojom.Update_Pointer, wants ...mojom.Advertisement) error {
+ return match(updatePtrs, false, wants...)
+}
+
+func matchLost(updatePtrs []mojom.Update_Pointer, wants ...mojom.Advertisement) error {
+ return match(updatePtrs, true, wants...)
+}
+
+func match(updatePtrs []mojom.Update_Pointer, lost bool, wants ...mojom.Advertisement) error {
+ updateMap := make(map[[internal.AdIdLen]uint8]mojom.Update)
+ updates := make([]mojom.Update, 0)
+ for _, ptr := range updatePtrs {
+ update := mojom.NewUpdateProxy(ptr, bindings.GetAsyncWaiter())
+ defer update.Close_Proxy()
+
+ id, _ := update.GetId()
+ updateMap[id] = update
+ updates = append(updates, update)
+ }
+ for _, want := range wants {
+ update := updateMap[*want.Id]
+ if update == nil {
+ break
+ }
+ if got, _ := update.IsLost(); got != lost {
+ break
+ }
+ if !updateEqual(update, want) {
+ break
+ }
+ delete(updateMap, *want.Id)
+ }
+ if len(updateMap) == 0 {
+ return nil
+ }
+ return fmt.Errorf("Match failed; got %v, but wanted %v", updatesToDebugString(updates), adsToDebugString(wants))
+}
+
+func updateEqual(update mojom.Update, ad mojom.Advertisement) bool {
+ if got, _ := update.GetId(); got != *ad.Id {
+ return false
+ }
+ if got, _ := update.GetInterfaceName(); got != ad.InterfaceName {
+ return false
+ }
+ if got, _ := update.GetAddresses(); !reflect.DeepEqual(got, ad.Addresses) {
+ return false
+ }
+ if ad.Attributes != nil {
+ for k, v := range *ad.Attributes {
+ if got, _ := update.GetAttribute(k); got != v {
+ return false
+ }
+ }
+ }
+ if ad.Attachments != nil {
+ for k, v := range *ad.Attachments {
+ h, err := update.GetAttachment(k)
+ if err != nil {
+ return false
+ }
+ defer h.Close()
+ h.Wait(system.MOJO_HANDLE_SIGNAL_READABLE, system.MOJO_DEADLINE_INDEFINITE)
+ r, got := h.ReadData(system.MOJO_READ_DATA_FLAG_ALL_OR_NONE)
+ if r != system.MOJO_RESULT_OK {
+ return false
+ }
+ if !bytes.Equal(got, v) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+func adsToDebugString(ads []mojom.Advertisement) string {
+ var strs []string
+ for _, ad := range ads {
+ strs = append(strs, adToDebugString(ad))
+ }
+ return "[]" + strings.Join(strs, ", ") + "]"
+}
+
+func adToDebugString(ad mojom.Advertisement) string {
+ return "{" + strings.Join(dumpFields(ad), ", ") + "}"
+}
+
+func updatesToDebugString(updates []mojom.Update) string {
+ var strs []string
+ for _, u := range updates {
+ strs = append(strs, updateToDebugString(u))
+ }
+ return "[]" + strings.Join(strs, ", ") + "]"
+}
+
+func updateToDebugString(update mojom.Update) string {
+ lost, _ := update.IsLost()
+ ad, _ := update.GetAdvertisement()
+ return fmt.Sprintf("{%v, %v}", lost, strings.Join(dumpFields(ad), ", "))
+}
+
+func dumpFields(i interface{}) []string {
+ var fields []string
+ for rv, i := reflect.ValueOf(i), 0; i < rv.NumField(); i++ {
+ fields = append(fields, fmt.Sprint(rv.Field(i)))
+ }
+ return fields
+}
diff --git a/go/src/v.io/mojo/discovery/apptest/discovery_apptest.go b/go/src/v.io/mojo/discovery/apptest/discovery_apptest.go
index 8eb7325..afc6f92 100644
--- a/go/src/v.io/mojo/discovery/apptest/discovery_apptest.go
+++ b/go/src/v.io/mojo/discovery/apptest/discovery_apptest.go
@@ -7,18 +7,10 @@
package apptest
import (
- "bytes"
- "errors"
- "fmt"
- "log"
- "reflect"
- "strings"
"testing"
- "time"
"mojo/public/go/application"
"mojo/public/go/bindings"
- "mojo/public/go/system"
mojom "mojom/v.io/discovery"
@@ -33,7 +25,7 @@
return mojom.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
}
-func AppTestBasic(t *testing.T, mctx application.Context) {
+func AppTestDiscoveryBasic(t *testing.T, mctx application.Context) {
ads := []mojom.Advertisement{
{
Id: &[internal.AdIdLen]uint8{1, 2, 3},
@@ -78,7 +70,7 @@
}
// Make sure none of advertisements are discoverable by the same discovery instance.
- if err := scanAndMatch(d1, ""); err != nil {
+ if err := scanAndMatch(d1, ``); err != nil {
t.Error(err)
}
@@ -97,11 +89,11 @@
}
// Open a new scan channel and consume expected advertisements first.
- scanCh, stop, err := scan(d2, `v.InterfaceName="v.io/v23/a"`)
+ scanCh, scanStop, err := scan(d2, `v.InterfaceName="v.io/v23/a"`)
if err != nil {
t.Fatal(err)
}
- defer stop()
+ defer scanStop()
update := <-scanCh
if err := matchFound([]mojom.Update_Pointer{update}, ads[0]); err != nil {
@@ -127,208 +119,3 @@
t.Error(err)
}
}
-
-type mockScanHandler struct {
- ch chan mojom.Update_Pointer
-}
-
-func (h *mockScanHandler) OnUpdate(ptr mojom.Update_Pointer) error {
- h.ch <- ptr
- return nil
-}
-
-func scan(d mojom.Discovery, query string) (<-chan mojom.Update_Pointer, func(), error) {
- ch := make(chan mojom.Update_Pointer)
- handler := &mockScanHandler{ch}
- req, ptr := mojom.CreateMessagePipeForScanHandler()
- stub := mojom.NewScanHandlerStub(req, handler, bindings.GetAsyncWaiter())
-
- closer, e1, e2 := d.Scan(query, ptr)
- if e1 != nil {
- close(ch)
- return nil, nil, errors.New(e1.Msg)
- }
- if e2 != nil {
- close(ch)
- return nil, nil, e2
- }
-
- go func() {
- for {
- if err := stub.ServeRequest(); err != nil {
- connErr, ok := err.(*bindings.ConnectionError)
- if !ok || !connErr.Closed() {
- log.Println(err)
- }
- break
- }
- }
- }()
-
- stop := func() {
- p := mojom.NewCloserProxy(*closer, bindings.GetAsyncWaiter())
- p.Close()
- p.Close_Proxy()
- stub.Close()
- close(ch)
- }
- return ch, stop, nil
-}
-
-func scanAndMatch(d mojom.Discovery, query string, wants ...mojom.Advertisement) error {
- const timeout = 10 * time.Second
-
- var err error
- for now := time.Now(); time.Since(now) < timeout; {
- var updatePtrs []mojom.Update_Pointer
- updatePtrs, err = doScan(d, query, len(wants))
- if err != nil {
- return err
- }
- err = matchFound(updatePtrs, wants...)
- if err == nil {
- return nil
- }
- }
- return err
-}
-
-func doScan(d mojom.Discovery, query string, expectedUpdates int) ([]mojom.Update_Pointer, error) {
- scanCh, stop, err := scan(d, query)
- if err != nil {
- return nil, err
- }
- defer func() {
- stop()
- for range scanCh {
- }
- }()
-
- updatePtrs := make([]mojom.Update_Pointer, 0, expectedUpdates)
- for {
- var timer <-chan time.Time
- if len(updatePtrs) >= expectedUpdates {
- timer = time.After(5 * time.Millisecond)
- }
-
- select {
- case ptr := <-scanCh:
- updatePtrs = append(updatePtrs, ptr)
- case <-timer:
- return updatePtrs, nil
- }
- }
-}
-
-func matchFound(updatePtrs []mojom.Update_Pointer, wants ...mojom.Advertisement) error {
- return match(updatePtrs, false, wants...)
-}
-
-func matchLost(updatePtrs []mojom.Update_Pointer, wants ...mojom.Advertisement) error {
- return match(updatePtrs, true, wants...)
-}
-
-func match(updatePtrs []mojom.Update_Pointer, lost bool, wants ...mojom.Advertisement) error {
- updateMap := make(map[[internal.AdIdLen]uint8]mojom.Update)
- updates := make([]mojom.Update, 0)
- for _, ptr := range updatePtrs {
- update := mojom.NewUpdateProxy(ptr, bindings.GetAsyncWaiter())
- defer update.Close_Proxy()
-
- id, _ := update.GetId()
- updateMap[id] = update
- updates = append(updates, update)
- }
- for _, want := range wants {
- update := updateMap[*want.Id]
- if update == nil {
- break
- }
- if got, _ := update.IsLost(); got != lost {
- break
- }
- if !updateEqual(update, want) {
- break
- }
- delete(updateMap, *want.Id)
- }
- if len(updateMap) == 0 {
- return nil
- }
-
- return fmt.Errorf("Match failed; got %v, but wanted %v", updatesToDebugString(updates), adsToDebugString(wants))
-}
-
-func updateEqual(update mojom.Update, ad mojom.Advertisement) bool {
- if got, _ := update.GetId(); got != *ad.Id {
- return false
- }
- if got, _ := update.GetInterfaceName(); got != ad.InterfaceName {
- return false
- }
- if got, _ := update.GetAddresses(); !reflect.DeepEqual(got, ad.Addresses) {
- return false
- }
- if ad.Attributes != nil {
- for k, v := range *ad.Attributes {
- if got, _ := update.GetAttribute(k); got != v {
- return false
- }
- }
- }
- if ad.Attachments != nil {
- for k, v := range *ad.Attachments {
- h, err := update.GetAttachment(k)
- if err != nil {
- return false
- }
- defer h.Close()
- h.Wait(system.MOJO_HANDLE_SIGNAL_READABLE, system.MOJO_DEADLINE_INDEFINITE)
- r, got := h.ReadData(system.MOJO_READ_DATA_FLAG_ALL_OR_NONE)
- if r != system.MOJO_RESULT_OK {
- return false
- }
- if !bytes.Equal(got, v) {
- return false
- }
- }
- }
- if got, _ := update.GetAdvertisement(); !reflect.DeepEqual(got, ad) {
- return false
- }
- return true
-}
-
-func adsToDebugString(ads []mojom.Advertisement) string {
- var strs []string
- for _, ad := range ads {
- strs = append(strs, adToDebugString(ad))
- }
- return "[]" + strings.Join(strs, ", ") + "]"
-}
-
-func adToDebugString(ad mojom.Advertisement) string {
- return "{" + strings.Join(dumpFields(ad), ", ") + "}"
-}
-
-func updatesToDebugString(updates []mojom.Update) string {
- var strs []string
- for _, u := range updates {
- strs = append(strs, updateToDebugString(u))
- }
- return "[]" + strings.Join(strs, ", ") + "]"
-}
-
-func updateToDebugString(update mojom.Update) string {
- lost, _ := update.IsLost()
- ad, _ := update.GetAdvertisement()
- return fmt.Sprintf("{%v, %v}", lost, strings.Join(dumpFields(ad), ", "))
-}
-
-func dumpFields(i interface{}) []string {
- var fields []string
- for rv, i := reflect.ValueOf(i), 0; i < rv.NumField(); i++ {
- fields = append(fields, fmt.Sprint(rv.Field(i)))
- }
- return fields
-}
diff --git a/go/src/v.io/mojo/discovery/apptest/global_discovery_apptest.go b/go/src/v.io/mojo/discovery/apptest/global_discovery_apptest.go
new file mode 100644
index 0000000..6dabf9f
--- /dev/null
+++ b/go/src/v.io/mojo/discovery/apptest/global_discovery_apptest.go
@@ -0,0 +1,130 @@
+// Copyright 2016 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.
+
+// +build mojo
+
+package apptest
+
+import (
+ "encoding/hex"
+ "fmt"
+ "net/url"
+ "testing"
+ "time"
+
+ "mojo/public/go/application"
+ "mojo/public/go/bindings"
+
+ mojom "mojom/v.io/discovery"
+
+ _ "v.io/x/ref/runtime/factories/generic"
+
+ "v.io/mojo/discovery/internal"
+)
+
+// TODO(jhahn): Mojom 'const' is ignored in mojom.go.
+// See https://github.com/domokit/mojo/issues/685.
+const (
+ QueryGlobal = "global"
+ QueryMountTTL = "mount_ttl"
+ QueryScanInterval = "scan_interval"
+)
+
+func newGlobalDiscovery(mctx application.Context, scanInterval time.Duration) *mojom.Discovery_Proxy {
+ u, _ := url.Parse("https://mojo.v.io/discovery.mojo")
+ q := u.Query()
+ q.Set(QueryGlobal, "a/b/c")
+ q.Set(QueryScanInterval, fmt.Sprintf("%.3fs", scanInterval.Seconds()))
+ u.RawQuery = q.Encode()
+
+ req, ptr := mojom.CreateMessagePipeForDiscovery()
+ mctx.ConnectToApplication(u.String()).ConnectToService(&req)
+ return mojom.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
+}
+
+func AppTestGlobalDiscoveryBasic(t *testing.T, mctx application.Context) {
+ ads := []mojom.Advertisement{
+ {
+ Id: &[internal.AdIdLen]uint8{1, 2, 3},
+ Addresses: []string{"/h1:123/x"},
+ },
+ {
+ Addresses: []string{"/h1:123/y"},
+ },
+ }
+
+ d1 := newGlobalDiscovery(mctx, 0)
+ defer d1.Close_Proxy()
+
+ var stops []func()
+ for i, ad := range ads {
+ id, closer, e1, e2 := d1.Advertise(ad, nil)
+ if e1 != nil || e2 != nil {
+ t.Fatalf("ad[%d]: failed to advertise: %v, %v", i, e1, e2)
+ }
+ if id == nil {
+ t.Errorf("ad[%d]: got nil id", i)
+ continue
+ }
+ if ad.Id == nil {
+ ads[i].Id = id
+ } else if *id != *ad.Id {
+ t.Errorf("ad[%d]: got ad id %v, but wanted %v", i, *id, *ad.Id)
+ }
+
+ stop := func() {
+ p := mojom.NewCloserProxy(*closer, bindings.GetAsyncWaiter())
+ p.Close()
+ p.Close_Proxy()
+ }
+ stops = append(stops, stop)
+ }
+
+ // Make sure none of advertisements are discoverable by the same discovery instance.
+ if err := scanAndMatch(d1, ``); err != nil {
+ t.Error(err)
+ }
+
+ // Create a new discovery instance. All advertisements should be discovered with that.
+ d2 := newGlobalDiscovery(mctx, 1*time.Millisecond)
+ defer d2.Close_Proxy()
+
+ if err := scanAndMatch(d2, `k="01020300000000000000000000000000"`, ads[0]); err != nil {
+ t.Error(err)
+ }
+ if err := scanAndMatch(d2, ``, ads...); err != nil {
+ t.Error(err)
+ }
+
+ // Open a new scan channel and consume expected advertisements first.
+ scanCh, scanStop, err := scan(d2, `k="01020300000000000000000000000000"`)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer scanStop()
+
+ update := <-scanCh
+ if err := matchFound([]mojom.Update_Pointer{update}, ads[0]); err != nil {
+ t.Error(err)
+ }
+
+ // Make sure scan returns the lost advertisement when advertising is stopped.
+ stops[0]()
+
+ update = <-scanCh
+ if err := matchLost([]mojom.Update_Pointer{update}, ads[0]); err != nil {
+ t.Error(err)
+ }
+
+ // Also it shouldn't affect the other.
+ if err := scanAndMatch(d2, fmt.Sprintf(`k="%s"`, hex.EncodeToString(ads[1].Id[:])), ads[1]); err != nil {
+ t.Error(err)
+ }
+
+ // Stop advertising the remaining one; Shouldn't discover any advertisements.
+ stops[1]()
+ if err := scanAndMatch(d2, ``); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/go/src/v.io/mojo/discovery/discovery.go b/go/src/v.io/mojo/discovery/discovery.go
index 181f4cc..6006cbf 100644
--- a/go/src/v.io/mojo/discovery/discovery.go
+++ b/go/src/v.io/mojo/discovery/discovery.go
@@ -18,11 +18,13 @@
"v.io/v23"
"v.io/v23/context"
+ "v.io/v23/naming"
idiscovery "v.io/x/ref/lib/discovery"
fdiscovery "v.io/x/ref/lib/discovery/factory"
"v.io/x/ref/lib/discovery/plugins/mock"
"v.io/x/ref/runtime/factories/roaming"
+ "v.io/x/ref/services/mounttable/mounttablelib"
"v.io/mojo/discovery/internal"
)
@@ -31,7 +33,7 @@
import "C"
var (
- flagUseMock = flag.Bool("use-mock", false, "Use a mock plugin for mojo apptests.")
+ flagTestMode = flag.Bool("test-mode", false, "should only be true for apptests.")
)
type delegate struct {
@@ -50,21 +52,34 @@
roaming.SetArgs(mctx)
d.ctx, d.shutdown = v23.Init()
- if *flagUseMock {
+ if *flagTestMode {
+ // Inject a mock plugin.
df, _ := idiscovery.NewFactory(d.ctx, mock.New())
fdiscovery.InjectFactory(df)
+
+ // Start a mounttable and set the namespace roots.
+ name, _, err := mounttablelib.StartServers(d.ctx, v23.GetListenSpec(d.ctx), "", "", "", "", "mounttable")
+ if err != nil {
+ panic(err)
+ }
+ ns := v23.GetNamespace(d.ctx)
+ ns.SetRoots(name)
+ ns.CacheCtl(naming.DisableCache(true))
}
}
-func (d *delegate) Create(request mojom.Discovery_Request) {
- discovery := internal.NewDiscovery(d.ctx)
- stub := mojom.NewDiscoveryStub(request, discovery, bindings.GetAsyncWaiter())
+func (d *delegate) AcceptConnection(connection *application.Connection) {
+ f := &factory{d, connection.ConnectionURL()}
+ connection.ProvideServices(&mojom.Discovery_ServiceFactory{f})
+}
+
+func (d *delegate) run(stub *bindings.Stub, done func()) {
d.mu.Lock()
d.stubs[stub] = struct{}{}
d.mu.Unlock()
go func() {
- defer discovery.Close()
+ defer done()
for {
if err := stub.ServeRequest(); err != nil {
@@ -82,10 +97,6 @@
}()
}
-func (d *delegate) AcceptConnection(connection *application.Connection) {
- connection.ProvideServices(&mojom.Discovery_ServiceFactory{d})
-}
-
func (d *delegate) Quit() {
d.mu.Lock()
for stub := range d.stubs {
@@ -95,6 +106,22 @@
d.shutdown()
}
+type factory struct {
+ d *delegate
+ url string
+}
+
+func (f *factory) Create(request mojom.Discovery_Request) {
+ discovery, err := internal.NewDiscovery(f.d.ctx, f.url)
+ if err != nil {
+ f.d.ctx.Error(err)
+ request.Close()
+ return
+ }
+ stub := mojom.NewDiscoveryStub(request, discovery, bindings.GetAsyncWaiter())
+ f.d.run(stub, discovery.Close)
+}
+
//export MojoMain
func MojoMain(handle C.MojoHandle) C.MojoResult {
application.Run(&delegate{stubs: map[*bindings.Stub]struct{}{}}, system.MojoHandle(handle))
diff --git a/go/src/v.io/mojo/discovery/internal/discovery.go b/go/src/v.io/mojo/discovery/internal/discovery.go
index 17f5056..b6a900d 100644
--- a/go/src/v.io/mojo/discovery/internal/discovery.go
+++ b/go/src/v.io/mojo/discovery/internal/discovery.go
@@ -5,7 +5,9 @@
package internal
import (
+ "net/url"
"sync"
+ "time"
"mojo/public/go/bindings"
@@ -14,11 +16,19 @@
"v.io/v23"
"v.io/v23/context"
"v.io/v23/discovery"
+
+ "v.io/x/ref/lib/discovery/global"
)
// TODO(jhahn): Mojom 'const' is ignored in mojom.go.
// See https://github.com/domokit/mojo/issues/685.
-const AdIdLen = 16
+const (
+ AdIdLen = 16
+
+ QueryGlobal = "global"
+ QueryMountTTL = "mount_ttl"
+ QueryScanInterval = "scan_interval"
+)
// closer implements the mojom.Closer.
type closer struct {
@@ -30,7 +40,7 @@
return nil
}
-type discoveryCloser interface {
+type DiscoveryCloser interface {
mojom.Discovery
// Close closes all active tasks.
@@ -141,29 +151,47 @@
}
}
-// ediscovery always returns the given error.
-type ediscovery struct{ err error }
-
-func (d *ediscovery) Advertise(mojom.Advertisement, *[]string) (*[AdIdLen]uint8, *mojom.Closer_Pointer, *mojom.Error, error) {
- return nil, nil, v2mError(d.err), nil
-}
-func (d *ediscovery) Scan(string, mojom.ScanHandler_Pointer) (*mojom.Closer_Pointer, *mojom.Error, error) {
- return nil, v2mError(d.err), nil
-}
-func (d *ediscovery) Close() {}
-
// NewDiscovery returns a new Vanadium discovery instance.
-func NewDiscovery(ctx *context.T) discoveryCloser {
- d, err := v23.NewDiscovery(ctx)
+func NewDiscovery(ctx *context.T, connectionUrl string) (DiscoveryCloser, error) {
+ d, err := newDiscovery(ctx, connectionUrl)
if err != nil {
- return &ediscovery{err}
+ return nil, err
}
ctx, cancel := context.WithCancel(ctx)
- return &mdiscovery{
+ md := &mdiscovery{
ctx: ctx,
cancel: cancel,
d: d,
stubs: make(map[*bindings.Stub]struct{}),
}
+ return md, nil
+}
+
+func newDiscovery(ctx *context.T, connectionUrl string) (discovery.T, error) {
+ u, err := url.ParseRequestURI(connectionUrl)
+ if err != nil {
+ return nil, err
+ }
+
+ q := u.Query()
+ if _, ok := q[QueryGlobal]; ok {
+ mountTTL, err := parseDuration(q.Get(QueryMountTTL))
+ if err != nil {
+ return nil, err
+ }
+ scanInterval, err := parseDuration(q.Get(QueryScanInterval))
+ if err != nil {
+ return nil, err
+ }
+ return global.NewWithTTL(ctx, q.Get(QueryGlobal), mountTTL, scanInterval)
+ }
+ return v23.NewDiscovery(ctx)
+}
+
+func parseDuration(s string) (time.Duration, error) {
+ if len(s) == 0 {
+ return 0, nil
+ }
+ return time.ParseDuration(s)
}
diff --git a/java/app/build.gradle b/java/app/build.gradle
index 1a63fbf..160b242 100644
--- a/java/app/build.gradle
+++ b/java/app/build.gradle
@@ -64,7 +64,7 @@
}
dependencies {
- compile 'io.v:vanadium-android:1.11+'
+ compile 'io.v:vanadium-android:1.12+'
compile 'com.android.support:multidex:1.0.0'
// Mojo system should not be included in binary.
diff --git a/java/app/src/main/java/io/v/mojo/discovery/DiscoveryApp.java b/java/app/src/main/java/io/v/mojo/discovery/DiscoveryApp.java
index 83433d1..62cbd18 100644
--- a/java/app/src/main/java/io/v/mojo/discovery/DiscoveryApp.java
+++ b/java/app/src/main/java/io/v/mojo/discovery/DiscoveryApp.java
@@ -7,6 +7,10 @@
import android.content.Context;
import android.util.Log;
+import com.google.common.collect.ImmutableList;
+
+import java.io.File;
+
import org.chromium.mojo.application.ApplicationConnection;
import org.chromium.mojo.application.ApplicationDelegate;
import org.chromium.mojo.application.ApplicationRunner;
@@ -18,9 +22,9 @@
import io.v.android.v23.V;
import io.v.v23.context.VContext;
-import io.v.v23.verror.VException;
import io.v.impl.google.lib.discovery.FactoryUtil;
+import io.v.impl.google.services.mounttable.MountTableServer;
/**
* Android mojo application providing the vanadium discovery service.
@@ -29,20 +33,39 @@
static final String TAG = "DiscoveryApp";
private final Core mCore;
- private final VContext mContext;
+ private VContext mContext;
+
+ private File mCacheDir;
DiscoveryApp(Core core, Context context) {
mCore = core;
mContext = V.init(context);
+
+ // TODO(jhahn): MountTableServer always requires a storage directory for now.
+ // Remove this once this bug is fixed.
+ mCacheDir = context.getCacheDir();
}
@Override
public void initialize(Shell shell, String[] args, String url) {
for (String arg : args) {
- if (arg.matches("-{1,2}use-mock")) {
+ if (arg.matches("-{1,2}test-mode")) {
try {
+ // Inject a mock plugin.
FactoryUtil.injectMockPlugin(mContext);
- } catch (VException e) {
+
+ // Start a mounttable and set the namespace roots.
+ File storageRoot = new File(mCacheDir, "mounttable");
+ storageRoot.mkdirs();
+ mContext =
+ MountTableServer.withNewServer(
+ mContext,
+ new MountTableServer.Params()
+ .withStatsPrefix("mounttable")
+ .withStorageRootDir(storageRoot.getAbsolutePath()));
+ String name = V.getServer(mContext).getStatus().getEndpoints()[0].name();
+ V.getNamespace(mContext).setRoots(ImmutableList.of(name));
+ } catch (Exception e) {
Log.e(TAG, e.toString());
}
break;
@@ -51,14 +74,17 @@
}
@Override
- public boolean configureIncomingConnection(ApplicationConnection applicationConnection) {
+ public boolean configureIncomingConnection(final ApplicationConnection applicationConnection) {
applicationConnection.addService(
new ServiceFactoryBinder<Discovery>() {
@Override
public void bind(InterfaceRequest<Discovery> request) {
try {
- Discovery.MANAGER.bind(new DiscoveryImpl(mCore, mContext), request);
- } catch (VException e) {
+ Discovery.MANAGER.bind(
+ new DiscoveryImpl(
+ mCore, mContext, applicationConnection.connectionUrl()),
+ request);
+ } catch (Exception e) {
Log.e(TAG, e.toString());
request.close();
}
diff --git a/java/app/src/main/java/io/v/mojo/discovery/DiscoveryImpl.java b/java/app/src/main/java/io/v/mojo/discovery/DiscoveryImpl.java
index 134ac89..406e4e4 100644
--- a/java/app/src/main/java/io/v/mojo/discovery/DiscoveryImpl.java
+++ b/java/app/src/main/java/io/v/mojo/discovery/DiscoveryImpl.java
@@ -4,6 +4,8 @@
package io.v.mojo.discovery;
+import android.net.Uri;
+
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
@@ -12,6 +14,11 @@
import org.chromium.mojo.system.Core;
import org.chromium.mojo.system.MojoException;
import org.chromium.mojo.system.RunLoop;
+import org.joda.time.DateTimeZone;
+import org.joda.time.Duration;
+import org.joda.time.format.PeriodFormatter;
+import org.joda.time.format.PeriodFormatterBuilder;
+import org.joda.time.tz.UTCProvider;
import io.v.android.v23.V;
import io.v.v23.InputChannelCallback;
@@ -20,15 +27,34 @@
import io.v.v23.security.BlessingPattern;
import io.v.v23.verror.VException;
+import io.v.impl.google.lib.discovery.GlobalDiscovery;
+
class DiscoveryImpl implements Discovery {
private final Core mCore;
private final VContext mContext;
private final io.v.v23.discovery.Discovery mDiscovery;
- DiscoveryImpl(Core core, VContext context) throws VException {
+ static {
+ // TODO(jhahn): To avoid IOException: 'Resource not found: "org/joda/time/tz/data/ZoneInfoMap"'
+ // Load resources or find other way to parse duration strings.
+ DateTimeZone.setProvider(new UTCProvider());
+ }
+
+ DiscoveryImpl(Core core, VContext context, String connectionUrl) throws Exception {
mCore = core;
mContext = context.withCancel();
- mDiscovery = V.newDiscovery(mContext);
+
+ Uri uri = Uri.parse(connectionUrl);
+ String global = uri.getQueryParameter(DiscoveryConstants.QUERY_GLOBAL);
+ if (global != null) {
+ Duration mountTTL =
+ parseDuration(uri.getQueryParameter(DiscoveryConstants.QUERY_MOUNT_TTL));
+ Duration scanInterval =
+ parseDuration(uri.getQueryParameter(DiscoveryConstants.QUERY_SCAN_INTERVAL));
+ mDiscovery = GlobalDiscovery.newDiscovery(mContext, global, mountTTL, scanInterval);
+ } else {
+ mDiscovery = V.newDiscovery(mContext);
+ }
}
private static class CloserImpl implements Closer {
@@ -76,6 +102,22 @@
public void onConnectionError(MojoException e) {}
}
+ private static Duration parseDuration(String duration) {
+ if (duration == null || duration.equals("0")) {
+ return Duration.ZERO;
+ }
+ PeriodFormatter formatter =
+ new PeriodFormatterBuilder()
+ .appendHours()
+ .appendSuffix("h")
+ .appendMinutes()
+ .appendSuffix("m")
+ .appendSecondsWithOptionalMillis()
+ .appendSuffix("s")
+ .toFormatter();
+ return formatter.parsePeriod(duration).toStandardDuration();
+ }
+
@Override
public void advertise(Advertisement ad, String[] visibility, AdvertiseResponse callback) {
try {
diff --git a/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart b/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart
index 827cac0..ab497bb 100644
--- a/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart
+++ b/lib/gen/dart-gen/mojom/lib/discovery/discovery.mojom.dart
@@ -7,6 +7,9 @@
import 'package:mojo/bindings.dart' as bindings;
import 'package:mojo/core.dart' as core;
import 'package:mojo/mojo/bindings/types/service_describer.mojom.dart' as service_describer;
+const String queryGlobal = "global";
+const String queryMountTtl = "mount_ttl";
+const String queryScanInterval = "scan_interval";
@@ -1870,8 +1873,8 @@
}
}
-const int _Discovery_advertiseName = 0;
-const int _Discovery_scanName = 1;
+const int _discoveryMethodAdvertiseName = 0;
+const int _discoveryMethodScanName = 1;
class _DiscoveryServiceDescription implements service_describer.ServiceDescription {
dynamic getTopLevelInterface([Function responseFactory]) =>
@@ -1911,7 +1914,7 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
- case _Discovery_advertiseName:
+ case _discoveryMethodAdvertiseName:
var r = DiscoveryAdvertiseResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -1931,7 +1934,7 @@
}
c.complete(r);
break;
- case _Discovery_scanName:
+ case _discoveryMethodScanName:
var r = DiscoveryScanResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -1975,7 +1978,7 @@
params.visibility = visibility;
return _proxyImpl.sendMessageWithRequestId(
params,
- _Discovery_advertiseName,
+ _discoveryMethodAdvertiseName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -1985,7 +1988,7 @@
params.handler = handler;
return _proxyImpl.sendMessageWithRequestId(
params,
- _Discovery_scanName,
+ _discoveryMethodScanName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2070,18 +2073,18 @@
}
- DiscoveryAdvertiseResponseParams _DiscoveryAdvertiseResponseParamsFactory(List<int> instanceId, Object closer, Error err) {
- var mojo_factory_result = new DiscoveryAdvertiseResponseParams();
- mojo_factory_result.instanceId = instanceId;
- mojo_factory_result.closer = closer;
- mojo_factory_result.err = err;
- return mojo_factory_result;
+ DiscoveryAdvertiseResponseParams _discoveryAdvertiseResponseParamsFactory(List<int> instanceId, Object closer, Error err) {
+ var result = new DiscoveryAdvertiseResponseParams();
+ result.instanceId = instanceId;
+ result.closer = closer;
+ result.err = err;
+ return result;
}
- DiscoveryScanResponseParams _DiscoveryScanResponseParamsFactory(Object closer, Error err) {
- var mojo_factory_result = new DiscoveryScanResponseParams();
- mojo_factory_result.closer = closer;
- mojo_factory_result.err = err;
- return mojo_factory_result;
+ DiscoveryScanResponseParams _discoveryScanResponseParamsFactory(Object closer, Error err) {
+ var result = new DiscoveryScanResponseParams();
+ result.closer = closer;
+ result.err = err;
+ return result;
}
dynamic handleMessage(bindings.ServiceMessage message) {
@@ -2092,16 +2095,16 @@
}
assert(_impl != null);
switch (message.header.type) {
- case _Discovery_advertiseName:
+ case _discoveryMethodAdvertiseName:
var params = _DiscoveryAdvertiseParams.deserialize(
message.payload);
- var response = _impl.advertise(params.ad,params.visibility,_DiscoveryAdvertiseResponseParamsFactory);
+ var response = _impl.advertise(params.ad,params.visibility,_discoveryAdvertiseResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Discovery_advertiseName,
+ _discoveryMethodAdvertiseName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -2109,21 +2112,21 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Discovery_advertiseName,
+ _discoveryMethodAdvertiseName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
break;
- case _Discovery_scanName:
+ case _discoveryMethodScanName:
var params = _DiscoveryScanParams.deserialize(
message.payload);
- var response = _impl.scan(params.query,params.handler,_DiscoveryScanResponseParamsFactory);
+ var response = _impl.scan(params.query,params.handler,_discoveryScanResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Discovery_scanName,
+ _discoveryMethodScanName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -2131,7 +2134,7 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Discovery_scanName,
+ _discoveryMethodScanName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -2165,7 +2168,7 @@
}
}
-const int _Closer_closeName = 0;
+const int _closerMethodCloseName = 0;
class _CloserServiceDescription implements service_describer.ServiceDescription {
dynamic getTopLevelInterface([Function responseFactory]) =>
@@ -2204,7 +2207,7 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
- case _Closer_closeName:
+ case _closerMethodCloseName:
var r = CloserCloseResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2246,7 +2249,7 @@
var params = new _CloserCloseParams();
return _proxyImpl.sendMessageWithRequestId(
params,
- _Closer_closeName,
+ _closerMethodCloseName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2331,9 +2334,9 @@
}
- CloserCloseResponseParams _CloserCloseResponseParamsFactory() {
- var mojo_factory_result = new CloserCloseResponseParams();
- return mojo_factory_result;
+ CloserCloseResponseParams _closerCloseResponseParamsFactory() {
+ var result = new CloserCloseResponseParams();
+ return result;
}
dynamic handleMessage(bindings.ServiceMessage message) {
@@ -2344,14 +2347,14 @@
}
assert(_impl != null);
switch (message.header.type) {
- case _Closer_closeName:
- var response = _impl.close(_CloserCloseResponseParamsFactory);
+ case _closerMethodCloseName:
+ var response = _impl.close(_closerCloseResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Closer_closeName,
+ _closerMethodCloseName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -2359,7 +2362,7 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Closer_closeName,
+ _closerMethodCloseName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -2393,7 +2396,7 @@
}
}
-const int _ScanHandler_onUpdateName = 0;
+const int _scanHandlerMethodOnUpdateName = 0;
class _ScanHandlerServiceDescription implements service_describer.ServiceDescription {
dynamic getTopLevelInterface([Function responseFactory]) =>
@@ -2457,7 +2460,7 @@
}
var params = new _ScanHandlerOnUpdateParams();
params.update = update;
- _proxyImpl.sendMessage(params, _ScanHandler_onUpdateName);
+ _proxyImpl.sendMessage(params, _scanHandlerMethodOnUpdateName);
}
}
@@ -2549,7 +2552,7 @@
}
assert(_impl != null);
switch (message.header.type) {
- case _ScanHandler_onUpdateName:
+ case _scanHandlerMethodOnUpdateName:
var params = _ScanHandlerOnUpdateParams.deserialize(
message.payload);
_impl.onUpdate(params.update);
@@ -2583,13 +2586,13 @@
}
}
-const int _Update_isLostName = 0;
-const int _Update_getIdName = 1;
-const int _Update_getInterfaceNameName = 2;
-const int _Update_getAddressesName = 3;
-const int _Update_getAttributeName = 4;
-const int _Update_getAttachmentName = 5;
-const int _Update_getAdvertisementName = 6;
+const int _updateMethodIsLostName = 0;
+const int _updateMethodGetIdName = 1;
+const int _updateMethodGetInterfaceNameName = 2;
+const int _updateMethodGetAddressesName = 3;
+const int _updateMethodGetAttributeName = 4;
+const int _updateMethodGetAttachmentName = 5;
+const int _updateMethodGetAdvertisementName = 6;
class _UpdateServiceDescription implements service_describer.ServiceDescription {
dynamic getTopLevelInterface([Function responseFactory]) =>
@@ -2634,7 +2637,7 @@
void handleResponse(bindings.ServiceMessage message) {
switch (message.header.type) {
- case _Update_isLostName:
+ case _updateMethodIsLostName:
var r = UpdateIsLostResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2654,7 +2657,7 @@
}
c.complete(r);
break;
- case _Update_getIdName:
+ case _updateMethodGetIdName:
var r = UpdateGetIdResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2674,7 +2677,7 @@
}
c.complete(r);
break;
- case _Update_getInterfaceNameName:
+ case _updateMethodGetInterfaceNameName:
var r = UpdateGetInterfaceNameResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2694,7 +2697,7 @@
}
c.complete(r);
break;
- case _Update_getAddressesName:
+ case _updateMethodGetAddressesName:
var r = UpdateGetAddressesResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2714,7 +2717,7 @@
}
c.complete(r);
break;
- case _Update_getAttributeName:
+ case _updateMethodGetAttributeName:
var r = UpdateGetAttributeResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2734,7 +2737,7 @@
}
c.complete(r);
break;
- case _Update_getAttachmentName:
+ case _updateMethodGetAttachmentName:
var r = UpdateGetAttachmentResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2754,7 +2757,7 @@
}
c.complete(r);
break;
- case _Update_getAdvertisementName:
+ case _updateMethodGetAdvertisementName:
var r = UpdateGetAdvertisementResponseParams.deserialize(
message.payload);
if (!message.header.hasRequestId) {
@@ -2796,7 +2799,7 @@
var params = new _UpdateIsLostParams();
return _proxyImpl.sendMessageWithRequestId(
params,
- _Update_isLostName,
+ _updateMethodIsLostName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2804,7 +2807,7 @@
var params = new _UpdateGetIdParams();
return _proxyImpl.sendMessageWithRequestId(
params,
- _Update_getIdName,
+ _updateMethodGetIdName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2812,7 +2815,7 @@
var params = new _UpdateGetInterfaceNameParams();
return _proxyImpl.sendMessageWithRequestId(
params,
- _Update_getInterfaceNameName,
+ _updateMethodGetInterfaceNameName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2820,7 +2823,7 @@
var params = new _UpdateGetAddressesParams();
return _proxyImpl.sendMessageWithRequestId(
params,
- _Update_getAddressesName,
+ _updateMethodGetAddressesName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2829,7 +2832,7 @@
params.name = name;
return _proxyImpl.sendMessageWithRequestId(
params,
- _Update_getAttributeName,
+ _updateMethodGetAttributeName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2838,7 +2841,7 @@
params.name = name;
return _proxyImpl.sendMessageWithRequestId(
params,
- _Update_getAttachmentName,
+ _updateMethodGetAttachmentName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2846,7 +2849,7 @@
var params = new _UpdateGetAdvertisementParams();
return _proxyImpl.sendMessageWithRequestId(
params,
- _Update_getAdvertisementName,
+ _updateMethodGetAdvertisementName,
-1,
bindings.MessageHeader.kMessageExpectsResponse);
}
@@ -2931,40 +2934,40 @@
}
- UpdateIsLostResponseParams _UpdateIsLostResponseParamsFactory(bool lost) {
- var mojo_factory_result = new UpdateIsLostResponseParams();
- mojo_factory_result.lost = lost;
- return mojo_factory_result;
+ UpdateIsLostResponseParams _updateIsLostResponseParamsFactory(bool lost) {
+ var result = new UpdateIsLostResponseParams();
+ result.lost = lost;
+ return result;
}
- UpdateGetIdResponseParams _UpdateGetIdResponseParamsFactory(List<int> id) {
- var mojo_factory_result = new UpdateGetIdResponseParams();
- mojo_factory_result.id = id;
- return mojo_factory_result;
+ UpdateGetIdResponseParams _updateGetIdResponseParamsFactory(List<int> id) {
+ var result = new UpdateGetIdResponseParams();
+ result.id = id;
+ return result;
}
- UpdateGetInterfaceNameResponseParams _UpdateGetInterfaceNameResponseParamsFactory(String interfaceName) {
- var mojo_factory_result = new UpdateGetInterfaceNameResponseParams();
- mojo_factory_result.interfaceName = interfaceName;
- return mojo_factory_result;
+ UpdateGetInterfaceNameResponseParams _updateGetInterfaceNameResponseParamsFactory(String interfaceName) {
+ var result = new UpdateGetInterfaceNameResponseParams();
+ result.interfaceName = interfaceName;
+ return result;
}
- UpdateGetAddressesResponseParams _UpdateGetAddressesResponseParamsFactory(List<String> addresses) {
- var mojo_factory_result = new UpdateGetAddressesResponseParams();
- mojo_factory_result.addresses = addresses;
- return mojo_factory_result;
+ UpdateGetAddressesResponseParams _updateGetAddressesResponseParamsFactory(List<String> addresses) {
+ var result = new UpdateGetAddressesResponseParams();
+ result.addresses = addresses;
+ return result;
}
- UpdateGetAttributeResponseParams _UpdateGetAttributeResponseParamsFactory(String attribute) {
- var mojo_factory_result = new UpdateGetAttributeResponseParams();
- mojo_factory_result.attribute = attribute;
- return mojo_factory_result;
+ UpdateGetAttributeResponseParams _updateGetAttributeResponseParamsFactory(String attribute) {
+ var result = new UpdateGetAttributeResponseParams();
+ result.attribute = attribute;
+ return result;
}
- UpdateGetAttachmentResponseParams _UpdateGetAttachmentResponseParamsFactory(core.MojoDataPipeConsumer data) {
- var mojo_factory_result = new UpdateGetAttachmentResponseParams();
- mojo_factory_result.data = data;
- return mojo_factory_result;
+ UpdateGetAttachmentResponseParams _updateGetAttachmentResponseParamsFactory(core.MojoDataPipeConsumer data) {
+ var result = new UpdateGetAttachmentResponseParams();
+ result.data = data;
+ return result;
}
- UpdateGetAdvertisementResponseParams _UpdateGetAdvertisementResponseParamsFactory(Advertisement ad) {
- var mojo_factory_result = new UpdateGetAdvertisementResponseParams();
- mojo_factory_result.ad = ad;
- return mojo_factory_result;
+ UpdateGetAdvertisementResponseParams _updateGetAdvertisementResponseParamsFactory(Advertisement ad) {
+ var result = new UpdateGetAdvertisementResponseParams();
+ result.ad = ad;
+ return result;
}
dynamic handleMessage(bindings.ServiceMessage message) {
@@ -2975,14 +2978,14 @@
}
assert(_impl != null);
switch (message.header.type) {
- case _Update_isLostName:
- var response = _impl.isLost(_UpdateIsLostResponseParamsFactory);
+ case _updateMethodIsLostName:
+ var response = _impl.isLost(_updateIsLostResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Update_isLostName,
+ _updateMethodIsLostName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -2990,19 +2993,19 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Update_isLostName,
+ _updateMethodIsLostName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
break;
- case _Update_getIdName:
- var response = _impl.getId(_UpdateGetIdResponseParamsFactory);
+ case _updateMethodGetIdName:
+ var response = _impl.getId(_updateGetIdResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Update_getIdName,
+ _updateMethodGetIdName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -3010,19 +3013,19 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Update_getIdName,
+ _updateMethodGetIdName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
break;
- case _Update_getInterfaceNameName:
- var response = _impl.getInterfaceName(_UpdateGetInterfaceNameResponseParamsFactory);
+ case _updateMethodGetInterfaceNameName:
+ var response = _impl.getInterfaceName(_updateGetInterfaceNameResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Update_getInterfaceNameName,
+ _updateMethodGetInterfaceNameName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -3030,19 +3033,19 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Update_getInterfaceNameName,
+ _updateMethodGetInterfaceNameName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
break;
- case _Update_getAddressesName:
- var response = _impl.getAddresses(_UpdateGetAddressesResponseParamsFactory);
+ case _updateMethodGetAddressesName:
+ var response = _impl.getAddresses(_updateGetAddressesResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Update_getAddressesName,
+ _updateMethodGetAddressesName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -3050,21 +3053,21 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Update_getAddressesName,
+ _updateMethodGetAddressesName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
break;
- case _Update_getAttributeName:
+ case _updateMethodGetAttributeName:
var params = _UpdateGetAttributeParams.deserialize(
message.payload);
- var response = _impl.getAttribute(params.name,_UpdateGetAttributeResponseParamsFactory);
+ var response = _impl.getAttribute(params.name,_updateGetAttributeResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Update_getAttributeName,
+ _updateMethodGetAttributeName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -3072,21 +3075,21 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Update_getAttributeName,
+ _updateMethodGetAttributeName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
break;
- case _Update_getAttachmentName:
+ case _updateMethodGetAttachmentName:
var params = _UpdateGetAttachmentParams.deserialize(
message.payload);
- var response = _impl.getAttachment(params.name,_UpdateGetAttachmentResponseParamsFactory);
+ var response = _impl.getAttachment(params.name,_updateGetAttachmentResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Update_getAttachmentName,
+ _updateMethodGetAttachmentName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -3094,19 +3097,19 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Update_getAttachmentName,
+ _updateMethodGetAttachmentName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
break;
- case _Update_getAdvertisementName:
- var response = _impl.getAdvertisement(_UpdateGetAdvertisementResponseParamsFactory);
+ case _updateMethodGetAdvertisementName:
+ var response = _impl.getAdvertisement(_updateGetAdvertisementResponseParamsFactory);
if (response is Future) {
return response.then((response) {
if (response != null) {
return buildResponseWithId(
response,
- _Update_getAdvertisementName,
+ _updateMethodGetAdvertisementName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
@@ -3114,7 +3117,7 @@
} else if (response != null) {
return buildResponseWithId(
response,
- _Update_getAdvertisementName,
+ _updateMethodGetAdvertisementName,
message.header.requestId,
bindings.MessageHeader.kMessageIsResponse);
}
diff --git a/mojoapptests b/mojoapptests
index 88c0b2f..992d966 100644
--- a/mojoapptests
+++ b/mojoapptests
@@ -5,7 +5,7 @@
{
"test": "https://test.v.io/discovery_apptests.mojo",
"test-args": [],
- "shell-args": ["--args-for=https://mojo.v.io/discovery.mojo --use-mock"],
+ "shell-args": ["--args-for=https://mojo.v.io/discovery.mojo --test-mode"],
"timeout": 120,
},
# Testing dart apptests timeout failure with a large timeout value.
@@ -14,7 +14,7 @@
"test": "https://dart.test.mojo.v.io/discovery_apptests.dart",
"type": "dart",
"dart_strict_mode": True,
- "shell-args": ["--args-for=https://mojo.v.io/discovery.mojo --use-mock"],
- "timeout": 1200,
+ "shell-args": ["--args-for=https://mojo.v.io/discovery.mojo --test-mode"],
+ "timeout": 120,
}
]
diff --git a/mojom/v.io/discovery.mojom b/mojom/v.io/discovery.mojom
index 41786cb..12f60bd 100644
--- a/mojom/v.io/discovery.mojom
+++ b/mojom/v.io/discovery.mojom
@@ -53,7 +53,23 @@
string msg;
};
+// Url query parameters for global discovery service.
+const string QUERY_GLOBAL = "global";
+const string QUERY_MOUNT_TTL = "mount_ttl";
+const string QUERY_SCAN_INTERVAL = "scan_interval";
+
// Discovery provides Vanadium discovery service.
+//
+// Global discovery:
+// You can connect to a global discovery service that uses the Vanadium namespace
+// under |path| by passing a query string "global=<path>". Optionally you can
+// set |mount_ttl| (default is 120s) and |scan_interval| (default is 90s) with
+// query strings "mount_ttl=<mount_ttl>" and "scan_interval=<scan_interval>".
+// A duration string is a sequence of decimal numbers, each with a unit suffix,
+// such as "90s" or "1m30s". Valid time units are "s", "m", and "h".
+//
+// Global discovery is an experimental work to see its feasibility and set the
+// long-term goal, and can be changed without notice.
[ServiceName="v23::discovery::Discovery"]
interface Discovery {
// Broadcasts the advertisement to be discovered by |Scan| operations.