mojo/discovery: update mojo interface with a new sessioned discovery

  * This doesn't include updates on Dart and Java interfaces.
    - aghassemi@ will update Dart and I'll update Java once this CL is
      submitted.

Change-Id: Id5abce7b818040cd269e4b14dc0ae9839c53465a
diff --git a/Makefile b/Makefile
index 010712f..88d5cd9 100644
--- a/Makefile
+++ b/Makefile
@@ -121,12 +121,10 @@
 
 # Examples.
 run-advertiser: $(DISCOVERY_BUILD_DIR)/advertiser.mojo $(DISCOVERY_BUILD_DIR)/discovery.mojo
-	$(MOJO_DEVTOOLS)/mojo_run --config-file $(CURDIR)/mojoconfig $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) https://mojo.v.io/advertiser.mojo \
-	--args-for="https://mojo.v.io/discovery.mojo"
+	$(call MOJO_RUN,"https://mojo.v.io/advertiser.mojo")
 
 run-scanner: $(DISCOVERY_BUILD_DIR)/scanner.mojo $(DISCOVERY_BUILD_DIR)/discovery.mojo
-	$(MOJO_DEVTOOLS)/mojo_run --config-file $(CURDIR)/mojoconfig $(MOJO_SHELL_FLAGS) $(MOJO_ANDROID_FLAGS) https://mojo.v.io/scanner.mojo \
-	--args-for="https://mojo.v.io/discovery.mojo"
+	$(call MOJO_RUN,"https://mojo.v.io/scanner.mojo")
 
 $(DISCOVERY_BUILD_DIR)/advertiser.mojo: $(V23_GO_FILES) go/src/mojom/vanadium/discovery/discovery.mojom.go | mojo-env-check
 	$(call MOGO_BUILD,examples/advertiser,$@)
diff --git a/go/src/examples/advertiser/advertiser.go b/go/src/examples/advertiser/advertiser.go
index 7226b6e..0d41e53 100644
--- a/go/src/examples/advertiser/advertiser.go
+++ b/go/src/examples/advertiser/advertiser.go
@@ -17,42 +17,46 @@
 //#include "mojo/public/c/system/types.h"
 import "C"
 
