Move syncbase discovery to the ref repo.

This change also includes the chnage in:
https://vanadium-review.googlesource.com/#/c/22812/

Please see that change for details.

MultiPart: 1/2
Change-Id: I3fdfbe27cfdbb4fc8beb91f7401d59a46d18c850
diff --git a/syncbase/.api b/syncbase/.api
index 78e1422..ecea5e1 100644
--- a/syncbase/.api
+++ b/syncbase/.api
@@ -1,6 +1,5 @@
 pkg syncbase, const DeleteChange ChangeType
 pkg syncbase, const PutChange ChangeType
-pkg syncbase, func NewDiscovery(*context.T) (discovery.T, error)
 pkg syncbase, func NewService(string) Service
 pkg syncbase, func NewValue(*context.T, interface{}) (*Value, error)
 pkg syncbase, func Prefix(string) PrefixRange
@@ -13,8 +12,6 @@
 pkg syncbase, method (*ConflictRow) VDLRead(vdl.Decoder) error
 pkg syncbase, method (*ConflictRowSet) VDLRead(vdl.Decoder) error
 pkg syncbase, method (*ConflictScanSet) VDLRead(vdl.Decoder) error
-pkg syncbase, method (*Discovery) Advertise(*context.T, *discovery.Advertisement, []security.BlessingPattern) (<-chan struct{}, error)
-pkg syncbase, method (*Discovery) Scan(*context.T, string) (<-chan discovery.Update, error)
 pkg syncbase, method (*Resolution) VDLRead(vdl.Decoder) error
 pkg syncbase, method (*ResolvedRow) VDLRead(vdl.Decoder) error
 pkg syncbase, method (*Value) Get(interface{}) error
@@ -131,7 +128,6 @@
 pkg syncbase, type DatabaseHandle interface, GetResumeMarker(*context.T) (watch.ResumeMarker, error)
 pkg syncbase, type DatabaseHandle interface, Id() wire.Id
 pkg syncbase, type DatabaseHandle interface, ListCollections(*context.T) ([]wire.Id, error)
-pkg syncbase, type Discovery struct
 pkg syncbase, type PrefixRange interface { Limit, Prefix, Start }
 pkg syncbase, type PrefixRange interface, Limit() string
 pkg syncbase, type PrefixRange interface, Prefix() string