-type advDelegate struct {
-	id    uint32
-	proxy *discovery.Advertiser_Proxy
+type delegate struct {
+	stop func()
 }
 
-func (a *advDelegate) Initialize(ctx application.Context) {
-	req, ptr := discovery.CreateMessagePipeForAdvertiser()
+func (d *delegate) Initialize(ctx application.Context) {
+	req, ptr := discovery.CreateMessagePipeForDiscovery()
 	ctx.ConnectToApplication("https://mojo.v.io/discovery.mojo").ConnectToService(&req)
-	a.proxy = discovery.NewAdvertiserProxy(ptr, bindings.GetAsyncWaiter())
-	s := discovery.Service{
+
+	service := discovery.Service{
 		InterfaceName: "v.io/discovery.T",
 		Addrs:         []string{"localhost:1000", "localhost:2000"},
 		Attrs:         &map[string]string{"foo": "bar"},
 	}
-	id, _, e1, e2 := a.proxy.Advertise(s, nil)
+	proxy := discovery.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
+	instanceId, e1, e2 := proxy.StartAdvertising(service, nil)
 	if e1 != nil || e2 != nil {
 		log.Println("Error occurred", e1, e2)
 		return
 	}
 
-	a.id = id
+	d.stop = func() {
+		proxy.StopAdvertising(instanceId)
+		proxy.Close_Proxy()
+	}
 }
 
-func (*advDelegate) AcceptConnection(connection *application.Connection) {
+func (*delegate) AcceptConnection(connection *application.Connection) {
 	connection.Close()
 }
 
-func (s *advDelegate) Quit() {
-	s.proxy.Stop(s.id)
+func (d *delegate) Quit() {
+	if d.stop != nil {
+		d.stop()
+	}
 }
 
 //export MojoMain
 func MojoMain(handle C.MojoHandle) C.MojoResult {
-	application.Run(&advDelegate{}, system.MojoHandle(handle))
+	application.Run(&delegate{}, system.MojoHandle(handle))
 	return C.MOJO_RESULT_OK
 }
 
-func main() {
-}
+func main() {}
diff --git a/go/src/examples/scanner/scanner.go b/go/src/examples/scanner/scanner.go
index 9a78238..2ad52a1 100644
--- a/go/src/examples/scanner/scanner.go
+++ b/go/src/examples/scanner/scanner.go
@@ -17,42 +17,50 @@
 //#include "mojo/public/c/system/types.h"
 import "C"
 
-type handler struct{}
+type scanHandler struct{}
 
-func (*handler) Found(s discovery.Service) error {
-	log.Println("Found a new service", s)
+func (*scanHandler) Update(update discovery.Update) error {
+	var tag string
+	switch update.UpdateType {
+	case discovery.UpdateType_Found:
+		tag = "Found"
+	case discovery.UpdateType_Lost:
+		tag = "Lost"
+	}
+	log.Printf("%s service: %v", tag, update.Service)
 	return nil
 }
 
-func (*handler) Lost(s []uint8) error {
-	log.Println("Lost a new service", s)
-	return nil
+type delegate struct {
+	stop func()
 }
 
-type scannerDelegate struct {
-	id    uint32
-	proxy *discovery.Scanner_Proxy
-	stub  *bindings.Stub
-}
-
-func (s *scannerDelegate) Initialize(ctx application.Context) {
-	req, ptr := discovery.CreateMessagePipeForScanner()
+func (d *delegate) Initialize(ctx application.Context) {
+	req, ptr := discovery.CreateMessagePipeForDiscovery()
 	ctx.ConnectToApplication("https://mojo.v.io/discovery.mojo").ConnectToService(&req)
-	s.proxy = discovery.NewScannerProxy(ptr, bindings.GetAsyncWaiter())
-	scanReq, scanPtr := discovery.CreateMessagePipeForScanHandler()
-	s.stub = discovery.NewScanHandlerStub(scanReq, &handler{}, bindings.GetAsyncWaiter())
-	id, e1, e2 := s.proxy.Scan(`v.InterfaceName="v.io/discovery.T"`, scanPtr)
+
+	scanHandlerReq, scanHandlerPtr := discovery.CreateMessagePipeForScanHandler()
+	scanHandlerStub := discovery.NewScanHandlerStub(scanHandlerReq, &scanHandler{}, bindings.GetAsyncWaiter())
+
+	proxy := discovery.NewDiscoveryProxy(ptr, bindings.GetAsyncWaiter())
+	scanId, e1, e2 := proxy.StartScan(`v.InterfaceName="v.io/discovery.T"`, scanHandlerPtr)
 	if e1 != nil || e2 != nil {
 		log.Println("Error occurred", e1, e2)
+		scanHandlerStub.Close()
 		return
 	}
 
-	s.id = id
+	d.stop = func() {
+		proxy.StopScan(scanId)
+		scanHandlerStub.Close()
+		proxy.Close_Proxy()
+	}
+
 	go func() {
 		for {
-			if err := s.stub.ServeRequest(); err != nil {
-				connectionError, ok := err.(*bindings.ConnectionError)
-				if !ok || !connectionError.Closed() {
+			if err := scanHandlerStub.ServeRequest(); err != nil {
+				connErr, ok := err.(*bindings.ConnectionError)
+				if !ok || !connErr.Closed() {
 					log.Println(err)
 				}
 				break
@@ -61,20 +69,18 @@
 	}()
 }
 
-func (*scannerDelegate) AcceptConnection(connection *application.Connection) {
+func (*delegate) AcceptConnection(connection *application.Connection) {
 	connection.Close()
 }
 
-func (s *scannerDelegate) Quit() {
-	s.proxy.Stop(s.id)
-	s.stub.Close()
+func (d *delegate) Quit() {
+	d.stop()
 }
 
 //export MojoMain
 func MojoMain(handle C.MojoHandle) C.MojoResult {
-	application.Run(&scannerDelegate{}, system.MojoHandle(handle))
+	application.Run(&delegate{}, system.MojoHandle(handle))
 	return C.MOJO_RESULT_OK
 }
 
-func main() {
-}
+func main() {}
diff --git a/go/src/mojom/vanadium/discovery/discovery.mojom.go b/go/src/mojom/vanadium/discovery/discovery.mojom.go
index 44df270..f8e7461 100644
--- a/go/src/mojom/vanadium/discovery/discovery.mojom.go
+++ b/go/src/mojom/vanadium/discovery/discovery.mojom.go
@@ -19,6 +19,81 @@
 	sort "sort"
 )
 
+// These IDs are the Mojom Identifiers / Type Keys.
+// Mojom libraries importing this one will use these identifiers when building
+// TypeReference objects.
+var ID_discovery_UpdateType__ string = "discovery_UpdateType__"
+var ID_discovery_Service__ string = "discovery_Service__"
+var ID_discovery_Update__ string = "discovery_Update__"
+var ID_discovery_Error__ string = "discovery_Error__"
+var ID_discovery_Discovery__ string = "discovery_Discovery__"
+var ID_discovery_ScanHandler__ string = "discovery_ScanHandler__"
+
+var discoveryDesc__ = make(map[string]mojom_types.UserDefinedType)
+
+func init() {
+	discoveryDesc__["discovery_UpdateType__"] = &mojom_types.UserDefinedTypeEnumType{
+		Value: discovery_UpdateType__(),
+	}
+	discoveryDesc__["discovery_Service__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Service__(),
+	}
+
+	discoveryDesc__["discovery_Update__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Update__(),
+	}
+
+	discoveryDesc__["discovery_Error__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Error__(),
+	}
+
+	discoveryDesc__["discovery_Discovery__"] = &mojom_types.UserDefinedTypeInterfaceType{
+		Value: discovery_Discovery__(),
+	}
+	discoveryDesc__["discovery_Discovery_StartAdvertising_Params__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StartAdvertising_Params__(),
+	}
+
+	discoveryDesc__["discovery_Discovery_StartAdvertising_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StartAdvertising_ResponseParams__(),
+	}
+
+	discoveryDesc__["discovery_Discovery_StopAdvertising_Params__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StopAdvertising_Params__(),
+	}
+
+	discoveryDesc__["discovery_Discovery_StopAdvertising_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StopAdvertising_ResponseParams__(),
+	}
+
+	discoveryDesc__["discovery_Discovery_StartScan_Params__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StartScan_Params__(),
+	}
+
+	discoveryDesc__["discovery_ScanHandler__"] = &mojom_types.UserDefinedTypeInterfaceType{
+		Value: discovery_ScanHandler__(),
+	}
+	discoveryDesc__["discovery_ScanHandler_Update_Params__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_ScanHandler_Update_Params__(),
+	}
+
+	discoveryDesc__["discovery_Discovery_StartScan_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StartScan_ResponseParams__(),
+	}
+
+	discoveryDesc__["discovery_Discovery_StopScan_Params__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StopScan_Params__(),
+	}
+
+	discoveryDesc__["discovery_Discovery_StopScan_ResponseParams__"] = &mojom_types.UserDefinedTypeStructType{
+		Value: discovery_Discovery_StopScan_ResponseParams__(),
+	}
+
+}
+func GetAllMojomTypeDefinitions() map[string]mojom_types.UserDefinedType {
+	return discoveryDesc__
+}
+
 type UpdateType int32
 
 const (
@@ -26,78 +101,112 @@
 	UpdateType_Lost  = UpdateType_Found + 1
 )
 
-type Advertiser interface {
-	Advertise(inService Service, inVisibility *[]string) (outHandle uint32, outInstanceId string, outErr *Error, err error)
-	Stop(inH uint32) (outErr *Error, err error)
+// String names and labels used by the MojomEnum types.
+var (
+	enumName_UpdateType            = "UpdateType"
+	enumFullIdentifier_UpdateType  = "discovery.UpdateType"
+	enumFieldName_UpdateType_Found = "Found"
+	enumFieldName_UpdateType_Lost  = "Lost"
+)
+
+func discovery_UpdateType__() mojom_types.MojomEnum {
+	return mojom_types.MojomEnum{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &enumName_UpdateType,
+			FullIdentifier: &enumFullIdentifier_UpdateType,
+		},
+		Values: []mojom_types.EnumValue{mojom_types.EnumValue{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &enumFieldName_UpdateType_Found,
+			},
+			EnumTypeKey: ID_discovery_UpdateType__,
+			IntValue:    int32(1),
+		}, mojom_types.EnumValue{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &enumFieldName_UpdateType_Lost,
+			},
+			EnumTypeKey: ID_discovery_UpdateType__,
+			IntValue:    int32(2),
+		}},
+	}
 }
 
-var advertiser_Name = "v23::discovery::Advertiser"
-
-type Advertiser_Request bindings.InterfaceRequest
-
-func (r *Advertiser_Request) Name() string {
-	return advertiser_Name
+type Discovery interface {
+	StartAdvertising(inService Service, inVisibility *[]string) (outInstanceId string, outErr *Error, err error)
+	StopAdvertising(inInstanceId string) (outErr *Error, err error)
+	StartScan(inQuery string, inHandler ScanHandler_Pointer) (outScanId uint32, outErr *Error, err error)
+	StopScan(inScanId uint32) (outErr *Error, err error)
 }
 
-type Advertiser_Pointer bindings.InterfacePointer
+var discovery_Name = "v23::discovery::Discovery"
 
-func (p *Advertiser_Pointer) Name() string {
-	return advertiser_Name
+type Discovery_Request bindings.InterfaceRequest
+
+func (r *Discovery_Request) Name() string {
+	return discovery_Name
 }
 
-type Advertiser_ServiceFactory struct {
-	Delegate Advertiser_Factory
+type Discovery_Pointer bindings.InterfacePointer
+
+func (p *Discovery_Pointer) Name() string {
+	return discovery_Name
 }
 
-type Advertiser_Factory interface {
-	Create(request Advertiser_Request)
+type Discovery_ServiceFactory struct {
+	Delegate Discovery_Factory
 }
 
-func (f *Advertiser_ServiceFactory) Name() string {
-	return advertiser_Name
+type Discovery_Factory interface {
+	Create(request Discovery_Request)
 }
 
-func (f *Advertiser_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
-	return &Advertiser_ServiceDescription{}
+func (f *Discovery_ServiceFactory) Name() string {
+	return discovery_Name
 }
 
-func (f *Advertiser_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
-	request := Advertiser_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
+func (f *Discovery_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
+	return &Discovery_ServiceDescription{}
+}
+
+func (f *Discovery_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
+	request := Discovery_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
 	f.Delegate.Create(request)
 }
 
-// CreateMessagePipeForAdvertiser creates a message pipe for use with the
-// Advertiser interface with a Advertiser_Request on one end and a Advertiser_Pointer on the other.
-func CreateMessagePipeForAdvertiser() (Advertiser_Request, Advertiser_Pointer) {
+// CreateMessagePipeForDiscovery creates a message pipe for use with the
+// Discovery interface with a Discovery_Request on one end and a Discovery_Pointer on the other.
+func CreateMessagePipeForDiscovery() (Discovery_Request, Discovery_Pointer) {
 	r, p := bindings.CreateMessagePipeForMojoInterface()
-	return Advertiser_Request(r), Advertiser_Pointer(p)
+	return Discovery_Request(r), Discovery_Pointer(p)
 }
 
-const advertiser_Advertise_Name uint32 = 0
-const advertiser_Stop_Name uint32 = 1
+const discovery_StartAdvertising_Name uint32 = 0
+const discovery_StopAdvertising_Name uint32 = 1
+const discovery_StartScan_Name uint32 = 2
+const discovery_StopScan_Name uint32 = 3
 
-type Advertiser_Proxy struct {
+type Discovery_Proxy struct {
 	router *bindings.Router
 	ids    bindings.Counter
 }
 
-func NewAdvertiserProxy(p Advertiser_Pointer, waiter bindings.AsyncWaiter) *Advertiser_Proxy {
-	return &Advertiser_Proxy{
+func NewDiscoveryProxy(p Discovery_Pointer, waiter bindings.AsyncWaiter) *Discovery_Proxy {
+	return &Discovery_Proxy{
 		bindings.NewRouter(p.PassMessagePipe(), waiter),
 		bindings.NewCounter(),
 	}
 }
 
-func (p *Advertiser_Proxy) Close_Proxy() {
+func (p *Discovery_Proxy) Close_Proxy() {
 	p.router.Close()
 }
 
-type advertiser_Advertise_Params struct {
+type discovery_StartAdvertising_Params struct {
 	inService    Service
 	inVisibility *[]string
 }
 
-func (s *advertiser_Advertise_Params) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_StartAdvertising_Params) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(16, 0)
 	if err := encoder.WritePointer(); err != nil {
 		return err
@@ -130,23 +239,23 @@
 	return nil
 }
 
-var advertiser_Advertise_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_StartAdvertising_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{24, 0},
 }
 
-func (s *advertiser_Advertise_Params) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StartAdvertising_Params) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(advertiser_Advertise_Params_Versions), func(i int) bool {
-		return advertiser_Advertise_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StartAdvertising_Params_Versions), func(i int) bool {
+		return discovery_StartAdvertising_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(advertiser_Advertise_Params_Versions) {
-		if advertiser_Advertise_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StartAdvertising_Params_Versions) {
+		if discovery_StartAdvertising_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := advertiser_Advertise_Params_Versions[index].Size
+		expectedSize := discovery_StartAdvertising_Params_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -206,17 +315,45 @@
 	return nil
 }
 
-type advertiser_Advertise_ResponseParams struct {
-	outHandle     uint32
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStartAdvertisingParams                   = "DiscoveryStartAdvertisingParams"
+	structFullIdentifier_DiscoveryStartAdvertisingParams         = "discovery.DiscoveryStartAdvertisingParams"
+	structFieldName_DiscoveryStartAdvertisingParams_InService    = "InService"
+	structFieldName_DiscoveryStartAdvertisingParams_InVisibility = "InVisibility"
+)
+
+func discovery_Discovery_StartAdvertising_Params__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStartAdvertisingParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStartAdvertisingParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartAdvertisingParams_InService,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Identifier: &ID_discovery_Service__,
+					TypeKey: &ID_discovery_Service__},
+			},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartAdvertisingParams_InVisibility,
+			},
+			Type: &mojom_types.TypeArrayType{
+				Value: mojom_types.ArrayType{Nullable: true, ElementType: &mojom_types.TypeStringType{mojom_types.StringType{false}}},
+			},
+		}},
+	}
+}
+
+type discovery_StartAdvertising_ResponseParams struct {
 	outInstanceId string
 	outErr        *Error
 }
 
-func (s *advertiser_Advertise_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WriteUint32(s.outHandle); err != nil {
-		return err
-	}
+func (s *discovery_StartAdvertising_ResponseParams) Encode(encoder *bindings.Encoder) error {
+	encoder.StartStruct(16, 0)
 	if err := encoder.WritePointer(); err != nil {
 		return err
 	}
@@ -239,23 +376,23 @@
 	return nil
 }
 
-var advertiser_Advertise_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
+var discovery_StartAdvertising_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+	bindings.DataHeader{24, 0},
 }
 
-func (s *advertiser_Advertise_ResponseParams) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StartAdvertising_ResponseParams) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(advertiser_Advertise_ResponseParams_Versions), func(i int) bool {
-		return advertiser_Advertise_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StartAdvertising_ResponseParams_Versions), func(i int) bool {
+		return discovery_StartAdvertising_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(advertiser_Advertise_ResponseParams_Versions) {
-		if advertiser_Advertise_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StartAdvertising_ResponseParams_Versions) {
+		if discovery_StartAdvertising_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := advertiser_Advertise_ResponseParams_Versions[index].Size
+		expectedSize := discovery_StartAdvertising_ResponseParams_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -263,13 +400,6 @@
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadUint32()
-		if err != nil {
-			return err
-		}
-		s.outHandle = value0
-	}
-	if header.ElementsOrVersion >= 0 {
 		pointer0, err := decoder.ReadPointer()
 		if err != nil {
 			return err
@@ -304,13 +434,43 @@
 	return nil
 }
 
-func (p *Advertiser_Proxy) Advertise(inService Service, inVisibility *[]string) (outHandle uint32, outInstanceId string, outErr *Error, err error) {
-	payload := &advertiser_Advertise_Params{
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStartAdvertisingResponseParams                    = "DiscoveryStartAdvertisingResponseParams"
+	structFullIdentifier_DiscoveryStartAdvertisingResponseParams          = "discovery.DiscoveryStartAdvertisingResponseParams"
+	structFieldName_DiscoveryStartAdvertisingResponseParams_OutInstanceId = "OutInstanceId"
+	structFieldName_DiscoveryStartAdvertisingResponseParams_OutErr        = "OutErr"
+)
+
+func discovery_Discovery_StartAdvertising_ResponseParams__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStartAdvertisingResponseParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStartAdvertisingResponseParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartAdvertisingResponseParams_OutInstanceId,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartAdvertisingResponseParams_OutErr,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
+					TypeKey: &ID_discovery_Error__},
+			},
+		}},
+	}
+}
+
+func (p *Discovery_Proxy) StartAdvertising(inService Service, inVisibility *[]string) (outInstanceId string, outErr *Error, err error) {
+	payload := &discovery_StartAdvertising_Params{
 		inService,
 		inVisibility,
 	}
 	header := bindings.MessageHeader{
-		Type:      advertiser_Advertise_Name,
+		Type:      discovery_StartAdvertising_Name,
 		Flags:     bindings.MessageExpectsResponseFlag,
 		RequestId: p.ids.Count(),
 	}
@@ -331,30 +491,32 @@
 		}
 		return
 	}
-	if got, want := readResult.Message.Header.Type, advertiser_Advertise_Name; got != want {
+	if got, want := readResult.Message.Header.Type, discovery_StartAdvertising_Name; got != want {
 		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
 			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
 		}
 		return
 	}
-	var response advertiser_Advertise_ResponseParams
+	var response discovery_StartAdvertising_ResponseParams
 	if err = readResult.Message.DecodePayload(&response); err != nil {
 		p.Close_Proxy()
 		return
 	}
-	outHandle = response.outHandle
 	outInstanceId = response.outInstanceId
 	outErr = response.outErr
 	return
 }
 
-type advertiser_Stop_Params struct {
-	inH uint32
+type discovery_StopAdvertising_Params struct {
+	inInstanceId string
 }
 
-func (s *advertiser_Stop_Params) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_StopAdvertising_Params) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(8, 0)
-	if err := encoder.WriteUint32(s.inH); err != nil {
+	if err := encoder.WritePointer(); err != nil {
+		return err
+	}
+	if err := encoder.WriteString(s.inInstanceId); err != nil {
 		return err
 	}
 	if err := encoder.Finish(); err != nil {
@@ -363,23 +525,23 @@
 	return nil
 }
 
-var advertiser_Stop_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_StopAdvertising_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{16, 0},
 }
 
-func (s *advertiser_Stop_Params) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StopAdvertising_Params) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(advertiser_Stop_Params_Versions), func(i int) bool {
-		return advertiser_Stop_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StopAdvertising_Params_Versions), func(i int) bool {
+		return discovery_StopAdvertising_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(advertiser_Stop_Params_Versions) {
-		if advertiser_Stop_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StopAdvertising_Params_Versions) {
+		if discovery_StopAdvertising_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := advertiser_Stop_Params_Versions[index].Size
+		expectedSize := discovery_StopAdvertising_Params_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -387,11 +549,19 @@
 		}
 	}
 	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadUint32()
+		pointer0, err := decoder.ReadPointer()
 		if err != nil {
 			return err
 		}
-		s.inH = value0
+		if pointer0 == 0 {
+			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+		} else {
+			value0, err := decoder.ReadString()
+			if err != nil {
+				return err
+			}
+			s.inInstanceId = value0
+		}
 	}
 	if err := decoder.Finish(); err != nil {
 		return err
@@ -399,11 +569,32 @@
 	return nil
 }
 
-type advertiser_Stop_ResponseParams struct {
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStopAdvertisingParams                   = "DiscoveryStopAdvertisingParams"
+	structFullIdentifier_DiscoveryStopAdvertisingParams         = "discovery.DiscoveryStopAdvertisingParams"
+	structFieldName_DiscoveryStopAdvertisingParams_InInstanceId = "InInstanceId"
+)
+
+func discovery_Discovery_StopAdvertising_Params__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStopAdvertisingParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStopAdvertisingParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStopAdvertisingParams_InInstanceId,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+		}},
+	}
+}
+
+type discovery_StopAdvertising_ResponseParams struct {
 	outErr *Error
 }
 
-func (s *advertiser_Stop_ResponseParams) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_StopAdvertising_ResponseParams) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(8, 0)
 	if s.outErr == nil {
 		encoder.WriteNullPointer()
@@ -421,23 +612,23 @@
 	return nil
 }
 
-var advertiser_Stop_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_StopAdvertising_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{16, 0},
 }
 
-func (s *advertiser_Stop_ResponseParams) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StopAdvertising_ResponseParams) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(advertiser_Stop_ResponseParams_Versions), func(i int) bool {
-		return advertiser_Stop_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StopAdvertising_ResponseParams_Versions), func(i int) bool {
+		return discovery_StopAdvertising_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(advertiser_Stop_ResponseParams_Versions) {
-		if advertiser_Stop_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StopAdvertising_ResponseParams_Versions) {
+		if discovery_StopAdvertising_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := advertiser_Stop_ResponseParams_Versions[index].Size
+		expectedSize := discovery_StopAdvertising_ResponseParams_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -464,12 +655,36 @@
 	return nil
 }
 
-func (p *Advertiser_Proxy) Stop(inH uint32) (outErr *Error, err error) {
-	payload := &advertiser_Stop_Params{
-		inH,
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStopAdvertisingResponseParams             = "DiscoveryStopAdvertisingResponseParams"
+	structFullIdentifier_DiscoveryStopAdvertisingResponseParams   = "discovery.DiscoveryStopAdvertisingResponseParams"
+	structFieldName_DiscoveryStopAdvertisingResponseParams_OutErr = "OutErr"
+)
+
+func discovery_Discovery_StopAdvertising_ResponseParams__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStopAdvertisingResponseParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStopAdvertisingResponseParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStopAdvertisingResponseParams_OutErr,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
+					TypeKey: &ID_discovery_Error__},
+			},
+		}},
+	}
+}
+
+func (p *Discovery_Proxy) StopAdvertising(inInstanceId string) (outErr *Error, err error) {
+	payload := &discovery_StopAdvertising_Params{
+		inInstanceId,
 	}
 	header := bindings.MessageHeader{
-		Type:      advertiser_Stop_Name,
+		Type:      discovery_StopAdvertising_Name,
 		Flags:     bindings.MessageExpectsResponseFlag,
 		RequestId: p.ids.Count(),
 	}
@@ -490,13 +705,13 @@
 		}
 		return
 	}
-	if got, want := readResult.Message.Header.Type, advertiser_Stop_Name; got != want {
+	if got, want := readResult.Message.Header.Type, discovery_StopAdvertising_Name; got != want {
 		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
 			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
 		}
 		return
 	}
-	var response advertiser_Stop_ResponseParams
+	var response discovery_StopAdvertising_ResponseParams
 	if err = readResult.Message.DecodePayload(&response); err != nil {
 		p.Close_Proxy()
 		return
@@ -505,172 +720,12 @@
 	return
 }
 
-type advertiser_Stub struct {
-	connector *bindings.Connector
-	impl      Advertiser
+type discovery_StartScan_Params struct {
+	inQuery   string
+	inHandler ScanHandler_Pointer
 }
 
-func NewAdvertiserStub(r Advertiser_Request, impl Advertiser, waiter bindings.AsyncWaiter) *bindings.Stub {
-	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
-	return bindings.NewStub(connector, &advertiser_Stub{connector, impl})
-}
-
-func (f *Advertiser_Request) ServiceDescription() service_describer.ServiceDescription {
-	return &Advertiser_ServiceDescription{}
-}
-
-type Advertiser_ServiceDescription struct{}
-
-func (sd *Advertiser_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
-	err = fmt.Errorf("GetTopLevelInterface not implemented")
-	return
-}
-
-func (sd *Advertiser_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
-	err = fmt.Errorf("GetTypeDefinition not implemented")
-	return
-}
-
-func (sd *Advertiser_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
-	err = fmt.Errorf("GetAllTypeDefinitions not implemented")
-	return
-}
-
-var _ service_describer.ServiceDescription = (*Advertiser_ServiceDescription)(nil)
-
-func (s *advertiser_Stub) Accept(message *bindings.Message) (err error) {
-	switch message.Header.Type {
-	case advertiser_Advertise_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request advertiser_Advertise_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response advertiser_Advertise_ResponseParams
-		response.outHandle, response.outInstanceId, response.outErr, err = s.impl.Advertise(request.inService, request.inVisibility)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      advertiser_Advertise_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case advertiser_Stop_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request advertiser_Stop_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response advertiser_Stop_ResponseParams
-		response.outErr, err = s.impl.Stop(request.inH)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      advertiser_Stop_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	default:
-		return &bindings.ValidationError{
-			bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("unknown method %v", message.Header.Type),
-		}
-	}
-	return
-}
-
-type Scanner interface {
-	Scan(inQuery string, inScanHandler ScanHandler_Pointer) (outHandle uint32, outErr *Error, err error)
-	Stop(inH uint32) (outErr *Error, err error)
-}
-
-var scanner_Name = "v23::discovery::Scanner"
-
-type Scanner_Request bindings.InterfaceRequest
-
-func (r *Scanner_Request) Name() string {
-	return scanner_Name
-}
-
-type Scanner_Pointer bindings.InterfacePointer
-
-func (p *Scanner_Pointer) Name() string {
-	return scanner_Name
-}
-
-type Scanner_ServiceFactory struct {
-	Delegate Scanner_Factory
-}
-
-type Scanner_Factory interface {
-	Create(request Scanner_Request)
-}
-
-func (f *Scanner_ServiceFactory) Name() string {
-	return scanner_Name
-}
-
-func (f *Scanner_ServiceFactory) ServiceDescription() service_describer.ServiceDescription {
-	return &Scanner_ServiceDescription{}
-}
-
-func (f *Scanner_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
-	request := Scanner_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
-	f.Delegate.Create(request)
-}
-
-// CreateMessagePipeForScanner creates a message pipe for use with the
-// Scanner interface with a Scanner_Request on one end and a Scanner_Pointer on the other.
-func CreateMessagePipeForScanner() (Scanner_Request, Scanner_Pointer) {
-	r, p := bindings.CreateMessagePipeForMojoInterface()
-	return Scanner_Request(r), Scanner_Pointer(p)
-}
-
-const scanner_Scan_Name uint32 = 0
-const scanner_Stop_Name uint32 = 1
-
-type Scanner_Proxy struct {
-	router *bindings.Router
-	ids    bindings.Counter
-}
-
-func NewScannerProxy(p Scanner_Pointer, waiter bindings.AsyncWaiter) *Scanner_Proxy {
-	return &Scanner_Proxy{
-		bindings.NewRouter(p.PassMessagePipe(), waiter),
-		bindings.NewCounter(),
-	}
-}
-
-func (p *Scanner_Proxy) Close_Proxy() {
-	p.router.Close()
-}
-
-type scanner_Scan_Params struct {
-	inQuery       string
-	inScanHandler ScanHandler_Pointer
-}
-
-func (s *scanner_Scan_Params) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_StartScan_Params) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(16, 0)
 	if err := encoder.WritePointer(); err != nil {
 		return err
@@ -678,7 +733,7 @@
 	if err := encoder.WriteString(s.inQuery); err != nil {
 		return err
 	}
-	if err := encoder.WriteInterface(s.inScanHandler.PassMessagePipe()); err != nil {
+	if err := encoder.WriteInterface(s.inHandler.PassMessagePipe()); err != nil {
 		return err
 	}
 	if err := encoder.Finish(); err != nil {
@@ -687,23 +742,23 @@
 	return nil
 }
 
-var scanner_Scan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_StartScan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{24, 0},
 }
 
-func (s *scanner_Scan_Params) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StartScan_Params) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(scanner_Scan_Params_Versions), func(i int) bool {
-		return scanner_Scan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StartScan_Params_Versions), func(i int) bool {
+		return discovery_StartScan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(scanner_Scan_Params_Versions) {
-		if scanner_Scan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StartScan_Params_Versions) {
+		if discovery_StartScan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := scanner_Scan_Params_Versions[index].Size
+		expectedSize := discovery_StartScan_Params_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -732,7 +787,7 @@
 		}
 		if handle0.IsValid() {
 			handleOwner := bindings.NewMessagePipeHandleOwner(handle0)
-			s.inScanHandler = ScanHandler_Pointer{handleOwner}
+			s.inHandler = ScanHandler_Pointer{handleOwner}
 		} else {
 			return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"}
 		}
@@ -743,14 +798,44 @@
 	return nil
 }
 
-type scanner_Scan_ResponseParams struct {
-	outHandle uint32
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStartScanParams                = "DiscoveryStartScanParams"
+	structFullIdentifier_DiscoveryStartScanParams      = "discovery.DiscoveryStartScanParams"
+	structFieldName_DiscoveryStartScanParams_InQuery   = "InQuery"
+	structFieldName_DiscoveryStartScanParams_InHandler = "InHandler"
+)
+
+func discovery_Discovery_StartScan_Params__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStartScanParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStartScanParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartScanParams_InQuery,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartScanParams_InHandler,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Identifier: &ID_discovery_ScanHandler__,
+					TypeKey: &ID_discovery_ScanHandler__},
+			},
+		}},
+	}
+}
+
+type discovery_StartScan_ResponseParams struct {
+	outScanId uint32
 	outErr    *Error
 }
 
-func (s *scanner_Scan_ResponseParams) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_StartScan_ResponseParams) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(16, 0)
-	if err := encoder.WriteUint32(s.outHandle); err != nil {
+	if err := encoder.WriteUint32(s.outScanId); err != nil {
 		return err
 	}
 	if s.outErr == nil {
@@ -769,23 +854,23 @@
 	return nil
 }
 
-var scanner_Scan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_StartScan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{24, 0},
 }
 