diff --git a/syncbase/discovery.go b/syncbase/discovery.go
deleted file mode 100644
index 3ec1f6a..0000000
--- a/syncbase/discovery.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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.
-
-package syncbase
-
-import (
-	"strings"
-
-	"v.io/v23"
-	"v.io/v23/context"
-	"v.io/v23/discovery"
-	"v.io/v23/security"
-)
-
-const visibilityKey = "vis"
-
-// Discovery implements v.io/v23/discovery.T for syncbase based
-// applications.
-// TODO(mattr): Actually this is not syncbase specific.  At some
-// point we should just replace the result of v23.NewDiscovery
-// with this.
-type Discovery struct {
-	nhDiscovery discovery.T
-	// TODO(mattr): Add global discovery.
-}
-
-// NewDiscovery creates a new syncbase discovery object.
-func NewDiscovery(ctx *context.T) (discovery.T, error) {
-	nhDiscovery, err := v23.NewDiscovery(ctx)
-	if err != nil {
-		return nil, err
-	}
-	return &Discovery{nhDiscovery: nhDiscovery}, nil
-}
-
-// Scan implements v.io/v23/discovery/T.Scan.
-func (d *Discovery) Scan(ctx *context.T, query string) (<-chan discovery.Update, error) {
-	nhUpdates, err := d.nhDiscovery.Scan(ctx, query)
-	if err != nil {
-		return nil, err
-	}
-
-	// Currently setting visibility on the neighborhood discovery
-	// service turns IBE encryption on.  We currently don't have the
-	// infrastructure support for IBE, so that would make our advertisements
-	// unreadable by everyone.
-	// Instead we add the visibility list to the attributes of the advertisement
-	// and filter on the client side.  This is a temporary measure until
-	// IBE is set up.  See v.io/i/1345.
-	updates := make(chan discovery.Update)
-	go func() {
-		for u := range nhUpdates {
-			patterns := splitPatterns(u.Attribute(visibilityKey))
-			if len(patterns) > 0 && !matchesPatterns(ctx, patterns) {
-				continue
-			}
-			updates <- update{u}
-		}
-		close(updates)
-	}()
-
-	return updates, nil
-}
-
-// Advertise implements v.io/v23/discovery/T.Advertise.
-func (d *Discovery) Advertise(ctx *context.T, ad *discovery.Advertisement, visibility []security.BlessingPattern) (<-chan struct{}, error) {
-	// Currently setting visibility on the neighborhood discovery
-	// service turns IBE encryption on.  We currently don't have the
-	// infrastructure support for IBE, so that would make our advertisements
-	// unreadable by everyone.
-	// Instead we add the visibility list to the attributes of the advertisement
-	// and filter on the client side.  This is a temporary measure until
-	// IBE is set up.  See v.io/i/1345.
-	adCopy := *ad
-	if len(visibility) > 0 {
-		adCopy.Attributes = make(discovery.Attributes, len(ad.Attributes)+1)
-		for k, v := range ad.Attributes {
-			adCopy.Attributes[k] = v
-		}
-		patterns := joinPatterns(visibility)
-		adCopy.Attributes[visibilityKey] = patterns
-	}
-	ch, err := d.nhDiscovery.Advertise(ctx, &adCopy, nil)
-	ad.Id = adCopy.Id
-	return ch, err
-}
-
-func matchesPatterns(ctx *context.T, patterns []security.BlessingPattern) bool {
-	p := v23.GetPrincipal(ctx)
-	blessings := p.BlessingStore().PeerBlessings()
-	for _, b := range blessings {
-		names := security.BlessingNames(p, b)
-		for _, pattern := range patterns {
-			if pattern.MatchedBy(names...) {
-				return true
-			}
-		}
-	}
-	return false
-}
-
-// update wraps the discovery.Update to remove the visibility attribute which we add.
-type update struct {
-	discovery.Update
-}
-
-func (u update) Attribute(name string) string {
-	if name == visibilityKey {
-		return ""
-	}
-	return u.Update.Attribute(name)
-}
-
-func (u update) Advertisement() discovery.Advertisement {
-	cp := u.Update.Advertisement()
-	orig := cp.Attributes
-	cp.Attributes = make(discovery.Attributes, len(orig))
-	for k, v := range orig {
-		if k != visibilityKey {
-			cp.Attributes[k] = v
-		}
-	}
-	return cp
-}
-
-// blessingSeparator is used to join multiple blessings into a
-// single string.
-// Note that comma cannot appear in blessings, see:
-// v.io/v23/security/certificate.go
-const blessingsSeparator = ','
-
-// joinPatterns concatenates the elements of a to create a single string.
-// The string can be split again with SplitPatterns.
-func joinPatterns(a []security.BlessingPattern) string {
-	if len(a) == 0 {
-		return ""
-	}
-	if len(a) == 1 {
-		return string(a[0])
-	}
-	n := (len(a) - 1)
-	for i := 0; i < len(a); i++ {
-		n += len(a[i])
-	}
-
-	b := make([]byte, n)
-	bp := copy(b, a[0])
-	for _, s := range a[1:] {
-		b[bp] = blessingsSeparator
-		bp++
-		bp += copy(b[bp:], s)
-	}
-	return string(b)
-}
-
-// splitPatterns splits BlessingPatterns that were joined with
-// JoinBlessingPattern.
-func splitPatterns(patterns string) []security.BlessingPattern {
-	if patterns == "" {
-		return nil
-	}
-	n := strings.Count(patterns, string(blessingsSeparator)) + 1
-	out := make([]security.BlessingPattern, n)
-	last, start := 0, 0
-	for i, r := range patterns {
-		if r == blessingsSeparator {
-			out[last] = security.BlessingPattern(patterns[start:i])
-			last++
-			start = i + 1
-		}
-	}
-	out[last] = security.BlessingPattern(patterns[start:])
-	return out
-}
diff --git a/syncbase/discovery_pattern_test.go b/syncbase/discovery_pattern_test.go
deleted file mode 100644
index 1d61faa..0000000
--- a/syncbase/discovery_pattern_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-package syncbase
-
-import (
-	"reflect"
-	"testing"
-
-	"v.io/v23/security"
-)
-
-func TestJoinSplitPatterns(t *testing.T) {
-	cases := []struct {
-		patterns []security.BlessingPattern
-		joined   string
-	}{
-		{nil, ""},
-		{[]security.BlessingPattern{"a", "b"}, "a,b"},
-		{[]security.BlessingPattern{"a:b:c", "d:e:f"}, "a:b:c,d:e:f"},
-		{[]security.BlessingPattern{"alpha:one", "alpha:two", "alpha:three"}, "alpha:one,alpha:two,alpha:three"},
-	}
-	for _, c := range cases {
-		if got := joinPatterns(c.patterns); got != c.joined {
-			t.Errorf("%#v, got %q, wanted %q", c.patterns, got, c.joined)
-		}
-		if got := splitPatterns(c.joined); !reflect.DeepEqual(got, c.patterns) {
-			t.Errorf("%q, got %#v, wanted %#v", c.joined, got, c.patterns)
-		}
-	}
-	// Special case, Joining an empty non-nil list results in empty string.
-	if got := joinPatterns([]security.BlessingPattern{}); got != "" {
-		t.Errorf("Joining empty list: got %q, want %q", got, "")
-	}
-}
diff --git a/syncbase/discovery_test.go b/syncbase/discovery_test.go
deleted file mode 100644
index 8408b0d..0000000
--- a/syncbase/discovery_test.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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.
-
-package syncbase_test
-
-import (
-	"fmt"
-	"reflect"
-	"testing"
-	"time"
-
-	"v.io/v23"
-	"v.io/v23/context"
-	"v.io/v23/discovery"
-	"v.io/v23/security"
-	"v.io/v23/security/access"
-	wire "v.io/v23/services/syncbase"
-	"v.io/v23/syncbase"
-	"v.io/v23/verror"
-	tu "v.io/x/ref/services/syncbase/testutil"
-	"v.io/x/ref/test/testutil"
-)
-
-func TestSyncgroupDiscovery(t *testing.T) {
-	_, ctx, sName, rootp, cleanup := tu.SetupOrDieCustom("o:app1:client1", "server",
-		tu.DefaultPerms(access.AllTypicalTags(), "root:o:app1:client1"))
-	defer cleanup()
-	d := tu.CreateDatabase(t, ctx, syncbase.NewService(sName), "d")
-	collection1 := tu.CreateCollection(t, ctx, d, "c1")
-	collection2 := tu.CreateCollection(t, ctx, d, "c2")
-
-	c1Updates, err := scanAs(ctx, rootp, "o:app1:client1")
-	if err != nil {
-		panic(err)
-	}
-	c2Updates, err := scanAs(ctx, rootp, "o:app1:client2")
-	if err != nil {
-		panic(err)
-	}
-
-	sgId := d.Syncgroup(ctx, "sg1").Id()
-	spec := wire.SyncgroupSpec{
-		Description: "test syncgroup sg1",
-		Perms:       tu.DefaultPerms(wire.AllSyncgroupTags, "root:server", "root:o:app1:client1"),
-		Collections: []wire.Id{collection1.Id()},
-	}
-	createSyncgroup(t, ctx, d, sgId, spec, verror.ID(""))
-
-	// First update is for syncbase, and not a specific syncgroup.
-	u := <-c1Updates
-	attrs := u.Advertisement().Attributes
-	peer := attrs[wire.DiscoveryAttrPeer]
-	if peer == "" || len(attrs) != 1 {
-		t.Errorf("Got %v, expected only a peer name.", attrs)
-	}
-	// Client2 should see the same.
-	if err := expect(c2Updates, &discovery.AdId{}, find, discovery.Attributes{wire.DiscoveryAttrPeer: peer}); err != nil {
-		t.Error(err)
-	}
-
-	sg1Attrs := discovery.Attributes{
-		wire.DiscoveryAttrDatabaseName:      "d",
-		wire.DiscoveryAttrDatabaseBlessing:  "root:o:app1",
-		wire.DiscoveryAttrSyncgroupName:     "sg1",
-		wire.DiscoveryAttrSyncgroupBlessing: "root:o:app1:client1",
-	}
-	sg2Attrs := discovery.Attributes{
-		wire.DiscoveryAttrDatabaseName:      "d",
-		wire.DiscoveryAttrDatabaseBlessing:  "root:o:app1",
-		wire.DiscoveryAttrSyncgroupName:     "sg2",
-		wire.DiscoveryAttrSyncgroupBlessing: "root:o:app1:client1",
-	}
-
-	// Then we should see an update for the created syncgroup.
-	var sg1AdId discovery.AdId
-	if err := expect(c1Updates, &sg1AdId, find, sg1Attrs); err != nil {
-		t.Error(err)
-	}
-
-	// Now update the spec to add client2 to the permissions.
-	spec.Perms = tu.DefaultPerms(wire.AllSyncgroupTags, "root:server", "root:o:app1:client1", "root:o:app1:client2")
-	if err := d.SyncgroupForId(sgId).SetSpec(ctx, spec, ""); err != nil {
-		t.Fatalf("sg.SetSpec failed: %v", err)
-	}
-
-	// Client1 should see a lost and a found message.
-	if err := expect(c1Updates, &sg1AdId, both, sg1Attrs); err != nil {
-		t.Error(err)
-	}
-	// Client2 should just now see the found message.
-	if err := expect(c2Updates, &sg1AdId, find, sg1Attrs); err != nil {
-		t.Error(err)
-	}
-
-	// Now create a second syncgroup.
-	sg2Id := d.Syncgroup(ctx, "sg2").Id()
-	spec2 := wire.SyncgroupSpec{
-		Description: "test syncgroup sg2",
-		Perms:       tu.DefaultPerms(wire.AllSyncgroupTags, "root:server", "root:o:app1:client1", "root:o:app1:client2"),
-		Collections: []wire.Id{collection2.Id()},
-	}
-	createSyncgroup(t, ctx, d, sg2Id, spec2, verror.ID(""))
-
-	// Both clients should see the new syncgroup.
-	var sg2AdId discovery.AdId
-	if err := expect(c1Updates, &sg2AdId, find, sg2Attrs); err != nil {
-		t.Error(err)
-	}
-	if err := expect(c2Updates, &sg2AdId, find, sg2Attrs); err != nil {
-		t.Error(err)
-	}
-
-	spec2.Perms = tu.DefaultPerms(wire.AllSyncgroupTags, "root:server", "root:o:app1:client1")
-	if err := d.SyncgroupForId(sg2Id).SetSpec(ctx, spec2, ""); err != nil {
-		t.Fatalf("sg.SetSpec failed: %v", err)
-	}
-	if err := expect(c2Updates, &sg2AdId, lose, sg2Attrs); err != nil {
-		t.Error(err)
-	}
-}
-
-func scanAs(ctx *context.T, rootp security.Principal, as string) (<-chan discovery.Update, error) {
-	idp := testutil.IDProviderFromPrincipal(rootp)
-	p := testutil.NewPrincipal()
-	if err := idp.Bless(p, as); err != nil {
-		return nil, err
-	}
-	ctx, err := v23.WithPrincipal(ctx, p)
-	if err != nil {
-		return nil, err
-	}
-	dis, err := syncbase.NewDiscovery(ctx)
-	if err != nil {
-		return nil, err
-	}
-	return dis.Scan(ctx, `v.InterfaceName="v.io/x/ref/services/syncbase/server/interfaces/Sync"`)
-}
-
-const (
-	lose = "lose"
-	find = "find"
-	both = "both"
-)
-
-func expect(ch <-chan discovery.Update, id *discovery.AdId, typ string, want discovery.Attributes) error {
-	select {
-	case u := <-ch:
-		if (u.IsLost() && typ == find) || (!u.IsLost() && typ == lose) {
-			return fmt.Errorf("IsLost mismatch.  Got %v, wanted %v", u, typ)
-		}
-		ad := u.Advertisement()
-		got := ad.Attributes
-		if id.IsValid() {
-			if *id != ad.Id {
-				return fmt.Errorf("mismatched id, got %v, want %v", ad.Id, id)
-			}
-		} else {
-			*id = ad.Id
-		}
-		if !reflect.DeepEqual(got, want) {
-			return fmt.Errorf("got %v, want %v", got, want)
-		}
-		if typ == both {
-			typ = lose
-			if u.IsLost() {
-				typ = find
-			}
-			return expect(ch, id, typ, want)
-		}
-		return nil
-	case <-time.After(2 * time.Second):
-		return fmt.Errorf("timed out")
-	}
-}