-func (s *scanner_Scan_ResponseParams) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StartScan_ResponseParams) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(scanner_Scan_ResponseParams_Versions), func(i int) bool {
-		return scanner_Scan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StartScan_ResponseParams_Versions), func(i int) bool {
+		return discovery_StartScan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(scanner_Scan_ResponseParams_Versions) {
-		if scanner_Scan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StartScan_ResponseParams_Versions) {
+		if discovery_StartScan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := scanner_Scan_ResponseParams_Versions[index].Size
+		expectedSize := discovery_StartScan_ResponseParams_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -797,7 +882,7 @@
 		if err != nil {
 			return err
 		}
-		s.outHandle = value0
+		s.outScanId = value0
 	}
 	if header.ElementsOrVersion >= 0 {
 		pointer0, err := decoder.ReadPointer()
@@ -819,13 +904,43 @@
 	return nil
 }
 
-func (p *Scanner_Proxy) Scan(inQuery string, inScanHandler ScanHandler_Pointer) (outHandle uint32, outErr *Error, err error) {
-	payload := &scanner_Scan_Params{
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStartScanResponseParams                = "DiscoveryStartScanResponseParams"
+	structFullIdentifier_DiscoveryStartScanResponseParams      = "discovery.DiscoveryStartScanResponseParams"
+	structFieldName_DiscoveryStartScanResponseParams_OutScanId = "OutScanId"
+	structFieldName_DiscoveryStartScanResponseParams_OutErr    = "OutErr"
+)
+
+func discovery_Discovery_StartScan_ResponseParams__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStartScanResponseParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStartScanResponseParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartScanResponseParams_OutScanId,
+			},
+			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_UinT32},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStartScanResponseParams_OutErr,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
+					TypeKey: &ID_discovery_Error__},
+			},
+		}},
+	}
+}
+
+func (p *Discovery_Proxy) StartScan(inQuery string, inHandler ScanHandler_Pointer) (outScanId uint32, outErr *Error, err error) {
+	payload := &discovery_StartScan_Params{
 		inQuery,
-		inScanHandler,
+		inHandler,
 	}
 	header := bindings.MessageHeader{
-		Type:      scanner_Scan_Name,
+		Type:      discovery_StartScan_Name,
 		Flags:     bindings.MessageExpectsResponseFlag,
 		RequestId: p.ids.Count(),
 	}
@@ -846,29 +961,29 @@
 		}
 		return
 	}
-	if got, want := readResult.Message.Header.Type, scanner_Scan_Name; got != want {
+	if got, want := readResult.Message.Header.Type, discovery_StartScan_Name; got != want {
 		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
 			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
 		}
 		return
 	}
-	var response scanner_Scan_ResponseParams
+	var response discovery_StartScan_ResponseParams
 	if err = readResult.Message.DecodePayload(&response); err != nil {
 		p.Close_Proxy()
 		return
 	}
-	outHandle = response.outHandle
+	outScanId = response.outScanId
 	outErr = response.outErr
 	return
 }
 
-type scanner_Stop_Params struct {
-	inH uint32
+type discovery_StopScan_Params struct {
+	inScanId uint32
 }
 
-func (s *scanner_Stop_Params) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_StopScan_Params) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(8, 0)
-	if err := encoder.WriteUint32(s.inH); err != nil {
+	if err := encoder.WriteUint32(s.inScanId); err != nil {
 		return err
 	}
 	if err := encoder.Finish(); err != nil {
@@ -877,23 +992,23 @@
 	return nil
 }
 
-var scanner_Stop_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_StopScan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{16, 0},
 }
 
-func (s *scanner_Stop_Params) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StopScan_Params) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(scanner_Stop_Params_Versions), func(i int) bool {
-		return scanner_Stop_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StopScan_Params_Versions), func(i int) bool {
+		return discovery_StopScan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(scanner_Stop_Params_Versions) {
-		if scanner_Stop_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StopScan_Params_Versions) {
+		if discovery_StopScan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := scanner_Stop_Params_Versions[index].Size
+		expectedSize := discovery_StopScan_Params_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -905,7 +1020,7 @@
 		if err != nil {
 			return err
 		}
-		s.inH = value0
+		s.inScanId = value0
 	}
 	if err := decoder.Finish(); err != nil {
 		return err
@@ -913,11 +1028,32 @@
 	return nil
 }
 
-type scanner_Stop_ResponseParams struct {
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStopScanParams               = "DiscoveryStopScanParams"
+	structFullIdentifier_DiscoveryStopScanParams     = "discovery.DiscoveryStopScanParams"
+	structFieldName_DiscoveryStopScanParams_InScanId = "InScanId"
+)
+
+func discovery_Discovery_StopScan_Params__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStopScanParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStopScanParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStopScanParams_InScanId,
+			},
+			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_UinT32},
+		}},
+	}
+}
+
+type discovery_StopScan_ResponseParams struct {
 	outErr *Error
 }
 
-func (s *scanner_Stop_ResponseParams) Encode(encoder *bindings.Encoder) error {
+func (s *discovery_StopScan_ResponseParams) Encode(encoder *bindings.Encoder) error {
 	encoder.StartStruct(8, 0)
 	if s.outErr == nil {
 		encoder.WriteNullPointer()
@@ -935,23 +1071,23 @@
 	return nil
 }
 
-var scanner_Stop_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
+var discovery_StopScan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
 	bindings.DataHeader{16, 0},
 }
 
-func (s *scanner_Stop_ResponseParams) Decode(decoder *bindings.Decoder) error {
+func (s *discovery_StopScan_ResponseParams) Decode(decoder *bindings.Decoder) error {
 	header, err := decoder.StartStruct()
 	if err != nil {
 		return err
 	}
-	index := sort.Search(len(scanner_Stop_ResponseParams_Versions), func(i int) bool {
-		return scanner_Stop_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
+	index := sort.Search(len(discovery_StopScan_ResponseParams_Versions), func(i int) bool {
+		return discovery_StopScan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
 	})
-	if index < len(scanner_Stop_ResponseParams_Versions) {
-		if scanner_Stop_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
+	if index < len(discovery_StopScan_ResponseParams_Versions) {
+		if discovery_StopScan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
 			index--
 		}
-		expectedSize := scanner_Stop_ResponseParams_Versions[index].Size
+		expectedSize := discovery_StopScan_ResponseParams_Versions[index].Size
 		if expectedSize != header.Size {
 			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
 				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
@@ -978,12 +1114,36 @@
 	return nil
 }
 
-func (p *Scanner_Proxy) Stop(inH uint32) (outErr *Error, err error) {
-	payload := &scanner_Stop_Params{
-		inH,
+// String names and labels used by the MojomStruct types.
+var (
+	structName_DiscoveryStopScanResponseParams             = "DiscoveryStopScanResponseParams"
+	structFullIdentifier_DiscoveryStopScanResponseParams   = "discovery.DiscoveryStopScanResponseParams"
+	structFieldName_DiscoveryStopScanResponseParams_OutErr = "OutErr"
+)
+
+func discovery_Discovery_StopScan_ResponseParams__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_DiscoveryStopScanResponseParams,
+			FullIdentifier: &structFullIdentifier_DiscoveryStopScanResponseParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_DiscoveryStopScanResponseParams_OutErr,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Nullable: true, Identifier: &ID_discovery_Error__,
+					TypeKey: &ID_discovery_Error__},
+			},
+		}},
+	}
+}
+
+func (p *Discovery_Proxy) StopScan(inScanId uint32) (outErr *Error, err error) {
+	payload := &discovery_StopScan_Params{
+		inScanId,
 	}
 	header := bindings.MessageHeader{
-		Type:      scanner_Stop_Name,
+		Type:      discovery_StopScan_Name,
 		Flags:     bindings.MessageExpectsResponseFlag,
 		RequestId: p.ids.Count(),
 	}
@@ -1004,13 +1164,13 @@
 		}
 		return
 	}
-	if got, want := readResult.Message.Header.Type, scanner_Stop_Name; got != want {
+	if got, want := readResult.Message.Header.Type, discovery_StopScan_Name; got != want {
 		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
 			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
 		}
 		return
 	}
-	var response scanner_Stop_ResponseParams
+	var response discovery_StopScan_ResponseParams
 	if err = readResult.Message.DecodePayload(&response); err != nil {
 		p.Close_Proxy()
 		return
@@ -1019,58 +1179,112 @@
 	return
 }
 
-type scanner_Stub struct {
+type discovery_Stub struct {
 	connector *bindings.Connector
-	impl      Scanner
+	impl      Discovery
 }
 
-func NewScannerStub(r Scanner_Request, impl Scanner, waiter bindings.AsyncWaiter) *bindings.Stub {
+func NewDiscoveryStub(r Discovery_Request, impl Discovery, waiter bindings.AsyncWaiter) *bindings.Stub {
 	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
-	return bindings.NewStub(connector, &scanner_Stub{connector, impl})
+	return bindings.NewStub(connector, &discovery_Stub{connector, impl})
 }
 
-func (f *Scanner_Request) ServiceDescription() service_describer.ServiceDescription {
-	return &Scanner_ServiceDescription{}
+var (
+	interfaceName_Discovery                        = "Discovery"
+	interfaceFullIdentifier_Discovery              = "discovery.Discovery"
+	interfaceMethodName_Discovery_StartAdvertising = "StartAdvertising"
+	interfaceMethodName_Discovery_StopAdvertising  = "StopAdvertising"
+	interfaceMethodName_Discovery_StartScan        = "StartScan"
+	interfaceMethodName_Discovery_StopScan         = "StopScan"
+)
+
+func discovery_Discovery__() mojom_types.MojomInterface {
+	responseParamsMap := make(map[string]*mojom_types.MojomStruct)
+	_ = responseParamsMap // To avoid the declared but unused compiler error
+	mstruct_StartAdvertising := discovery_Discovery_StartAdvertising_ResponseParams__()
+	responseParamsMap[interfaceMethodName_Discovery_StartAdvertising] = &mstruct_StartAdvertising
+	mstruct_StopAdvertising := discovery_Discovery_StopAdvertising_ResponseParams__()
+	responseParamsMap[interfaceMethodName_Discovery_StopAdvertising] = &mstruct_StopAdvertising
+	mstruct_StartScan := discovery_Discovery_StartScan_ResponseParams__()
+	responseParamsMap[interfaceMethodName_Discovery_StartScan] = &mstruct_StartScan
+	mstruct_StopScan := discovery_Discovery_StopScan_ResponseParams__()
+	responseParamsMap[interfaceMethodName_Discovery_StopScan] = &mstruct_StopScan
+	return mojom_types.MojomInterface{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &interfaceName_Discovery,
+			FullIdentifier: &interfaceFullIdentifier_Discovery,
+		},
+		Methods: map[uint32]mojom_types.MojomMethod{discovery_StartAdvertising_Name: mojom_types.MojomMethod{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &interfaceMethodName_Discovery_StartAdvertising,
+			},
+			Parameters:     discovery_Discovery_StartAdvertising_Params__(),
+			ResponseParams: responseParamsMap[interfaceMethodName_Discovery_StartAdvertising],
+		}, discovery_StopAdvertising_Name: mojom_types.MojomMethod{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &interfaceMethodName_Discovery_StopAdvertising,
+			},
+			Parameters:     discovery_Discovery_StopAdvertising_Params__(),
+			ResponseParams: responseParamsMap[interfaceMethodName_Discovery_StopAdvertising],
+		}, discovery_StartScan_Name: mojom_types.MojomMethod{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &interfaceMethodName_Discovery_StartScan,
+			},
+			Parameters:     discovery_Discovery_StartScan_Params__(),
+			ResponseParams: responseParamsMap[interfaceMethodName_Discovery_StartScan],
+		}, discovery_StopScan_Name: mojom_types.MojomMethod{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &interfaceMethodName_Discovery_StopScan,
+			},
+			Parameters:     discovery_Discovery_StopScan_Params__(),
+			ResponseParams: responseParamsMap[interfaceMethodName_Discovery_StopScan],
+		}},
+	}
 }
 
-type Scanner_ServiceDescription struct{}
-
-func (sd *Scanner_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
-	err = fmt.Errorf("GetTopLevelInterface not implemented")
-	return
+func (f *Discovery_Request) ServiceDescription() service_describer.ServiceDescription {
+	return &Discovery_ServiceDescription{}
 }
 
-func (sd *Scanner_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
-	err = fmt.Errorf("GetTypeDefinition not implemented")
-	return
+type Discovery_ServiceDescription struct{}
+
+func (sd *Discovery_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
+	return discovery_Discovery__(), nil
 }
 
-func (sd *Scanner_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
-	err = fmt.Errorf("GetAllTypeDefinitions not implemented")
-	return
+func (sd *Discovery_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
+	if udt, ok := GetAllMojomTypeDefinitions()[inTypeKey]; ok {
+		return udt, nil
+	}
+	return nil, fmt.Errorf("%s_ServiceDescription does not recognize %s", "Discovery", inTypeKey)
 }
 
-var _ service_describer.ServiceDescription = (*Scanner_ServiceDescription)(nil)
+func (sd *Discovery_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
+	o := GetAllMojomTypeDefinitions()
+	return &o, nil
+}
 
-func (s *scanner_Stub) Accept(message *bindings.Message) (err error) {
+var _ service_describer.ServiceDescription = (*Discovery_ServiceDescription)(nil)
+
+func (s *discovery_Stub) Accept(message *bindings.Message) (err error) {
 	switch message.Header.Type {
-	case scanner_Scan_Name:
+	case discovery_StartAdvertising_Name:
 		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
 			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
 				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
 			}
 		}
-		var request scanner_Scan_Params
+		var request discovery_StartAdvertising_Params
 		if err := message.DecodePayload(&request); err != nil {
 			return err
 		}
-		var response scanner_Scan_ResponseParams
-		response.outHandle, response.outErr, err = s.impl.Scan(request.inQuery, request.inScanHandler)
+		var response discovery_StartAdvertising_ResponseParams
+		response.outInstanceId, response.outErr, err = s.impl.StartAdvertising(request.inService, request.inVisibility)
 		if err != nil {
 			return
 		}
 		header := bindings.MessageHeader{
-			Type:      scanner_Scan_Name,
+			Type:      discovery_StartAdvertising_Name,
 			Flags:     bindings.MessageIsResponseFlag,
 			RequestId: message.Header.RequestId,
 		}
@@ -1079,23 +1293,73 @@
 			return err
 		}
 		return s.connector.WriteMessage(message)
-	case scanner_Stop_Name:
+	case discovery_StopAdvertising_Name:
 		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
 			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
 				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
 			}
 		}
-		var request scanner_Stop_Params
+		var request discovery_StopAdvertising_Params
 		if err := message.DecodePayload(&request); err != nil {
 			return err
 		}
-		var response scanner_Stop_ResponseParams
-		response.outErr, err = s.impl.Stop(request.inH)
+		var response discovery_StopAdvertising_ResponseParams
+		response.outErr, err = s.impl.StopAdvertising(request.inInstanceId)
 		if err != nil {
 			return
 		}
 		header := bindings.MessageHeader{
-			Type:      scanner_Stop_Name,
+			Type:      discovery_StopAdvertising_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case discovery_StartScan_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request discovery_StartScan_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response discovery_StartScan_ResponseParams
+		response.outScanId, response.outErr, err = s.impl.StartScan(request.inQuery, request.inHandler)
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      discovery_StartScan_Name,
+			Flags:     bindings.MessageIsResponseFlag,
+			RequestId: message.Header.RequestId,
+		}
+		message, err = bindings.EncodeMessage(header, &response)
+		if err != nil {
+			return err
+		}
+		return s.connector.WriteMessage(message)
+	case discovery_StopScan_Name:
+		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
+			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
+				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
+			}
+		}
+		var request discovery_StopScan_Params
+		if err := message.DecodePayload(&request); err != nil {
+			return err
+		}
+		var response discovery_StopScan_ResponseParams
+		response.outErr, err = s.impl.StopScan(request.inScanId)
+		if err != nil {
+			return
+		}
+		header := bindings.MessageHeader{
+			Type:      discovery_StopScan_Name,
 			Flags:     bindings.MessageIsResponseFlag,
 			RequestId: message.Header.RequestId,
 		}
@@ -1237,6 +1501,30 @@
 	return nil
 }
 
+// String names and labels used by the MojomStruct types.
+var (
+	structName_ScanHandlerUpdateParams               = "ScanHandlerUpdateParams"
+	structFullIdentifier_ScanHandlerUpdateParams     = "discovery.ScanHandlerUpdateParams"
+	structFieldName_ScanHandlerUpdateParams_InUpdate = "InUpdate"
+)
+
+func discovery_ScanHandler_Update_Params__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_ScanHandlerUpdateParams,
+			FullIdentifier: &structFullIdentifier_ScanHandlerUpdateParams,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_ScanHandlerUpdateParams_InUpdate,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Identifier: &ID_discovery_Update__,
+					TypeKey: &ID_discovery_Update__},
+			},
+		}},
+	}
+}
+
 func (p *ScanHandler_Proxy) Update(inUpdate Update) (err error) {
 	payload := &scanHandler_Update_Params{
 		inUpdate,
@@ -1268,6 +1556,30 @@
 	return bindings.NewStub(connector, &scanHandler_Stub{connector, impl})
 }
 
+var (
+	interfaceName_ScanHandler              = "ScanHandler"
+	interfaceFullIdentifier_ScanHandler    = "discovery.ScanHandler"
+	interfaceMethodName_ScanHandler_Update = "Update"
+)
+
+func discovery_ScanHandler__() mojom_types.MojomInterface {
+	responseParamsMap := make(map[string]*mojom_types.MojomStruct)
+	_ = responseParamsMap // To avoid the declared but unused compiler error
+	return mojom_types.MojomInterface{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &interfaceName_ScanHandler,
+			FullIdentifier: &interfaceFullIdentifier_ScanHandler,
+		},
+		Methods: map[uint32]mojom_types.MojomMethod{scanHandler_Update_Name: mojom_types.MojomMethod{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &interfaceMethodName_ScanHandler_Update,
+			},
+			Parameters:     discovery_ScanHandler_Update_Params__(),
+			ResponseParams: responseParamsMap[interfaceMethodName_ScanHandler_Update],
+		}},
+	}
+}
+
 func (f *ScanHandler_Request) ServiceDescription() service_describer.ServiceDescription {
 	return &ScanHandler_ServiceDescription{}
 }
@@ -1275,18 +1587,19 @@
 type ScanHandler_ServiceDescription struct{}
 
 func (sd *ScanHandler_ServiceDescription) GetTopLevelInterface() (outMojomInterface mojom_types.MojomInterface, err error) {
-	err = fmt.Errorf("GetTopLevelInterface not implemented")
-	return
+	return discovery_ScanHandler__(), nil
 }
 
 func (sd *ScanHandler_ServiceDescription) GetTypeDefinition(inTypeKey string) (outType mojom_types.UserDefinedType, err error) {
-	err = fmt.Errorf("GetTypeDefinition not implemented")
-	return
+	if udt, ok := GetAllMojomTypeDefinitions()[inTypeKey]; ok {
+		return udt, nil
+	}
+	return nil, fmt.Errorf("%s_ServiceDescription does not recognize %s", "ScanHandler", inTypeKey)
 }
 
 func (sd *ScanHandler_ServiceDescription) GetAllTypeDefinitions() (outDefinitions *map[string]mojom_types.UserDefinedType, err error) {
-	err = fmt.Errorf("GetAllTypeDefinitions not implemented")
-	return
+	o := GetAllMojomTypeDefinitions()
+	return &o, nil
 }
 
 var _ service_describer.ServiceDescription = (*ScanHandler_ServiceDescription)(nil)
@@ -1322,10 +1635,11 @@
 	InterfaceName string
 	Attrs         *map[string]string
 	Addrs         []string
+	Attachments   *map[string][]uint8
 }
 
 func (s *Service) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(40, 0)
+	encoder.StartStruct(48, 0)
 	if s.InstanceId == nil {
 		encoder.WriteNullPointer()
 	} else {
@@ -1416,6 +1730,61 @@
 	if err := encoder.Finish(); err != nil {
 		return err
 	}
+	if s.Attachments == nil {
+		encoder.WriteNullPointer()
+	} else {
+		if err := encoder.WritePointer(); err != nil {
+			return err
+		}
+		encoder.StartMap()
+		{
+			var keys0 []string
+			var values0 [][]uint8
+			for key0, value0 := range *s.Attachments {
+				keys0 = append(keys0, key0)
+				values0 = append(values0, value0)
+			}
+			if err := encoder.WritePointer(); err != nil {
+				return err
+			}
+			encoder.StartArray(uint32(len(keys0)), 64)
+			for _, elem1 := range keys0 {
+				if err := encoder.WritePointer(); err != nil {
+					return err
+				}
+				if err := encoder.WriteString(elem1); err != nil {
+					return err
+				}
+			}
+			if err := encoder.Finish(); err != nil {
+				return err
+			}
+			if err := encoder.WritePointer(); err != nil {
+				return err
+			}
+			encoder.StartArray(uint32(len(values0)), 64)
+			for _, elem1 := range values0 {
+				if err := encoder.WritePointer(); err != nil {
+					return err
+				}
+				encoder.StartArray(uint32(len(elem1)), 8)
+				for _, elem2 := range elem1 {
+					if err := encoder.WriteUint8(elem2); err != nil {
+						return err
+					}
+				}
+				if err := encoder.Finish(); err != nil {
+					return err
+				}
+			}
+			if err := encoder.Finish(); err != nil {
+				return err
+			}
+		}
+		if err := encoder.Finish(); err != nil {
+			return err
+		}
+	}
 	if err := encoder.Finish(); err != nil {
 		return err
 	}
@@ -1423,7 +1792,7 @@
 }
 
 var service_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{48, 0},
+	bindings.DataHeader{56, 0},
 }
 
 func (s *Service) Decode(decoder *bindings.Decoder) error {
@@ -1621,12 +1990,181 @@
 			}
 		}
 	}
+	if header.ElementsOrVersion >= 0 {
+		pointer0, err := decoder.ReadPointer()
+		if err != nil {
+			return err
+		}
+		if pointer0 == 0 {
+			s.Attachments = nil
+		} else {
+			s.Attachments = new(map[string][]uint8)
+			if err := decoder.StartMap(); err != nil {
+				return err
+			}
+			var keys0 []string
+			{
+				pointer1, err := decoder.ReadPointer()
+				if err != nil {
+					return err
+				}
+				if pointer1 == 0 {
+					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+				} else {
+					len1, err := decoder.StartArray(64)
+					if err != nil {
+						return err
+					}
+					keys0 = make([]string, len1)
+					for i1 := uint32(0); i1 < len1; i1++ {
+						pointer2, err := decoder.ReadPointer()
+						if err != nil {
+							return err
+						}
+						if pointer2 == 0 {
+							return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+						} else {
+							value2, err := decoder.ReadString()
+							if err != nil {
+								return err
+							}
+							keys0[i1] = value2
+						}
+					}
+					if err := decoder.Finish(); err != nil {
+						return err
+					}
+				}
+			}
+			var values0 [][]uint8
+			{
+				pointer1, err := decoder.ReadPointer()
+				if err != nil {
+					return err
+				}
+				if pointer1 == 0 {
+					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+				} else {
+					len1, err := decoder.StartArray(64)
+					if err != nil {
+						return err
+					}
+					values0 = make([][]uint8, len1)
+					for i1 := uint32(0); i1 < len1; i1++ {
+						pointer2, err := decoder.ReadPointer()
+						if err != nil {
+							return err
+						}
+						if pointer2 == 0 {
+							return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
+						} else {
+							len2, err := decoder.StartArray(8)
+							if err != nil {
+								return err
+							}
+							values0[i1] = make([]uint8, len2)
+							for i2 := uint32(0); i2 < len2; i2++ {
+								value3, err := decoder.ReadUint8()
+								if err != nil {
+									return err
+								}
+								values0[i1][i2] = value3
+							}
+							if err := decoder.Finish(); err != nil {
+								return err
+							}
+						}
+					}
+					if err := decoder.Finish(); err != nil {
+						return err
+					}
+				}
+			}
+			if len(keys0) != len(values0) {
+				return &bindings.ValidationError{bindings.DifferentSizedArraysInMap,
+					fmt.Sprintf("Number of keys %d is different from number of values %d", len(keys0), len(values0)),
+				}
+			}
+			if err := decoder.Finish(); err != nil {
+				return err
+			}
+			len0 := len(keys0)
+			map0 := make(map[string][]uint8)
+			for i0 := 0; i0 < len0; i0++ {
+				map0[keys0[i0]] = values0[i0]
+			}
+			(*s.Attachments) = map0
+		}
+	}
 	if err := decoder.Finish(); err != nil {
 		return err
 	}
 	return nil
 }
 
+// String names and labels used by the MojomStruct types.
+var (
+	structName_Service                    = "Service"
+	structFullIdentifier_Service          = "discovery.Service"
+	structFieldName_Service_InstanceId    = "InstanceId"
+	structFieldName_Service_InstanceName  = "InstanceName"
+	structFieldName_Service_InterfaceName = "InterfaceName"
+	structFieldName_Service_Attrs         = "Attrs"
+	structFieldName_Service_Addrs         = "Addrs"
+	structFieldName_Service_Attachments   = "Attachments"
+)
+
+func discovery_Service__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_Service,
+			FullIdentifier: &structFullIdentifier_Service,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Service_InstanceId,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Service_InstanceName,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{true}},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Service_InterfaceName,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Service_Attrs,
+			},
+			Type: &mojom_types.TypeMapType{
+				Value: mojom_types.MapType{Nullable: true, KeyType: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+					ValueType: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+				},
+			},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Service_Addrs,
+			},
+			Type: &mojom_types.TypeArrayType{
+				Value: mojom_types.ArrayType{ElementType: &mojom_types.TypeStringType{mojom_types.StringType{false}}},
+			},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Service_Attachments,
+			},
+			Type: &mojom_types.TypeMapType{
+				Value: mojom_types.MapType{Nullable: true, KeyType: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+					ValueType: &mojom_types.TypeArrayType{
+						Value: mojom_types.ArrayType{ElementType: &mojom_types.TypeSimpleType{mojom_types.SimpleType_UinT8}},
+					},
+				},
+			},
+		}},
+	}
+}
+
 type Update struct {
 	Service    Service
 	UpdateType UpdateType
@@ -1698,6 +2236,39 @@
 	return nil
 }
 
+// String names and labels used by the MojomStruct types.
+var (
+	structName_Update                 = "Update"
+	structFullIdentifier_Update       = "discovery.Update"
+	structFieldName_Update_Service    = "Service"
+	structFieldName_Update_UpdateType = "UpdateType"
+)
+
+func discovery_Update__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_Update,
+			FullIdentifier: &structFullIdentifier_Update,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Update_Service,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Identifier: &ID_discovery_Service__,
+					TypeKey: &ID_discovery_Service__},
+			},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Update_UpdateType,
+			},
+			Type: &mojom_types.TypeTypeReference{
+				Value: mojom_types.TypeReference{Identifier: &ID_discovery_UpdateType__,
+					TypeKey: &ID_discovery_UpdateType__},
+			},
+		}},
+	}
+}
+
 type Error struct {
 	Id     string
 	Action int32
@@ -1792,3 +2363,36 @@
 	}
 	return nil
 }
+
+// String names and labels used by the MojomStruct types.
+var (
+	structName_Error             = "Error"
+	structFullIdentifier_Error   = "discovery.Error"
+	structFieldName_Error_Id     = "Id"
+	structFieldName_Error_Action = "Action"
+	structFieldName_Error_Msg    = "Msg"
+)
+
+func discovery_Error__() mojom_types.MojomStruct {
+	return mojom_types.MojomStruct{
+		DeclData: &mojom_types.DeclarationData{
+			ShortName:      &structName_Error,
+			FullIdentifier: &structFullIdentifier_Error,
+		}, Fields: []mojom_types.StructField{mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Error_Id,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Error_Action,
+			},
+			Type: &mojom_types.TypeSimpleType{mojom_types.SimpleType_InT32},
+		}, mojom_types.StructField{
+			DeclData: &mojom_types.DeclarationData{
+				ShortName: &structFieldName_Error_Msg,
+			},
+			Type: &mojom_types.TypeStringType{mojom_types.StringType{false}},
+		}},
+	}
+}
diff --git a/go/src/vanadium/discovery/discovery.go b/go/src/vanadium/discovery/discovery.go
index 56932d0..229dd68 100644
--- a/go/src/vanadium/discovery/discovery.go
+++ b/go/src/vanadium/discovery/discovery.go
@@ -23,88 +23,65 @@
 //#include "mojo/public/c/system/types.h"
 import "C"
 
-type discoveryDelegate struct {
-	// mu protects stubs.  All calls to methods on the delegate by
-	// mojo will be done in the same goroutine.  We need mu so
-	// we can clean up stubs that fail because of pipe errors because
-	// each stub serves all its requests in its own goroutine.
-	mu    sync.Mutex
-	stubs map[*bindings.Stub]struct{}
-
-	ctx *context.T
-
+type delegate struct {
+	ctx      *context.T
 	shutdown v23.Shutdown
-	impl     *internal.DiscoveryService
+
+	mu    sync.Mutex
+	stubs map[*bindings.Stub]struct{} // GUARDED_BY(mu)
 }
 
-func (d *discoveryDelegate) Initialize(mctx application.Context) {
+func (d *delegate) Initialize(mctx application.Context) {
 	// TODO(bjornick): Calling init multiple times in the same process
 	// will be bad.  For now, this is ok because this is the only
 	// vanadium service that will be used in the demos and each go library
 	// will be in its own process.
 	d.ctx, d.shutdown = v23.Init(mctx)
-	d.impl = internal.NewDiscoveryService(d.ctx)
 }
 
-func (d *discoveryDelegate) addAndServeStub(stub *bindings.Stub) {
+func (d *delegate) Create(request mojom.Discovery_Request) {
+	discovery := internal.NewDiscovery(d.ctx)
+	stub := mojom.NewDiscoveryStub(request, discovery, bindings.GetAsyncWaiter())
 	d.mu.Lock()
 	d.stubs[stub] = struct{}{}
 	d.mu.Unlock()
+
 	go func() {
+		defer discovery.Close()
+
 		for {
 			if err := stub.ServeRequest(); err != nil {
-				connectionErr, ok := err.(*bindings.ConnectionError)
-				if !ok || !connectionErr.Closed() {
+				connErr, ok := err.(*bindings.ConnectionError)
+				if !ok || !connErr.Closed() {
 					d.ctx.Error(err)
 				}
 				break
 			}
 		}
+
 		d.mu.Lock()
 		delete(d.stubs, stub)
 		d.mu.Unlock()
 	}()
 }
 
-type advertiseFactory struct {
-	d *discoveryDelegate
+func (d *delegate) AcceptConnection(connection *application.Connection) {
+	connection.ProvideServices(&mojom.Discovery_ServiceFactory{d})
 }
 
-func (a *advertiseFactory) Create(request mojom.Advertiser_Request) {
-	stub := mojom.NewAdvertiserStub(request, a.d.impl, bindings.GetAsyncWaiter())
-	a.d.addAndServeStub(stub)
-}
-
-type scannerFactory struct {
-	d *discoveryDelegate
-}
-
-func (s *scannerFactory) Create(request mojom.Scanner_Request) {
-	stub := mojom.NewScannerStub(request, s.d.impl, bindings.GetAsyncWaiter())
-	s.d.addAndServeStub(stub)
-}
-
-func (d *discoveryDelegate) AcceptConnection(connection *application.Connection) {
-	advFactory := &advertiseFactory{d: d}
-	scanFactory := &scannerFactory{d: d}
-	connection.ProvideServices(&mojom.Advertiser_ServiceFactory{advFactory}, &mojom.Scanner_ServiceFactory{scanFactory})
-}
-
-func (d *discoveryDelegate) Quit() {
-	d.impl.StopAll()
-	d.shutdown()
+func (d *delegate) Quit() {
 	d.mu.Lock()
 	for stub := range d.stubs {
 		stub.Close()
 	}
 	d.mu.Unlock()
+	d.shutdown()
 }
 
 //export MojoMain
 func MojoMain(handle C.MojoHandle) C.MojoResult {
-	application.Run(&discoveryDelegate{stubs: map[*bindings.Stub]struct{}{}}, system.MojoHandle(handle))
+	application.Run(&delegate{stubs: map[*bindings.Stub]struct{}{}}, system.MojoHandle(handle))
 	return C.MOJO_RESULT_OK
 }
 
-func main() {
-}
+func main() {}
diff --git a/go/src/vanadium/discovery/internal/discovery.go b/go/src/vanadium/discovery/internal/discovery.go
index 5d28a81..2b582bb 100644
--- a/go/src/vanadium/discovery/internal/discovery.go
+++ b/go/src/vanadium/discovery/internal/discovery.go
@@ -8,6 +8,7 @@
 	"sync"
 
 	"mojo/public/go/bindings"
+
 	mojom "mojom/vanadium/discovery"
 
 	"v.io/v23"
@@ -20,28 +21,26 @@
 const pkgPath = "mojo/vanadium/discovery/vanadium/discovery"
 
 var (
-	errInvalidHandle = verror.Register(pkgPath+".errInvalidHandle", verror.NoRetry, "{1:}{2:} handle not valid")
+	errInvalidInstanceId = verror.Register(pkgPath+".errInvalidInstanceId", verror.NoRetry, "{1:}{2:} instance id not valid")
+	errInvalidScanId     = verror.Register(pkgPath+".errInvalidScanId", verror.NoRetry, "{1:}{2:} scan id not valid")
 )
 
-type handleT uint32
+type DiscoveryCloser interface {
+	mojom.Discovery
 
-// DiscoveryService implements the mojom interface mojom/vanadium/discovery.DiscoveryService.  It
-// is basically a thin wrapper around the Vanadium Discovery API.
-type DiscoveryService struct {
-	ctx       *context.T
-	discovery discovery.T
+	// Close closes all active tasks.
+	Close()
+}
 
-	// mu protects pending* and next*
-	mu sync.Mutex
+// mdiscovery is basically a thin wrapper around the Vanadium discovery API.
+type mdiscovery struct {
+	ctx *context.T
+	d   discovery.T
 
-	// The id to assign the next advertisement.
-	nextAdv handleT
-	// A map of advertisement ids to the cancellation function.
-	activeAdvs map[handleT]func()
-	// The id to assign to the next scan.
-	nextScan handleT
-	// A map of scan id to the cancellataion func()
-	activeScans map[handleT]func()
+	mu          sync.Mutex
+	activeAdvs  map[string]func() // GUARDED_BY(mu)
+	activeScans map[uint32]func() // GUARDED_BY(mu)
+	nextScanId  uint32            // GUARDED_BY(mu)
 }
 
 func v2mError(err error) *mojom.Error {
@@ -52,70 +51,6 @@
 	}
 }
 
-// NewDiscoveryService returns a new DiscoveryService bound to the context and the Vanadium
-// Discovery implementation passed in.
-func NewDiscoveryService(ctx *context.T) *DiscoveryService {
-	return &DiscoveryService{
-		ctx:         ctx,
-		discovery:   v23.GetDiscovery(ctx),
-		nextAdv:     1,
-		activeAdvs:  map[handleT]func(){},
-		activeScans: map[handleT]func(){},
-	}
-}
-
-func (d *DiscoveryService) Advertise(service mojom.Service, visibility *[]string) (uint32, string, *mojom.Error, error) {
-	vService := discovery.Service{
-		InterfaceName: service.InterfaceName,
-		Addrs:         service.Addrs,
-	}
-	if service.InstanceId != nil {
-		vService.InstanceId = *service.InstanceId
-	}
-	if service.InstanceName != nil {
-		vService.InstanceName = *service.InstanceName
-	}
-	if service.Attrs != nil {
-		vService.Attrs = *service.Attrs
-	}
-	var vVisibility []security.BlessingPattern
-	if visibility != nil {
-		vVisibility := make([]security.BlessingPattern, len(*visibility))
-		for i, p := range *visibility {
-			vVisibility[i] = security.BlessingPattern(p)
-		}
-	}
-
-	ctx, cancel := context.WithCancel(d.ctx)
-	done, err := d.discovery.Advertise(ctx, &vService, vVisibility)
-	if err != nil {
-		cancel()
-		return 0, "", v2mError(err), nil
-	}
-	d.mu.Lock()
-	currId := d.nextAdv
-	d.activeAdvs[currId] = func() {
-		cancel()
-		<-done
-	}
-	d.nextAdv += 2
-	d.mu.Unlock()
-	return uint32(currId), vService.InstanceId, nil, nil
-}
-
-func (d *DiscoveryService) stopAdvertising(handle uint32) (*mojom.Error, error) {
-	d.mu.Lock()
-	stop := d.activeAdvs[handleT(handle)]
-	if stop == nil {
-		d.mu.Unlock()
-		return v2mError(verror.New(errInvalidHandle, d.ctx)), nil
-	}
-	delete(d.activeAdvs, handleT(handle))
-	d.mu.Unlock()
-	stop()
-	return nil, nil
-}
-
 func v2mService(s discovery.Service) mojom.Service {
 	mService := mojom.Service{
 		InterfaceName: s.InterfaceName,
@@ -128,78 +63,171 @@
 		mService.InstanceName = &s.InstanceName
 	}
 	if len(s.Attrs) > 0 {
-		attr := map[string]string(s.Attrs)
-		mService.Attrs = &attr
+		attrs := map[string]string(s.Attrs)
+		mService.Attrs = &attrs
+	}
+	if len(s.Attachments) > 0 {
+		attachments := map[string][]byte(s.Attachments)
+		mService.Attachments = &attachments
 	}
 	return mService
 }
 
-func (d *DiscoveryService) Scan(query string, scanHandler mojom.ScanHandler_Pointer) (uint32, *mojom.Error, error) {
+func (d *mdiscovery) StartAdvertising(service mojom.Service, visibility *[]string) (string, *mojom.Error, error) {
+	vService := discovery.Service{
+		InterfaceName: service.InterfaceName,
+		Addrs:         service.Addrs,
+	}
+	if service.InstanceId != nil {
+		vService.InstanceId = *service.InstanceId
+	}
+	if service.InstanceName != nil {
+		vService.InstanceName = *service.InstanceName
+	}
+	if service.Attrs != nil {
+		vService.Attrs = *service.Attrs
+	}
+	if service.Attachments != nil {
+		vService.Attachments = *service.Attachments
+	}
+	var vVisibility []security.BlessingPattern
+	if visibility != nil {
+		vVisibility := make([]security.BlessingPattern, len(*visibility))
+		for i, p := range *visibility {
+			vVisibility[i] = security.BlessingPattern(p)
+		}
+	}
+
 	ctx, cancel := context.WithCancel(d.ctx)
-	scanCh, err := d.discovery.Scan(ctx, query)
+	done, err := d.d.Advertise(ctx, &vService, vVisibility)
 	if err != nil {
 		cancel()
-		return 0, v2mError(err), nil
+		return "", v2mError(err), nil
 	}
-	d.mu.Lock()
-	currId := d.nextScan
-	d.activeScans[currId] = cancel
-	d.nextScan += 2
-	d.mu.Unlock()
+	stop := func() {
+		cancel()
+		<-done
+	}
 
-	go func() {
-		proxy := mojom.NewScanHandlerProxy(scanHandler, bindings.GetAsyncWaiter())
-		for v := range scanCh {
-			switch value := v.(type) {
-			case discovery.UpdateFound:
-				update := mojom.Update{
-					Service:    v2mService(value.Value.Service),
-					UpdateType: mojom.UpdateType_Found,
-				}
-				proxy.Update(update)
-			case discovery.UpdateLost:
-				update := mojom.Update{
-					Service:    v2mService(value.Value.Service),
-					UpdateType: mojom.UpdateType_Lost,
-				}
-				proxy.Update(update)
-			}
-		}
-	}()
-	return uint32(currId), nil, nil
+	d.mu.Lock()
+	d.activeAdvs[vService.InstanceId] = stop
+	d.mu.Unlock()
+	return vService.InstanceId, nil, nil
 }
 
-// Stop stops the scan.
-func (d *DiscoveryService) Stop(handle uint32) (*mojom.Error, error) {
-	if handle%2 == 0 {
-		return d.stopScan(handle)
-	}
-	return d.stopAdvertising(handle)
-}
-
-func (d *DiscoveryService) stopScan(handle uint32) (*mojom.Error, error) {
+func (d *mdiscovery) StopAdvertising(instanceId string) (*mojom.Error, error) {
 	d.mu.Lock()
-	cancel := d.activeScans[handleT(handle)]
-	if cancel == nil {
-		d.mu.Unlock()
-		return v2mError(verror.New(errInvalidHandle, d.ctx)), nil
-	}
-	delete(d.activeScans, handleT(handle))
+	stop := d.activeAdvs[instanceId]
+	delete(d.activeAdvs, instanceId)
 	d.mu.Unlock()
-	cancel()
+	if stop == nil {
+		return v2mError(verror.New(errInvalidInstanceId, d.ctx)), nil
+	}
+	stop()
 	return nil, nil
 }
 
-// Stop Stops all scans and advertisements.
-func (d *DiscoveryService) StopAll() {
-	d.mu.Lock()
-	for _, cancel := range d.activeScans {
+func (d *mdiscovery) StartScan(query string, handlerPtr mojom.ScanHandler_Pointer) (uint32, *mojom.Error, error) {
+	// There is no way to mock _Pointer or _Request types. So we put StartScan()
+	// logic into a separate function startScan() for unit testing.
+	proxy := mojom.NewScanHandlerProxy(handlerPtr, bindings.GetAsyncWaiter())
+	return d.startScan(query, proxy)
+}
+
+type scanHandlerProxy interface {
+	mojom.ScanHandler
+	Close_Proxy()
+}
+
+func (d *mdiscovery) startScan(query string, proxy scanHandlerProxy) (uint32, *mojom.Error, error) {
+	ctx, cancel := context.WithCancel(d.ctx)
+	scanCh, err := d.d.Scan(ctx, query)
+	if err != nil {
 		cancel()
+		proxy.Close_Proxy()
+		return 0, v2mError(err), nil
 	}
 
-	for _, cancel := range d.activeAdvs {
-		cancel()
-	}
-	d.discovery.Close()
+	d.mu.Lock()
+	scanId := d.nextScanId
+	d.activeScans[scanId] = cancel
+	d.nextScanId++
 	d.mu.Unlock()
+
+	go func() {
+		defer proxy.Close_Proxy()
+
+		for update := range scanCh {
+			var mupdate mojom.Update
+			switch u := update.(type) {
+			case discovery.UpdateFound:
+				mupdate = mojom.Update{
+					Service:    v2mService(u.Value.Service),
+					UpdateType: mojom.UpdateType_Found,
+				}
+			case discovery.UpdateLost:
+				mupdate = mojom.Update{
+					Service:    v2mService(u.Value.Service),
+					UpdateType: mojom.UpdateType_Lost,
+				}
+			}
+			if err := proxy.Update(mupdate); err != nil {
+				return
+			}
+		}
+	}()
+
+	return scanId, nil, nil
+}
+
+func (d *mdiscovery) StopScan(scanId uint32) (*mojom.Error, error) {
+	d.mu.Lock()
+	stop := d.activeScans[scanId]
+	delete(d.activeScans, scanId)
+	d.mu.Unlock()
+	if stop == nil {
+		return v2mError(verror.New(errInvalidScanId, d.ctx)), nil
+	}
+	stop()
+	return nil, nil
+}
+
+func (d *mdiscovery) Close() {
+	d.mu.Lock()
+	defer d.mu.Unlock()
+
+	for _, stop := range d.activeAdvs {
+		stop()
+	}
+	for _, stop := range d.activeScans {
+		stop()
+	}
+}
+
+// ediscovery always returns the given error.
+type ediscovery struct{ err error }
+
+func (d *ediscovery) StartAdvertising(mojom.Service, *[]string) (string, *mojom.Error, error) {
+	return "", v2mError(d.err), nil
+}
+func (d *ediscovery) StopAdvertising(string) (*mojom.Error, error) { return v2mError(d.err), nil }
+func (d *ediscovery) StartScan(string, mojom.ScanHandler_Pointer) (uint32, *mojom.Error, error) {
+	return 0, v2mError(d.err), nil
+}
+func (d *ediscovery) StopScan(uint32) (*mojom.Error, error) { return 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)
+	if err != nil {
+		return &ediscovery{err}
+	}
+
+	return &mdiscovery{
+		ctx:         ctx,
+		d:           d,
+		activeAdvs:  make(map[string]func()),
+		activeScans: make(map[uint32]func()),
+	}
 }
diff --git a/go/src/vanadium/discovery/internal/discovery_test.go b/go/src/vanadium/discovery/internal/discovery_test.go
index 2c64631..85829b3 100644
--- a/go/src/vanadium/discovery/internal/discovery_test.go
+++ b/go/src/vanadium/discovery/internal/discovery_test.go
@@ -5,136 +5,214 @@
 package internal
 
 import (
+	"errors"
 	"fmt"
-	"math/rand"
 	"reflect"
-	"strconv"
-	"sync"
+	"runtime"
 	"testing"
+	"time"
 
 	mojom "mojom/vanadium/discovery"
 
-	"v.io/v23/context"
 	"v.io/v23/discovery"
-	"v.io/v23/security"
 
 	idiscovery "v.io/x/ref/lib/discovery"
 	dfactory "v.io/x/ref/lib/discovery/factory"
+	"v.io/x/ref/lib/discovery/plugins/mock"
 	_ "v.io/x/ref/runtime/factories/generic"
-	vtest "v.io/x/ref/test"
+	"v.io/x/ref/test"
 )
 
-type mockDiscovery struct {
-	mu       sync.Mutex
-	trigger  *idiscovery.Trigger
-	id       int64
-	services map[int64]discovery.Service
-	// An item will be put in deleteCh when something has been deleted.
-	deleteCh chan struct{}
-}
-
-func (d *mockDiscovery) Advertise(ctx *context.T, s *discovery.Service, perms []security.BlessingPattern) (<-chan struct{}, error) {
-	if len(s.InstanceId) == 0 {
-		s.InstanceId = strconv.Itoa(rand.Int())
-	}
-	d.mu.Lock()
-	currId := d.id
-	d.services[currId] = *s
-	d.id++
-	d.mu.Unlock()
-	done := make(chan struct{})
-	stop := func() {
-		d.mu.Lock()
-		delete(d.services, currId)
-		d.mu.Unlock()
-		close(done)
-
-		go func() { d.deleteCh <- struct{}{} }()
-	}
-	d.trigger.Add(stop, ctx.Done())
-	return done, nil
-}
-
-func (*mockDiscovery) Scan(ctx *context.T, query string) (<-chan discovery.Update, error) {
-	return nil, nil
-}
-
-func (*mockDiscovery) Close() {}
-
-func compare(want discovery.Service, got mojom.Service) error {
-	mwant := v2mService(want)
-	if !reflect.DeepEqual(mwant, got) {
-		return fmt.Errorf("Got %#v want %#v", got, want)
-	}
-	return nil
-}
-
-func mkMojomService(instanceId, interfaceName string, attrs map[string]string, addrs []string) mojom.Service {
-	return mojom.Service{
-		InstanceId:    &instanceId,
-		InterfaceName: interfaceName,
-		Attrs:         &attrs,
-		Addrs:         addrs,
-	}
-}
-
-func TestAdvertising(t *testing.T) {
-	mock := &mockDiscovery{
-		trigger:  idiscovery.NewTrigger(),
-		services: map[int64]discovery.Service{},
-		deleteCh: make(chan struct{}),
-	}
-	dfactory.InjectDiscovery(mock)
-
-	ctx, shutdown := vtest.V23Init()
+func TestBasic(t *testing.T) {
+	ctx, shutdown := test.V23Init()
 	defer shutdown()
 
-	ds := NewDiscoveryService(ctx)
+	df, _ := idiscovery.NewFactory(ctx, mock.New())
+	dfactory.InjectFactory(df)
 
-	s1 := mkMojomService("s1", "v.io/discovery", map[string]string{"k1": "v1", "k2": "v2"}, []string{"addr1", "addr2"})
-	h1, id1, e1, e2 := ds.Advertise(s1, nil)
-	if e1 != nil || e2 != nil {
-		t.Fatalf("failed to start service: %v, %v", e1, e2)
-	}
-	if got, want := id1, "s1"; got != want {
-		t.Errorf("got instance id %s, but want %s", got, want)
-	}
-	if len(mock.services) != 1 {
-		t.Errorf("service missing in mock")
+	services := []discovery.Service{
+		{
+			InstanceId:    "123",
+			InterfaceName: "v.io/v23/a",
+			Attrs:         discovery.Attributes{"a1": "v1"},
+			Addrs:         []string{"/h1:123/x"},
+		},
+		{
+			InterfaceName: "v.io/v23/b",
+			Attrs:         discovery.Attributes{"b1": "v1"},
+			Addrs:         []string{"/h1:123/y"},
+		},
 	}
 
-	for _, service := range mock.services {
-		if err := compare(service, s1); err != nil {
-			t.Error(err)
+	d1 := NewDiscovery(ctx)
+
+	for i, service := range services {
+		instanceId, merr, err := d1.StartAdvertising(mkMojomService(service), nil)
+		if merr != nil || err != nil {
+			t.Fatalf("failed to advertise service: %v, %v", merr, err)
+		}
+		if len(instanceId) == 0 {
+			t.Errorf("service[%d]: got empty instance id", i)
+		}
+
+		if len(service.InstanceId) == 0 {
+			services[i].InstanceId = instanceId
+		} else if instanceId != service.InstanceId {
+			t.Errorf("service[%d]: got instance id %v, but wanted %v", i, instanceId, service.InstanceId)
 		}
 	}
 
-	s2 := mkMojomService("", "v.io/naming", map[string]string{"k1": "v1", "k2": "v2"}, []string{"addr3", "addr4"})
-	_, id2, e1, e2 := ds.Advertise(s2, nil)
-	if e1 != nil || e2 != nil {
-		t.Fatalf("failed to start service: %v, %v", e1, e2)
-	}
-	if len(id2) == 0 {
-		t.Error("empty instance id returned")
-	}
-	s2.InstanceId = &id2
-
-	ds.Stop(h1)
-	// Wait for the deletion to finish.
-	<-mock.deleteCh
-	if len(mock.services) != 1 {
-		t.Errorf("service should have been removed")
+	// Make sure none of advertisements are discoverable by the same discovery instance.
+	if err := scanAndMatch(d1, ""); err != nil {
+		t.Error(err)
 	}
 
-	for _, service := range mock.services {
-		if err := compare(service, s2); err != nil {
-			t.Error(err)
+	// Create a new discovery instance. All advertisements should be discovered with that.
+	d2 := NewDiscovery(ctx)
+
+	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/a"`, services[0]); err != nil {
+		t.Error(err)
+	}
+	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/b"`, services[1]); err != nil {
+		t.Error(err)
+	}
+	if err := scanAndMatch(d2, "", services...); err != nil {
+		t.Error(err)
+	}
+
+	// Open a new scan channel and consume expected advertisements first.
+	scanCh, scanStop, err := startScan(d2, `v.InterfaceName="v.io/v23/a"`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer scanStop()
+	update := <-scanCh
+	if !matchFound([]mojom.Update{update}, services[0]) {
+		t.Errorf("unexpected scan: %v", update)
+	}
+
+	// Make sure scan returns the lost advertisement when advertising is stopped.
+	d1.StopAdvertising(services[0].InstanceId)
+
+	update = <-scanCh
+	if !matchLost([]mojom.Update{update}, services[0]) {
+		t.Errorf("unexpected scan: %v", update)
+	}
+
+	// Also it shouldn't affect the other.
+	if err := scanAndMatch(d2, `v.InterfaceName="v.io/v23/b"`, services[1]); err != nil {
+		t.Error(err)
+	}
+
+	// Stop advertising the remaining one; Shouldn't discover any service.
+	d1.StopAdvertising(services[1].InstanceId)
+	if err := scanAndMatch(d2, ""); err != nil {
+		t.Error(err)
+	}
+}
+
+type mockScanHandler struct {
+	ch chan mojom.Update
+}
+
+func (m *mockScanHandler) Update(u mojom.Update) error {
+	m.ch <- u
+	return nil
+}
+func (m *mockScanHandler) Close_Proxy() { close(m.ch) }
+
+func startScan(d mojom.Discovery, query string) (<-chan mojom.Update, func(), error) {
+	ch := make(chan mojom.Update)
+	scanId, merr, err := d.(*mdiscovery).startScan(query, &mockScanHandler{ch})
+	if merr != nil {
+		return nil, nil, errors.New(merr.Msg)
+	}
+	if err != nil {
+		return nil, nil, err
+	}
+
+	stop := func() { d.StopScan(scanId) }
+	return ch, stop, nil
+}
+
+func scan(d mojom.Discovery, query string) ([]mojom.Update, error) {
+	ch, stop, err := startScan(d, query)
+	if err != nil {
+		return nil, err
+	}
+	defer stop()
+
+	var updates []mojom.Update
+	for {
+		select {
+		case update := <-ch:
+			updates = append(updates, update)
+		case <-time.After(5 * time.Millisecond):
+			return updates, nil
 		}
 	}
+}
 
-	ds.StopAll()
-	<-mock.deleteCh
-	if len(mock.services) != 0 {
-		t.Errorf("service should have been removed")
+func scanAndMatch(d mojom.Discovery, query string, wants ...discovery.Service) error {
+	const timeout = 3 * time.Second
+
+	var updates []mojom.Update
+	for now := time.Now(); time.Since(now) < timeout; {
+		runtime.Gosched()
+
+		var err error
+		updates, err = scan(d, query)
+		if err != nil {
+			return err
+		}
+		if matchFound(updates, wants...) {
+			return nil
+		}
 	}
+	return fmt.Errorf("Match failed; got %v, but wanted %v", updates, wants)
+}
+
+func match(updates []mojom.Update, updateType mojom.UpdateType, wants ...discovery.Service) bool {
+	for _, want := range wants {
+		matched := false
+		for i, update := range updates {
+			if update.UpdateType == updateType && reflect.DeepEqual(update.Service, mkMojomService(want)) {
+				updates = append(updates[:i], updates[i+1:]...)
+				matched = true
+				break
+			}
+		}
+		if !matched {
+			return false
+		}
+	}
+	return len(updates) == 0
+}
+
+func matchFound(updates []mojom.Update, wants ...discovery.Service) bool {
+	return match(updates, mojom.UpdateType_Found, wants...)
+}
+
+func matchLost(updates []mojom.Update, wants ...discovery.Service) bool {
+	return match(updates, mojom.UpdateType_Lost, wants...)
+}
+
+func mkMojomService(service discovery.Service) mojom.Service {
+	mservice := mojom.Service{
+		InstanceId:    &service.InstanceId,
+		InterfaceName: service.InterfaceName,
+		Addrs:         service.Addrs,
+	}
+	if len(service.InstanceName) > 0 {
+		mservice.InstanceName = &service.InstanceName
+	}
+	if len(service.Attrs) > 0 {
+		attrs := map[string]string(service.Attrs)
+		mservice.Attrs = &attrs
+	}
+	if len(service.Attachments) > 0 {
+		attachments := map[string][]byte(service.Attachments)
+		mservice.Attachments = &attachments
+	}
+	return mservice
 }
diff --git a/mojom/vanadium/discovery.mojom b/mojom/vanadium/discovery.mojom
index d638974..f9c5443 100644
--- a/mojom/vanadium/discovery.mojom
+++ b/mojom/vanadium/discovery.mojom
@@ -21,11 +21,14 @@
   // The addresses that the service is served on.
   // E.g., '/host:port/a/b/c'.
   array<string> Addrs;
+  // The service attachments.
+  // E.g., {'thumbnail': binary_data }.
+  map<string, array<uint8>>? Attachments;
 };
 
 enum UpdateType {
-	  found = 1,
-	  lost,
+  found = 1,
+  lost,
 };
 
 struct Update {
@@ -39,25 +42,21 @@
   string msg;
 };
 
-// Advertiser provides methods to do Vanadium Advertising.
-[ServiceName="v23::discovery::Advertiser"]
-interface Advertiser {
-  // Advertise advertises the service to be discovered by "Scanner" implementations.
-  // visibility is used to limit the principals that can see the advertisement. An
-  // empty set means that there are no restrictions on visibility (i.e, equivalent
-  // to []security.BlessingPattern{security.AllPrincipals}).
+// Discovery provides Vanadium discovery operations.
+[ServiceName="v23::discovery::Discovery"]
+interface Discovery {
+  // StartAdvertising advertises the service to be discovered by "Scanner"
+  // implementations. visibility is used to limit the principals that can see
+  // the advertisement. An empty set means that there are no restrictions on
+  // visibility (i.e, equivalent to []security.BlessingPattern{security.AllPrincipals}).
   //
   // It is an error to have simultaneously active advertisements for two identical
   // instances (service.InstanceUuid).
-  Advertise(Service service, array<string>? visibility) => (uint32 Handle, string instanceId, Error? Err);
+  StartAdvertising(Service service, array<string>? visibility) => (string instance_id, Error? err);
 
-  // Stop Stops the advertisement associated with the given handle.
-  Stop(uint32 h) => (Error? Err);
-};
+  // StopAdvertising stops the advertisement associated with the given instance id.
+  StopAdvertising(string instance_id) => (Error? Err);
 
-// Scanner provides methods to scan for Vanadium advertisements.
-[ServiceName="v23::discovery::Scanner"]
-interface Scanner {
   // Scan scans for services matching the query passed and calls ScanHandler with updates.
   //
   // The query is a WHERE expression of syncQL query against scanned services, where
@@ -71,14 +70,13 @@
   //
   // SyncQL tutorial at:
   //    https://github.com/vanadium/docs/blob/master/tutorials/syncql-tutorial.md
-  Scan(string query, ScanHandler scanHandler) => (uint32 Handle, Error? Err);
+  StartScan(string query, ScanHandler handler) => (uint32 scan_id, Error? err);
 
-  // StopScan stops the scanner associated weith the given handle.
-  Stop(uint32 h) => (Error? Err);
+  // StopScan stops the scanning associated with the given scan id.
+  StopScan(uint32 scan_id) => (Error? err);
 };
 
-// ScanHandler is used to pass updates about Services that are found/lost during
-// the scan.
+// ScanHandler is used to pass updates about services that are found/lost during the scan.
 [ServiceName="v23::discovery::ScanHandler"]
 interface ScanHandler {
   // Update will be called when a Service is found or lost.